diff options
| author | Gertjan van den Burg <gertjanvandenburg@gmail.com> | 2021-01-14 17:23:56 +0000 |
|---|---|---|
| committer | Gertjan van den Burg <gertjanvandenburg@gmail.com> | 2021-01-14 17:23:56 +0000 |
| commit | d49bf79e4b79b3bb3d9031c7fba4c21efc431548 (patch) | |
| tree | 5d2b35944af343f15ecb7dbd3e74f91a95ca2c3f | |
| parent | Update README (diff) | |
| parent | bump roxygen (diff) | |
| download | SyncRNG-d49bf79e4b79b3bb3d9031c7fba4c21efc431548.tar.gz SyncRNG-d49bf79e4b79b3bb3d9031c7fba4c21efc431548.zip | |
Merge branch 'R'
# Conflicts:
# .gitignore
# README.md
# new_R/src/syncrng.c
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | LICENSE | 340 | ||||
| -rw-r--r-- | NAMESPACE | 3 | ||||
| -rw-r--r-- | Python/SyncRNG.py | 48 | ||||
| -rw-r--r-- | README.md | 180 | ||||
| -rw-r--r-- | new_R/DESCRIPTION (renamed from DESCRIPTION) | 12 | ||||
| -rw-r--r-- | new_R/NAMESPACE | 7 | ||||
| -rw-r--r-- | new_R/NEWS.md | 4 | ||||
| -rw-r--r-- | new_R/R/SyncRNG.R (renamed from R/SyncRNG.R) | 9 | ||||
| -rw-r--r-- | new_R/R/syncrng-package.R | 50 | ||||
| -rw-r--r-- | new_R/cran-comments.md | 17 | ||||
| -rw-r--r-- | new_R/man/SyncRNG-class.Rd (renamed from man/SyncRNG-class.Rd) | 16 | ||||
| -rw-r--r-- | new_R/man/syncrng-package.Rd | 52 | ||||
| -rw-r--r-- | new_R/src/syncrng.c (renamed from src/syncrng.c) | 2 | ||||
| -rw-r--r-- | new_R/tests/testthat.R | 4 | ||||
| -rw-r--r-- | new_R/tests/testthat/first_1000_seed_0.txt (renamed from test/first_1000_seed_0.txt) | 0 | ||||
| -rw-r--r-- | new_R/tests/testthat/tests.R | 63 | ||||
| -rw-r--r-- | setup.py | 19 | ||||
| -rwxr-xr-x | test/run_tests.sh | 3 | ||||
| -rw-r--r-- | test/test.R | 43 | ||||
| -rw-r--r-- | test/test.py | 34 |
21 files changed, 269 insertions, 638 deletions
@@ -2,3 +2,4 @@ *.so *.o .Rproj.user +SyncRNG.Rproj diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8cdb845..0000000 --- a/LICENSE +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., <http://fsf.org/> - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. - diff --git a/NAMESPACE b/NAMESPACE deleted file mode 100644 index bb2ff1a..0000000 --- a/NAMESPACE +++ /dev/null @@ -1,3 +0,0 @@ -useDynLib(SyncRNG) -export(SyncRNG) -import(methods) diff --git a/Python/SyncRNG.py b/Python/SyncRNG.py deleted file mode 100644 index 0ab4c06..0000000 --- a/Python/SyncRNG.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Simple interface to SyncRNG. This file defines a SyncRNG object which can be -used to seed and pull numbers from the RNG. - -""" - -from __future__ import division - -from copy import deepcopy -from warnings import warn as _warn - -import syncrng - -class SyncRNG(object): - - def __init__(self, seed=0): - self.BPF = 32 - self.seed = seed - self.state = syncrng.seed(seed) - - def randi(self): - tmp = syncrng.rand(self.state) - self.state = tmp[:-1] - return(tmp[-1]) - - def rand(self): - return self.randi() * 2.3283064365387e-10 - - def randbelow(self, n): - maxsize = 1<<self.BPF - if n >= maxsize: - _warn("Underlying random generator does not supply \n" - "enough bits to choose from a population range this " - "large.\n") - return int(self.rand() * n) - rem = maxsize % n - limit = (maxsize - rem) / maxsize - r = self.rand() - while r >= limit: - r = self.rand() - return int(r*maxsize) % n - - def shuffle(self, x): - y = deepcopy(x) - for i in reversed(range(1, len(y))): - j = self.randbelow(i+1) - y[i], y[j] = y[j], y[i] - return y @@ -1,13 +1,14 @@ -# SyncRNG - +SyncRNG +======= A synchronized Tausworthe RNG usable in R and Python. -## Why? +Why? +==== -This program was created because it was desired to have the same random -numbers in both R and Python programs. Although both languages implement a -Mersenne-Twister RNG, the implementations are so different that it is not -possible to get the same random numbers with the same seed. +This program was created because I needed to have the same random numbers in +both R and Python. Although both languages implement a Mersenne-Twister RNG, +the implementations are so different that it is not possible to get the same +random numbers with the same seed. SyncRNG is a Tausworthe RNG implemented in ``syncrng.c``, and linked to both R and Python. Since both use the same underlying C code, the random numbers will @@ -16,61 +17,58 @@ be the same in both languages, provided the same seed is used. You can read more about my motivations for creating this [here](https://gertjanvandenburg.com/blog/syncrng/). -## Installation - -Installing the R package can be done through CRAN: - -``` -> install.packages('SyncRNG') -``` +How +=== -The Python package can be installed using pip: +First install the packages as stated under Installation. Then, in Python you +can do:: -``` -$ pip install syncrng -``` + from SyncRNG import SyncRNG -## Usage + s = SyncRNG(seed=123456) + for i in range(10): + print(s.randi()) -After installing the package, you can use the basic ``SyncRNG`` random number -generator. In Python you can do: +Similarly, after installing the R library you can do in R:: + library(SyncRNG) -```python ->>> from SyncRNG import SyncRNG ->>> s = SyncRNG(seed=123456) ->>> for i in range(10): ->>> print(s.randi()) -``` - -And in R you can use: - -```r -> library(SyncRNG) -> s <- SyncRNG(seed=123456) -> for (i in 1:10) { -> cat(s$randi(), '\n') -> } -``` + s <- SyncRNG(seed=123456) + for (i in 1:10) { + cat(s$randi(), '\n') + } You'll notice that the random numbers are indeed the same. -### R: User defined RNG +R - User defined RNG +-------------------- R allows the user to define a custom random number generator, which is then used for the common ``runif`` and ``rnorm`` functions in R. This has also been -implemented in SyncRNG as of version 1.3.0. To enable this, run: +implemented in SyncRNG as of version 1.3.0. To enable this, run:: + + library(SyncRNG) -```r -> library(SyncRNG) -> set.seed(123456, 'user', 'user') -> runif(10) -``` + set.seed(123456, 'user', 'user') + runif(10) These numbers are between [0, 1) and multiplying by ``2**32 - 1`` gives the same results as above. -### Functionality +Installation +============ + +Installing the R package can be done through CRAN:: + + install.packages('SyncRNG') + +The Python package can be installed using pip:: + + pip install syncrng + + +Usage +===== In both R and Python the following methods are available for the ``SyncRNG`` class: @@ -81,97 +79,9 @@ class: 3. ``randbelow(n)``: generate a random integer below a given integer ``n``. 4. ``shuffle(x)``: generate a permutation of a given list of numbers ``x``. -### Creating the same train/test splits - -A common use case for this package is to create the same train and test splits -in R and Python. Below are some code examples that illustrate how to do this. -Both assume you have a matrix ``X`` with `100` rows. - -In R: - -```r - -# This function creates a list with train and test indices for each fold -k.fold <- function(n, K, shuffle=TRUE, seed=0) -{ - idxs <- c(1:n) - if (shuffle) { - rng <- SyncRNG(seed=seed) - idxs <- rng$shuffle(idxs) - } - - # Determine fold sizes - fsizes <- c(1:K)*0 + floor(n / K) - mod <- n %% K - if (mod > 0) - fsizes[1:mod] <- fsizes[1:mod] + 1 - - out <- list(n=n, num.folds=K) - current <- 1 - for (f in 1:K) { - fs <- fsizes[f] - startidx <- current - stopidx <- current + fs - 1 - test.idx <- idxs[startidx:stopidx] - train.idx <- idxs[!(idxs %in% test.idx)] - out$testidxs[[f]] <- test.idx - out$trainidxs[[f]] <- train.idx - current <- stopidx - } - return(out) -} - -# Which you can use as follows -folds <- k.fold(nrow(X), K=10, shuffle=T, seed=123) -for (f in 1:folds$num.folds) { - X.train <- X[folds$trainidx[[f]], ] - X.test <- X[folds$testidx[[f]], ] - - # continue using X.train and X.test here -} -``` - -And in Python: - -```python -def k_fold(n, K, shuffle=True, seed=0): - """Generator for train and test indices""" - idxs = list(range(n)) - if shuffle: - rng = SyncRNG(seed=seed) - idxs = rng.shuffle(idxs) - - fsizes = [n // K]*K - mod = n % K - if mod > 0: - fsizes[:mod] = [x+1 for x in fsizes[:mod]] - - current = 0 - for fs in fsizes: - startidx = current - stopidx = current + fs - test_idx = idxs[startidx:stopidx] - train_idx = [x for x in idxs if not x in test_idx] - yield train_idx, test_idx - current = stopidx - -# Which you can use as follows -kf = k_fold(X.shape[0], K=3, shuffle=True, seed=123) -for trainidx, testidx in kf: - X_train = X[trainidx, :] - X_test = X[testidx, :] - - # continue using X_train and X_test here - -``` - -## Notes +Notes +===== The random numbers are uniformly distributed on ``[0, 2^32 - 1]``. -## Questions and Issues -If you have questions, comments, or suggestions about SyncRNG or you encounter -a problem, please open an issue [on -GitHub](https://github.com/GjjvdBurg/SyncRNG/). Please don't hesitate to -contact me, you're helping to make this project better for everyone! diff --git a/DESCRIPTION b/new_R/DESCRIPTION index ac0ee0c..141743a 100644 --- a/DESCRIPTION +++ b/new_R/DESCRIPTION @@ -1,11 +1,15 @@ Package: SyncRNG -Version: 1.0 -Date: 2015-07-31 +Version: 1.3.0 +Date: 2017-12-15 Title: A Synchronized Tausworthe RNG for R and Python Author: Gertjan van den Burg <gertjanvandenburg@gmail.com> Maintainer: Gertjan van den Burg <gertjanvandenburg@gmail.com> -Depends: R (>= 3.0.0) +Depends: + R (>= 3.0.0) Description: Random number generation designed for cross-language usage. -License: file LICENSE +License: GPL-2 Imports: methods +Suggests: + testthat +RoxygenNote: 7.1.1 diff --git a/new_R/NAMESPACE b/new_R/NAMESPACE new file mode 100644 index 0000000..052e9e8 --- /dev/null +++ b/new_R/NAMESPACE @@ -0,0 +1,7 @@ +# Generated by roxygen2: do not edit by hand + +export(SyncRNG) +exportClasses(SyncRNG) +import(methods) +importFrom(methods,new) +useDynLib(SyncRNG, .registration = TRUE) diff --git a/new_R/NEWS.md b/new_R/NEWS.md new file mode 100644 index 0000000..8b038d8 --- /dev/null +++ b/new_R/NEWS.md @@ -0,0 +1,4 @@ +# SyncRNG 1.3.0 + +* Allows using SyncRNG as a user-supplied random number generator in R. This + enables using the functions ``runif`` and ``rnorm``. diff --git a/R/SyncRNG.R b/new_R/R/SyncRNG.R index 84088b0..e7176b4 100644 --- a/R/SyncRNG.R +++ b/new_R/R/SyncRNG.R @@ -1,13 +1,20 @@ library(methods) #' A Reference Class for SyncRNG +#' +#' See \link{syncrng-package} for package documentation. #' #' @field seed The seed for the random number generator #' @field state The current state of the RNG, should not be modified by the #' user #' +#' @useDynLib SyncRNG, .registration = TRUE +#' @export SyncRNG +#' @exportClass SyncRNG +#' @importFrom methods new +#' #' @examples -#' s = SyncRNG(seed=123456) +#' s <- SyncRNG(seed=123456) #' for (i in 1:10) #' cat(s$randi(), '\n') #' diff --git a/new_R/R/syncrng-package.R b/new_R/R/syncrng-package.R new file mode 100644 index 0000000..949401d --- /dev/null +++ b/new_R/R/syncrng-package.R @@ -0,0 +1,50 @@ +#' @title SyncRNG - Synchronized Random Numbers in R and Python +#' +#' @description +#' The SyncRNG package provides a random number generator implemented in C and +#' linked to both R and Python. This way, you can generate the same random +#' number sequence in both languages by using the same seed. +#' +#' The package implements a Tausworthe LSFR RNG (more details at +#' \url{https://gertjanvandenburg.com/blog/syncrng/}). This is a very fast +#' pseudo-random number generator. +#' +#' @section Usage: +#' There are two ways to use this package in R. It can be used as a reference +#' class, where a SyncRNG object is used to keep the state of the generator and +#' numbers are generated using the object methods. It can also be used as a +#' user-defined random number generator using the strategy outlined in +#' .Random.user. See the examples section below. +#' +#' @author +#' Gerrit J.J. van den Burg\cr +#' Maintainer: Gerrit J.J. van den Burg <gertjanvandenburg@gmail.com> +#' +#' @references +#' URL: \url{https://github.com/GjjvdBurg/SyncRNG} +#' +#' @examples +#' library(SyncRNG) +#' +#' # As user defined RNG: +#' +#' set.seed(0, 'user', 'user') +#' runif(2) +#' # [1] 3.666952e-04 6.257184e-05 +#' set.seed(0, 'user', 'user') +#' rnorm(2) +#' # [1] 0.01006027 0.42889422 +#' +#' # As class: +#' +#' s <- SyncRNG(seed=0) +#' s$rand() +#' # [1] 0.0003666952 +#' s$rand() +#' # [1] 6.257184e-05 +#' +#' @name syncrng-package +#' @docType package +#' @import methods +NULL +#>NULL diff --git a/new_R/cran-comments.md b/new_R/cran-comments.md new file mode 100644 index 0000000..4f984f0 --- /dev/null +++ b/new_R/cran-comments.md @@ -0,0 +1,17 @@ +## Test environments +* local Arch Linux install, R 3.4.3 +* win-builder (devel and release) + +## R CMD check results +There were no ERRORs or WARNINGs. + +There was 1 NOTE: + +* checking CRAN incoming feasibility ... NOTE +Maintainer: 'Gertjan van den Burg <gertjanvandenburg@gmail.com>' + +Possibly mis-spelled words in DESCRIPTION: + RNG (4:34) + Tausworthe (4:23) + + RNG is a common abbreviation and Tausworthe is a name. diff --git a/man/SyncRNG-class.Rd b/new_R/man/SyncRNG-class.Rd index 599b540..92316da 100644 --- a/man/SyncRNG-class.Rd +++ b/new_R/man/SyncRNG-class.Rd @@ -1,21 +1,22 @@ -% Generated by roxygen2 (4.1.1): do not edit by hand +% Generated by roxygen2: do not edit by hand % Please edit documentation in R/SyncRNG.R \docType{class} \name{SyncRNG-class} -\alias{SyncRNG} \alias{SyncRNG-class} +\alias{SyncRNG} \title{A Reference Class for SyncRNG} \description{ -A Reference Class for SyncRNG +See \link{syncrng-package} for package documentation. } \section{Fields}{ \describe{ \item{\code{seed}}{The seed for the random number generator} -\item{\code{state}}{The current state of the RNG, should not be modified by the +\item{\code{state}}{The current state of the RNG, should not be modified by the user} }} + \section{Methods}{ \describe{ @@ -29,9 +30,10 @@ user} \item{\code{shuffle(x)}}{Randomly shuffle a provided array of values} }} + \examples{ -s = SyncRNG(seed=123456) +s <- SyncRNG(seed=123456) for (i in 1:10) - cat(s$randi(), '\\n') -} + cat(s$randi(), '\n') +} diff --git a/new_R/man/syncrng-package.Rd b/new_R/man/syncrng-package.Rd new file mode 100644 index 0000000..f8cfe02 --- /dev/null +++ b/new_R/man/syncrng-package.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/syncrng-package.R +\docType{package} +\name{syncrng-package} +\alias{syncrng-package} +\title{SyncRNG - Synchronized Random Numbers in R and Python} +\description{ +The SyncRNG package provides a random number generator implemented in C and +linked to both R and Python. This way, you can generate the same random +number sequence in both languages by using the same seed. + +The package implements a Tausworthe LSFR RNG (more details at +\url{https://gertjanvandenburg.com/blog/syncrng/}). This is a very fast +pseudo-random number generator. +} +\section{Usage}{ + +There are two ways to use this package in R. It can be used as a reference +class, where a SyncRNG object is used to keep the state of the generator and +numbers are generated using the object methods. It can also be used as a +user-defined random number generator using the strategy outlined in +.Random.user. See the examples section below. +} + +\examples{ +library(SyncRNG) + +# As user defined RNG: + +set.seed(0, 'user', 'user') +runif(2) +# [1] 3.666952e-04 6.257184e-05 +set.seed(0, 'user', 'user') +rnorm(2) +# [1] 0.01006027 0.42889422 + +# As class: + +s <- SyncRNG(seed=0) +s$rand() +# [1] 0.0003666952 +s$rand() +# [1] 6.257184e-05 + +} +\references{ +URL: \url{https://github.com/GjjvdBurg/SyncRNG} +} +\author{ +Gerrit J.J. van den Burg\cr +Maintainer: Gerrit J.J. van den Burg <gertjanvandenburg@gmail.com> +} diff --git a/src/syncrng.c b/new_R/src/syncrng.c index 3cc77fa..71fe58e 100644 --- a/src/syncrng.c +++ b/new_R/src/syncrng.c @@ -298,7 +298,7 @@ SEXP R_syncrng_rand(SEXP state) */ static uint32_t global_R_seed; -static uint32_t global_R_nseed = 1; +static int global_R_nseed = 1; static double global_R_result_uniform; static double global_R_result_normal; static uint64_t *global_R_state = NULL; diff --git a/new_R/tests/testthat.R b/new_R/tests/testthat.R new file mode 100644 index 0000000..b1f5cc8 --- /dev/null +++ b/new_R/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(SyncRNG) + +test_check("SyncRNG") diff --git a/test/first_1000_seed_0.txt b/new_R/tests/testthat/first_1000_seed_0.txt index 50aef45..50aef45 100644 --- a/test/first_1000_seed_0.txt +++ b/new_R/tests/testthat/first_1000_seed_0.txt diff --git a/new_R/tests/testthat/tests.R b/new_R/tests/testthat/tests.R new file mode 100644 index 0000000..59dc004 --- /dev/null +++ b/new_R/tests/testthat/tests.R @@ -0,0 +1,63 @@ +library(SyncRNG) +context("SyncRNG unit tests") + +test_that("test_randi", { + s <- SyncRNG(seed=123456) + expect_equal(s$randi(), 959852049) + expect_equal(s$randi(), 2314333085) + expect_equal(s$randi(), 2255782734) + expect_equal(s$randi(), 2921461239) + expect_equal(s$randi(), 1024197102) +}) + +test_that("test_rand", { + s <- SyncRNG(seed=123456) + expect_equal(s$rand(), 959852049 /(2**32)) + expect_equal(s$rand(), 2314333085/(2**32)) + expect_equal(s$rand(), 2255782734/(2**32)) + expect_equal(s$rand(), 2921461239/(2**32)) + expect_equal(s$rand(), 1024197102/(2**32)) +}) + +test_that("test_randbelow", { + s <- SyncRNG(seed=123456) + expect_equal(s$randbelow(5), 4) + expect_equal(s$randbelow(5), 0) + expect_equal(s$randbelow(5), 4) + expect_equal(s$randbelow(5), 4) + expect_equal(s$randbelow(5), 2) +}) + +test_that("test_shuffle", { + s <- SyncRNG(seed=123456) + x <- c(1, 2, 3, 4, 5) + y <- s$shuffle(x) + expect_equal(y, c(3, 4, 1, 2, 5)) +}) + +test_that("test_first_1000", { + s <- SyncRNG(seed=0) + fileName <- "./first_1000_seed_0.txt" + conn <- file(fileName, open="r") + linn <- readLines(conn) + for (i in 1:length(linn)) { + exp <- as.numeric(linn[i]) + expect_equal(exp, s$randi()) + } + close(conn) +}) + +printf <- function(...) invisible(cat(sprintf(...))); + +test_that("test_first_1000_unif", { + set.seed(0, 'user', 'user') + fileName <- "./first_1000_seed_0.txt" + conn <- file(fileName, open="r") + linn <- readLines(conn) + for (i in 1:length(linn)) { + exp <- as.numeric(linn[i]) + u <- as.numeric(runif(1)*(2**32 - 1)) + expect_equal(exp, u) + } + close(conn) +}) diff --git a/setup.py b/setup.py deleted file mode 100644 index 985c1eb..0000000 --- a/setup.py +++ /dev/null @@ -1,19 +0,0 @@ - -from distutils.core import setup, Extension - -setup( - name='SyncRNG', - author='Gertjan van den Burg', - version='1.0', - description='A synchronized Tausworthe RNG for Python and R', - license='GPL v2', - package_dir={'': 'Python'}, - packages=[''], - ext_modules=[ - Extension( - "syncrng", - define_macros=[('TARGETPYTHON', '1')], - sources=["src/syncrng.c"] - ) - ], - ) diff --git a/test/run_tests.sh b/test/run_tests.sh deleted file mode 100755 index 4c7c5da..0000000 --- a/test/run_tests.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -paste <(python test.py) <(Rscript test.R) diff --git a/test/test.R b/test/test.R deleted file mode 100644 index 0937f52..0000000 --- a/test/test.R +++ /dev/null @@ -1,43 +0,0 @@ -library(SyncRNG) - -test.randi <- function() -{ - s <- SyncRNG(seed=123456) - for (i in 1:5) - cat(s$randi(), '\n') -} - -test.rand <- function() -{ - s <- SyncRNG(seed=123456) - for (i in 1:5) - cat(sprintf('%.16f\n', s$rand())) -} - -test.randbelow <- function() -{ - s <- SyncRNG(seed=123456) - for (i in 1:5) - cat(s$randbelow(i), '\n') -} - -test.shuffle <- function() -{ - s <- SyncRNG(seed=123456) - x <- c(1:5) - for (i in 1:5) { - y <- s$shuffle(x) - x <- y - cat('[', paste(y, collapse=', '), ']\n', sep='') - } -} - -main <- function() -{ - test.randi() - test.rand() - test.randbelow() - test.shuffle() -} - -main() diff --git a/test/test.py b/test/test.py deleted file mode 100644 index 7d3f9f5..0000000 --- a/test/test.py +++ /dev/null @@ -1,34 +0,0 @@ - -from SyncRNG import SyncRNG - -def test_randi(): - s = SyncRNG(seed=123456) - for i in range(5): - print(s.randi()) - -def test_rand(): - s = SyncRNG(seed=123456) - for i in range(5): - print('%.16f' % s.rand()) - -def test_randbelow(): - s = SyncRNG(seed=123456) - for i in range(5): - print(s.randbelow(i+1)) - -def test_shuffle(): - s = SyncRNG(seed=123456) - x = [1, 2, 3, 4, 5] - for i in range(5): - y = s.shuffle(x) - x = y - print(y) - -def main(): - test_randi() - test_rand() - test_randbelow() - test_shuffle() - -if __name__ == '__main__': - main() |
