├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── doc ├── html │ ├── index.html │ ├── javascripts │ │ ├── jquery.tocLight.js │ │ └── scale.fix.js │ ├── randomkit.html │ └── stylesheets │ │ ├── pygment_trac.css │ │ └── styles.css ├── intro.md └── src │ ├── .gitignore │ ├── Gemfile │ ├── README.DOC.markdown │ ├── _config.yml │ ├── _layouts │ └── doc.html │ ├── _plugins │ └── fancytoc.rb │ ├── index.markdown │ ├── javascripts │ ├── jquery.tocLight.js │ └── scale.fix.js │ ├── randomkit.html │ └── stylesheets │ ├── pygment_trac.css │ └── styles.css ├── luasrc ├── CMakeLists.txt ├── generateDocsAndTests.py ├── generateMdDocs.py ├── init.lua ├── nonC.lua ├── tests │ ├── testCalls.lua │ ├── testMultipleRequire.lua │ ├── testMultivariateValues.lua │ ├── testSeed.lua │ ├── testValues.lua │ ├── testWrap.lua │ └── testWrongState.lua └── wrapC.lua ├── randomkit ├── CMakeLists.txt ├── README ├── distributions.c ├── distributions.h ├── randomkit.c └── randomkit.h └── rocks ├── randomkit-0-0.rockspec ├── randomkit-0-1.rockspec └── randomkit-scm-1.rockspec /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - gcc 4 | - clang 5 | cache: 6 | directories: 7 | - $HOME/OpenBlasInstall 8 | sudo: false 9 | env: 10 | - TORCH_LUA_VERSION=LUAJIT21 11 | addons: 12 | apt: 13 | packages: 14 | - cmake 15 | - gfortran 16 | - gcc-multilib 17 | - gfortran-multilib 18 | - liblapack-dev 19 | - build-essential 20 | - gcc 21 | - g++ 22 | - curl 23 | - cmake 24 | - libreadline-dev 25 | - git-core 26 | - libqt4-core 27 | - libqt4-gui 28 | - libqt4-dev 29 | - libjpeg-dev 30 | - libpng-dev 31 | - ncurses-dev 32 | - imagemagick 33 | - libzmq3-dev 34 | - gfortran 35 | - unzip 36 | - gnuplot 37 | - gnuplot-x11 38 | before_script: 39 | - export ROOT_TRAVIS_DIR=$(pwd) 40 | - export INSTALL_PREFIX=~/torch/install 41 | - ls $HOME/OpenBlasInstall/lib || (cd /tmp/ && git clone https://github.com/xianyi/OpenBLAS.git -b master && cd OpenBLAS && (make NO_AFFINITY=1 -j$(getconf _NPROCESSORS_ONLN) 2>/dev/null >/dev/null) && make PREFIX=$HOME/OpenBlasInstall install) 42 | - git clone https://github.com/torch/distro.git ~/torch --recursive 43 | - cd ~/torch && git submodule update --init --recursive 44 | - mkdir build && cd build 45 | - export CMAKE_LIBRARY_PATH=$HOME/OpenBlasInstall/include:$HOME/OpenBlasInstall/lib:$CMAKE_LIBRARY_PATH 46 | - cmake .. -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" -DCMAKE_BUILD_TYPE=Release -DWITH_${TORCH_LUA_VERSION}=ON 47 | - make && make install 48 | - cd $ROOT_TRAVIS_DIR 49 | - export LD_LIBRARY_PATH=${INSTALL_PREFIX}/lib:$LD_LIBRARY_PATH 50 | script: 51 | - ${INSTALL_PREFIX}/bin/luarocks make rocks/randomkit-scm-1.rockspec 52 | - export PATH=${INSTALL_PREFIX}/bin:$PATH 53 | - export TESTLUA=$(which luajit lua | head -n 1) 54 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testCalls.lua 55 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testMultipleRequire.lua 56 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testMultivariateValues.lua 57 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testSeed.lua 58 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testValues.lua 59 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testWrap.lua 60 | - ${TESTLUA} -ltorch -ltotem -lrandomkit luasrc/tests/testWrongState.lua 61 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR) 2 | CMAKE_POLICY(VERSION 2.6) 3 | FIND_PACKAGE(Torch REQUIRED) 4 | 5 | # libcephes compilation and installation is in its own subdirectory 6 | ADD_SUBDIRECTORY("randomkit") 7 | ADD_SUBDIRECTORY("luasrc") 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Want to contribute? Great! First, read this page (including the small print at the end). 2 | 3 | ### Before you contribute 4 | Before we can use your code, you must sign the 5 | [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) 6 | (CLA), which you can do online. The CLA is necessary mainly because you own the 7 | copyright to your changes, even after your contribution becomes part of our 8 | codebase, so we need your permission to use and distribute your code. We also 9 | need to be sure of various other things—for instance that you'll tell us if you 10 | know that your code infringes on other people's patents. You don't have to sign 11 | the CLA until after you've submitted your code for review and a member has 12 | approved it, but you must do it before we can put your code into our codebase. 13 | Before you start working on a larger contribution, you should get in touch with 14 | us first through the issue tracker with your idea so that we can help out and 15 | possibly guide you. Coordinating up front makes it much easier to avoid 16 | frustration later on. 17 | 18 | ### Code reviews 19 | All submissions, including submissions by project members, require review. We 20 | use Github pull requests for this purpose. 21 | 22 | ### The small print 23 | Contributions made by corporations are covered by a different agreement than 24 | the one above, the Software Grant and Corporate Contributor License Agreement. 25 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Julien Cornebise and Daniel Horgan 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the organization nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /doc/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Randomkit RNG for Torch 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 |
18 | 187 |
188 |

Randomkit random number generators, wrapped for Torch

189 | 190 |

Provides and wraps the random nnumber generators the Randomkit library, copied from Numpy

191 | 192 |

Example

193 | 194 |

Single sample

195 | 196 |

You can call any of the wrapped functions with just the distribution's parameters to generate a single sample and return a number:

197 |
require 'randomkit'
198 | randomkit.poisson(5)
199 | 
200 |

Multiple samples from one distribution

201 | 202 |

Often, you might want to generate many samples identically distributed. Simply pass as a first argument a tensor of the proper dimension, into which the samples will be stored:

203 |
x = torch.Tensor(10000)
204 | randomkit.poisson(x, 5)
205 | 
206 |

The sampler returns the tensor, so you can shorten the above in:

207 |
x = randomkit.poisson(torch.Tensor(10000), 5)
208 | 
209 |

Multiple samples from multiple distributions

210 | 211 |

Finally, you might want to generate many samples, each from a distribution with different parameters. This is achieved by passing a Tensor as the parameter of the distribution:

212 |
many_lambda = torch.Tensor{5, 3, 40, 60}
213 | x = randomkit.poisson(many_lambda)
214 | 
215 |

Of course, this can be combined with passing a result Tensor as an optional first element, to re-use memory and avoid creaating a new Tensor at each call:

216 |
many_lambda = torch.Tensor{5, 3, 40, 60}
217 | x = torch.Tensor(many_lambda:size())
218 | randomkit.poisson(x, many_lambda)
219 | 
220 |

Note: in the latter case, the size of the result Tensor must correspond to the size of the parameter tensor -- we do not resize the result tensor automatically, yet:

221 | 222 |

Getting/setting the seed and the state

223 | 224 |

Randomkit is transparently integrated with Torch's random stream: just use torch.manualSeed(seed), torch.getRNGState(), and torch.setRNGState(state) as usual. 225 | Specifying an (optional) torch.Generator instance as the first argument will only influence the state of that genereator, leaving the state of randomkit unchanged.

226 | 227 |

Installation

228 | 229 |

From a terminal:

230 |
torch-rocks install randomkit
231 | 
232 |

List of Randomkit generators

233 | 234 |

See this extensive automatically extracted doc, built from Numpy's docstrings.

235 | 236 |

Beta

237 | 238 |

Binomial

239 | 240 |

Bytes

241 | 242 |

Chisquare

243 | 244 |

Double

245 | 246 |

Exponential

247 | 248 |

F

249 | 250 |

Gamma

251 | 252 |

Gauss

253 | 254 |

Geometric

255 | 256 |

Gumbel

257 | 258 |

Hypergeometric

259 | 260 |

Interval

261 | 262 |

Laplace

263 | 264 |

Logistic

265 | 266 |

Lognormal

267 | 268 |

Logseries

269 | 270 |

Long

271 | 272 |

Negative binomial

273 | 274 |

Noncentral chisquare

275 | 276 |

Noncentral F

277 | 278 |

Normal

279 | 280 |

Pareto

281 | 282 |

Poisson

283 | 284 |

Power

285 | 286 |

Randint

287 | 288 |

Random

289 | 290 |

Random sample

291 | 292 |

Rayleigh

293 | 294 |

Standard cauchy

295 | 296 |

Standard exponential

297 | 298 |

Standard gamma

299 | 300 |

Standard normal

301 | 302 |

Standard t

303 | 304 |

Triangular

305 | 306 |

Ulong

307 | 308 |

Uniform

309 | 310 |

Vonmises

311 | 312 |

Wald

313 | 314 |

Weibull

315 | 316 |

Zipf

317 | 318 |

Unit Tests

319 | 320 |

Last but not least, the unit tests are in the folder 321 | luasrc/tests. You can run them from your local clone of the repostiory with:

322 |
git clone https://www.github.com/jucor/torch-randomkit
323 | find torch-randomkit/luasrc/tests -name "test*lua" -exec torch {} \;
324 | 
325 |

Those tests will soone be automatically installed with the package, once I sort out a bit of CMake resistance.

326 | 327 |

Direct access to FFI

328 | 329 |

randomkit.ffi.*

330 | 331 |

Functions directly accessible at the top of the randomkit table are Lua wrappers to the actual C functions from Randomkit, with extra error checking. If, for any reason, you want to get rid of this error checking and of a possible overhead, the FFI-wrapper functions can be called directly via randomkit.ffi.myfunction() instead of randomkit.myfunction().

332 | 333 |
334 |
335 | 336 | 337 | 338 | -------------------------------------------------------------------------------- /doc/html/javascripts/scale.fix.js: -------------------------------------------------------------------------------- 1 | var metas = document.getElementsByTagName('meta'); 2 | var i; 3 | if (navigator.userAgent.match(/iPhone/i)) { 4 | for (i=0; i 2 | 3 | 4 | 5 | {{ page.title }} 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 |
18 | 21 |
22 | {{ content }} 23 |
24 |
25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /doc/src/_plugins/fancytoc.rb: -------------------------------------------------------------------------------- 1 | module Jekyll 2 | module FancyToCFilter 3 | def fancytoc(input) 4 | converter = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC) 5 | converter.render(input) 6 | end 7 | end 8 | end 9 | 10 | Liquid::Template.register_filter(Jekyll::FancyToCFilter) 11 | -------------------------------------------------------------------------------- /doc/src/index.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: Randomkit RNG for Torch 3 | layout: doc 4 | --- 5 | 6 | #Randomkit random number generators, wrapped for Torch 7 | 8 | Provides and wraps the random nnumber generators the [Randomkit library](), copied from [Numpy]() 9 | 10 | ##Example 11 | 12 | ###Single sample 13 | 14 | You can call any of the wrapped functions with just the distribution's parameters to generate a single sample and return a number: 15 | 16 | ```lua 17 | require 'randomkit' 18 | randomkit.poisson(5) 19 | ``` 20 | 21 | ###Multiple samples from one distribution 22 | 23 | Often, you might want to generate many samples identically distributed. Simply pass as a first argument a tensor of the proper dimension, into which the samples will be stored: 24 | 25 | ```lua 26 | x = torch.Tensor(10000) 27 | randomkit.poisson(x, 5) 28 | ``` 29 | 30 | The sampler returns the tensor, so you can shorten the above in: 31 | 32 | ```lua 33 | x = randomkit.poisson(torch.Tensor(10000), 5) 34 | ``` 35 | 36 | ###Multiple samples from multiple distributions 37 | 38 | Finally, you might want to generate many samples, each from a distribution with different parameters. This is achieved by passing a Tensor as the parameter of the distribution: 39 | 40 | ```lua 41 | many_lambda = torch.Tensor{5, 3, 40, 60} 42 | x = randomkit.poisson(many_lambda) 43 | ``` 44 | 45 | Of course, this can be combined with passing a result Tensor as an optional first element, to re-use memory and avoid creaating a new Tensor at each call: 46 | 47 | ```lua 48 | many_lambda = torch.Tensor{5, 3, 40, 60} 49 | x = torch.Tensor(many_lambda:size()) 50 | randomkit.poisson(x, many_lambda) 51 | ``` 52 | 53 | **Note:** in the latter case, the size of the result Tensor must correspond to the size of the parameter tensor -- we do not resize the result tensor automatically, yet: 54 | 55 | ###Getting/setting the seed and the state 56 | 57 | Randomkit is transparently integrated with Torch's random stream: just use `torch.manualSeed(seed)`, `torch.getRNGState()`, and `torch.setRNGState(state)` as usual. 58 | Specifying an (optional) torch.Generator instance as the first argument will only influence the state of that genereator, leaving the state of randomkit unchanged. 59 | 60 | ##Installation 61 | 62 | From a terminal: 63 | 64 | ```bash 65 | torch-rocks install randomkit 66 | ``` 67 | 68 | ##List of Randomkit generators 69 | 70 | See this **[extensive automatically extracted doc](randomkit.html)**, built from Numpy's docstrings. 71 | 72 | ###[Beta](randomkit.html#beta) 73 | ###[Binomial](randomkit.html#binomial) 74 | ###[Bytes](randomkit.html#bytes) 75 | ###[Chisquare](randomkit.html#chisquare) 76 | ###[Double](randomkit.html#double) 77 | ###[Exponential](randomkit.html#exponential) 78 | ###[F](randomkit.html#f) 79 | ###[Gamma](randomkit.html#gamma) 80 | ###[Gauss](randomkit.html#gauss) 81 | ###[Geometric](randomkit.html#geometric) 82 | ###[Gumbel](randomkit.html#gumbel) 83 | ###[Hypergeometric](randomkit.html#hypergeometric) 84 | ###[Interval](randomkit.html#interval) 85 | ###[Laplace](randomkit.html#laplace) 86 | ###[Logistic](randomkit.html#logistic) 87 | ###[Lognormal](randomkit.html#lognormal) 88 | ###[Logseries](randomkit.html#logseries) 89 | ###[Long](randomkit.html#long) 90 | ###[Negative binomial](randomkit.html#negative_binomial) 91 | ###[Noncentral chisquare](randomkit.html#noncentral_chisquare) 92 | ###[Noncentral F](randomkit.html#noncentral_f) 93 | ###[Normal](randomkit.html#normal) 94 | ###[Pareto](randomkit.html#pareto) 95 | ###[Poisson](randomkit.html#poisson) 96 | ###[Power](randomkit.html#power) 97 | ###[Randint](randomkit.html#randint) 98 | ###[Random](randomkit.html#random) 99 | ###[Random sample](randomkit.html#random_sample) 100 | ###[Rayleigh](randomkit.html#rayleigh) 101 | ###[Standard cauchy](randomkit.html#standard_cauchy) 102 | ###[Standard exponential](randomkit.html#standard_exponential) 103 | ###[Standard gamma](randomkit.html#standard_gamma) 104 | ###[Standard normal](randomkit.html#standard_normal) 105 | ###[Standard t](randomkit.html#standard_t) 106 | ###[Triangular](randomkit.html#triangular) 107 | ###[Ulong](randomkit.html#ulong) 108 | ###[Uniform](randomkit.html#uniform) 109 | ###[Vonmises](randomkit.html#vonmises) 110 | ###[Wald](randomkit.html#wald) 111 | ###[Weibull](randomkit.html#weibull) 112 | ###[Zipf](randomkit.html#zipf) 113 | 114 | ##Unit Tests 115 | 116 | Last but not least, the unit tests are in the folder 117 | [`luasrc/tests`](https://github.com/jucor/torch-randomkit/tree/master/luasrc/tests). You can run them from your local clone of the repostiory with: 118 | 119 | ```bash 120 | git clone https://www.github.com/jucor/torch-randomkit 121 | find torch-randomkit/luasrc/tests -name "test*lua" -exec torch {} \; 122 | ``` 123 | 124 | Those tests will soone be automatically installed with the package, once I sort out a bit of CMake resistance. 125 | 126 | ##Direct access to FFI 127 | 128 | ###randomkit.ffi.* 129 | 130 | Functions directly accessible at the top of the `randomkit` table are Lua wrappers to the actual C functions from Randomkit, with extra error checking. If, for any reason, you want to get rid of this error checking and of a possible overhead, the FFI-wrapper functions can be called directly via `randomkit.ffi.myfunction()` instead of `randomkit.myfunction()`. 131 | 132 | -------------------------------------------------------------------------------- /doc/src/javascripts/jquery.tocLight.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | jekyll-toc-generator/js/jquery.tocLight.js at master · dafi/jekyll-toc-generator · GitHub 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | 81 | 82 |
83 | Sign up 84 | 85 |
86 | 87 |
88 | 89 | 95 |
96 | 97 | 104 | 105 | 106 | 107 |
108 | 109 | This repository 110 | 111 | 112 |
113 |
114 | 115 |
116 | 117 | 118 |
This repository
119 |
120 | 121 |
122 | 123 | 124 |
All repositories
125 |
126 | 127 |
128 |
129 |
130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 |
139 |
140 | 141 |
142 |
143 | 144 | 145 | 146 | 147 | 148 |
149 | 150 |
151 |
152 | 153 | 154 | 180 | 181 |

182 | public 183 | 184 | 185 | 186 | 187 | / 188 | jekyll-toc-generator 189 | 190 | 191 | Octocat-spinner-32 192 | 193 | 194 |

195 |
196 |
197 | 198 |
199 | 200 |
201 | 202 |
203 | 204 | 205 |
206 |
207 | 229 |
230 | 250 | 251 | 252 |
253 |
254 | 255 |
256 | 257 | 258 | 259 | 260 |
263 |

HTTPS clone URL

264 |
265 | 267 | 268 | 269 |
270 |
271 | 272 | 273 | 274 |
277 |

Subversion checkout URL

278 |
279 | 281 | 282 | 283 |
284 |
285 | 286 | 287 |

You can clone with 288 | HTTPS, 289 | or Subversion. 290 | 291 | 292 | 293 | 294 | 295 |

296 | 297 | 298 | 299 | 303 | 304 | Download ZIP 305 | 306 |
307 |
308 | 309 |
310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 |
320 | 321 | 322 | 323 |
324 | 328 | 329 | branch: 330 | master 331 | 332 | 333 |
334 | 335 |
336 |
337 | Switch branches/tags 338 | 339 |
340 | 341 |
342 |
343 | 344 |
345 |
346 | 354 |
355 |
356 | 357 |
358 | 359 |
360 | 361 | 362 |
363 | 364 | master 370 |
371 |
372 | 373 |
Nothing to show
374 |
375 | 376 |
377 |
378 | 379 | 380 |
381 | 382 |
Nothing to show
383 |
384 | 385 |
386 |
387 |
388 | 389 | 392 |
393 | 394 | 395 | 396 |
397 | 398 | 399 | 400 | 403 | 404 |
405 |

1 contributor

406 | 407 |
408 | 417 |
418 | 419 |
420 |
421 |
422 |
423 | 424 | file 425 | 58 lines (51 sloc) 426 | 1.688 kb 427 |
428 |
429 |
430 | Edit 432 | Raw 433 | Blame 434 | History 435 |
436 | 438 | Delete 439 | 440 |
441 | 442 |
443 |
444 | 445 | 446 | 506 | 509 | 510 |
447 | 1 448 | 2 449 | 3 450 | 4 451 | 5 452 | 6 453 | 7 454 | 8 455 | 9 456 | 10 457 | 11 458 | 12 459 | 13 460 | 14 461 | 15 462 | 16 463 | 17 464 | 18 465 | 19 466 | 20 467 | 21 468 | 22 469 | 23 470 | 24 471 | 25 472 | 26 473 | 27 474 | 28 475 | 29 476 | 30 477 | 31 478 | 32 479 | 33 480 | 34 481 | 35 482 | 36 483 | 37 484 | 38 485 | 39 486 | 40 487 | 41 488 | 42 489 | 43 490 | 44 491 | 45 492 | 46 493 | 47 494 | 48 495 | 49 496 | 50 497 | 51 498 | 52 499 | 53 500 | 54 501 | 55 502 | 56 503 | 57 504 | 505 | 507 |
/*
* jQuery Table of Content Generator Support for Jekyll v1.0
*
* https://github.com/dafi/jekyll-tocmd-generator
* Examples and documentation at: https://github.com/dafi/jekyll-tocmd-generator
*
* Requires: jQuery v1.7+
*
* Copyright (c) 2013 Davide Ficano
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
(function($) {
    $.toc = {};
    $.toc.clickHideButton = function(settings) {
        var config = {
            saveShowStatus: false,
            hideText: 'hide',
            showText: 'show'};

        if (settings) {
            $.extend(config, settings);
        }

        $('#toctogglelink').click(function() {
            var ul = $($('#toc ul')[0]);
            
            if (ul.is(':visible')) {
                ul.hide();
                $(this).text(config.showText);
                if (config.saveShowStatus) {
                    $.cookie('toc-hide', '1', { expires: 365, path: '/' });
                }
                $('#toc').addClass('tochidden');
            } else {
                ul.show();
                $(this).text(config.hideText);
                if (config.saveShowStatus) {
                    $.removeCookie('toc-hide', { path: '/' });
                }
                $('#toc').removeClass('tochidden');
            }
            return false;
        });

        if (config.saveShowStatus && $.cookie('toc-hide')) {
            var ul = $($('#toc ul')[0]);
            
            ul.hide();
            $('#toctogglelink').text(config.showText);
            $('#toc').addClass('tochidden');
        }

    }
})(jQuery);
508 |
511 |
512 | 513 |
514 |
515 | 516 | 517 | 523 | 524 |
525 | 526 |
527 | 528 |
529 |
530 | 531 | 532 |
533 | 534 |
535 | 558 |
559 | 560 | 561 |
562 |
563 |
564 | 565 |
566 |
568 |
569 |
570 |
571 |
572 | 581 |
582 | 583 | 584 | 585 |
586 | 587 | 588 | Something went wrong with that request. Please try again. 589 |
590 | 591 | 592 | 593 | 594 | -------------------------------------------------------------------------------- /doc/src/javascripts/scale.fix.js: -------------------------------------------------------------------------------- 1 | var metas = document.getElementsByTagName('meta'); 2 | var i; 3 | if (navigator.userAgent.match(/iPhone/i)) { 4 | for (i=0; i 1: 53 | testArgs[0] = "0.5" 54 | if name == 'zipf': 55 | testArgs = ["torch.Tensor(3, 4):fill(1.5)"] * (numArgs - 1) 56 | testArgs[0] = "1.5" 57 | yield """ tester:assert(%s(%s))""" % (func, ", ".join(testArgs)) 58 | 59 | # Call with one arg number and the rest tensors, and a 2D result tensor 60 | testArgs = ["torch.Tensor(2, 6)"] + testArgs 61 | yield """ tester:assert(%s(%s))""" % (func, ", ".join(testArgs)) 62 | 63 | # Call with one too many params - should break 64 | testArgs = ["0.5"] * numArgs 65 | yield """ tester:assertError(function() %s(%s) end)""" % (func, ", ".join(testArgs)) 66 | yield """end""" 67 | 68 | def funcDoc(name, sig, doc): 69 | yield "
" % (name,) 70 | yield "

%s

" % (sig,) 71 | yield "
"
 72 |     yield doc
 73 |     yield "
" 74 | 75 | def genIndex(funcNames): 76 | index = "

torch-randomkit

" 80 | return index 81 | 82 | def funcNames(): 83 | with open(randomkitFuncsPath, 'r') as f: 84 | for l in f.readlines(): 85 | yield l.strip() 86 | 87 | def getDocStrings(funcNames): 88 | 89 | for funcName in funcNames: 90 | func = getattr(scipy.random, funcName, None) 91 | if not func: 92 | print("Could not find scipy docstring for %s" % (funcName,)) 93 | continue 94 | 95 | docLines = func.__doc__.strip().split("\n") 96 | funcSig = re.sub("=[^,)]+", "", docLines[0]) 97 | funcSig = re.sub(",?\s*size", "", funcSig) 98 | funcSig = re.sub("\(", "([output], ", funcSig) 99 | funcSig = "randomkit." + funcSig 100 | doc = "\n".join(x.strip() for x in docLines[1:]) 101 | 102 | yield funcName, funcSig, doc 103 | 104 | def writeHTMLdoc(funcNames, funcInfo): 105 | with open(docFile, 'w') as f: 106 | 107 | f.write("") 108 | 109 | index = genIndex(funcNames) 110 | 111 | f.write(index) 112 | 113 | for name, sig, doc in funcInfo: 114 | for line in funcDoc(name, sig, doc): 115 | f.write(line) 116 | print("Generated doc for " + name) 117 | 118 | f.write("") 119 | 120 | def writeCallTests(funcNames, funcInfo): 121 | with open(testFile, 'w') as f: 122 | f.write(""" 123 | require 'randomkit' 124 | local myTests = {} 125 | local tester = torch.Tester() 126 | """) 127 | for name, sig, doc in funcInfo: 128 | for line in funcTest(name, sig, doc): 129 | f.write(line + "\n") 130 | print("Generated tests for " + name) 131 | 132 | f.write(""" 133 | tester:add(myTests) 134 | tester:run() 135 | """) 136 | 137 | funcNames = sorted(list(set(funcNames()) - set(exclude))) 138 | 139 | funcInfo = list(getDocStrings(funcNames)) 140 | 141 | writeHTMLdoc(funcNames, funcInfo) 142 | writeCallTests(funcNames, funcInfo) 143 | -------------------------------------------------------------------------------- /luasrc/generateMdDocs.py: -------------------------------------------------------------------------------- 1 | """ This script generates docs in markdown format for randomkit.* """ 2 | 3 | import numpy 4 | import re 5 | 6 | def getDocStrings(funcNames, exceptions): 7 | 8 | for funcName in funcNames: 9 | func = getattr(numpy.random, funcName, None) 10 | if not func: 11 | print("Could not find numpy docstring for %s" % (funcName,)) 12 | continue 13 | 14 | if funcName[0] == '_': 15 | continue 16 | if funcName in exceptions: 17 | continue 18 | 19 | docLines = func.__doc__.strip().split("\n") 20 | funcSig = re.sub("=[^,)]+", "", docLines[0]) 21 | funcSig = re.sub(",?\s*size", "", funcSig) 22 | funcSig = re.sub("\(", "([output], ", funcSig) 23 | funcSig = "randomkit." + funcSig 24 | doc = "\n".join(x.strip() for x in docLines[1:]) 25 | doc = re.sub(">>>", " $", doc) 26 | doc = re.sub("\.\.\. ", " ", doc) 27 | doc = re.sub("#", "", doc) 28 | doc = re.sub("\]_", "]", doc) 29 | doc = re.sub('.+ : .+',"* \g<0>", doc) 30 | doc = re.sub('\.\. \[(\d+?)\]', "\g<1>.", doc) 31 | doc = re.sub('(.+?)\n-+', "####\g<1>", doc) 32 | doc = re.sub('`(.+)\n<(.+)>`_', "1. \g<1>, \g<2>", doc) 33 | doc = re.sub(':math:`(.+?)`', "\\\\\(\g<1>\\\\\)", doc) 34 | doc = re.sub('\.\. math::(.+?)\n\n', "$$\g<1>$$\n\n", doc, flags=re.S) 35 | doc = re.sub(' \$ (.+)\n([^ ])', ' $ \g<1>\n\n\g<2>', doc) 36 | doc = re.sub('^([^ \n].+?)\n \$', '\g<1>\n\n $', doc, flags=re.M) 37 | doc += "\n" 38 | 39 | yield funcName, funcSig, doc 40 | 41 | def writeMDdoc(funcNames, funcInfo, introFile, docFile): 42 | with open(introFile, 'r') as f: 43 | introduction = f.read() 44 | with open(docFile, 'w') as f: 45 | f.write(introduction+"\n") 46 | f.write("#List of distributions\n") 47 | for name, sig, doc in funcInfo: 48 | f.write("##"+name+"\n") 49 | f.write(sig+"\n") 50 | f.write(doc+"\n") 51 | print("Generated doc for " + name) 52 | 53 | if __name__ == "__main__": 54 | introFile = "doc/intro.md" 55 | docFile = "README.md" 56 | funcNames = dir(numpy.random) 57 | excluded = ['RandomState', 'seed', 'set_state', 'get_state', 'choice', 'rand', 58 | 'randn', 'Tester', 'operator','warnings', 'info','test','bench', 'permutation', 59 | 'np', 'absolute_import', 'division', 'mtrand', 'print_function', 60 | 'random_integers', 'ranf', 'sample', 'shuffle'] 61 | funcInfo = list(getDocStrings(funcNames, excluded)) 62 | 63 | writeMDdoc(funcNames, funcInfo, introFile, docFile) -------------------------------------------------------------------------------- /luasrc/init.lua: -------------------------------------------------------------------------------- 1 | -- Force to include randomkit once only, relying on the global state 2 | -- NB: it is ugly to rely on the fact that we pollute the global 3 | -- namespace, yet I do not see a better way to avoid 4 | -- including ourselves twice -- which would cause seed problems. 5 | -- 6 | -- This will need deeper consideration once we will return only 7 | -- a local table, and once we will want proper multi-thread 8 | -- support. In particular, we will have to modify the interfacing 9 | -- with torch.[gs]etRNGState in wrapC.lua. 10 | -- 11 | -- But for now (November 2013), this is good enough. 12 | if rawget(_G, "randomkit") then 13 | return randomkit 14 | end 15 | 16 | randomkit = {} 17 | 18 | function randomkit._isTensor(v) 19 | if torch.typename(v) then 20 | return string.sub(torch.typename(v), -6, -1) == "Tensor" 21 | end 22 | end 23 | 24 | --[[! Argument checking for vectorized calls 25 | 26 | Process the optional return storage, the sizes of the parameter functions, etc 27 | 28 | @param K number of actual parameters for the sampler 29 | @param defaultResultType Tensor class corresponding to the expected result type (e.g. torch.DoubleTensor, torch.IntegerTensor, etc) 30 | @param ... List of all parameters passed to the original caller 31 | 32 | @return T vector or 1-d tensor to store the result into, N rows (or nil, if we should return a single value) 33 | @return p1 ... pk Tensor of parameters, all N rows 34 | --]] 35 | function randomkit._check1DParams(K, defaultResultType, ...) 36 | local argCount = select("#", ...) 37 | for index = 1,argCount do 38 | if select(index, ...) == nil then 39 | error("Bad randomkit call - argument " .. index .. " is nil when calling function bytes()!") 40 | end 41 | end 42 | local params = { ... } 43 | if #params ~= K and #params ~= K+1 then 44 | error('CHKPARAMS: need ' .. K .. ' arguments and optionally, one result tensor, instead got ' .. #params .. ' arguments') 45 | end 46 | 47 | local result 48 | local Nresult = nil -- Default: unknown result size 49 | if #params == K then 50 | local numberOnly = true 51 | for paramIndex, param in ipairs(params) do 52 | numberOnly = numberOnly and not randomkit._isTensor(param) 53 | end 54 | if numberOnly then 55 | return nil, params 56 | else 57 | result = defaultResultType.new(1) 58 | end 59 | else 60 | if randomkit._isTensor(params[1]) then 61 | -- The tensor dictates the size of the result 62 | result = params[1] 63 | Nresult = result:nElement() 64 | else 65 | error("Invalid type " .. type(params[1]) .. " for result") 66 | end 67 | table.remove(params, 1) 68 | end 69 | 70 | -- Ensure that all parameters agree in size 71 | local Nparams = 1 72 | for paramIndex, param in ipairs(params) do 73 | local size 74 | if randomkit._isTensor(param) then 75 | size = param:nElement() 76 | elseif type(param) == 'number' or type(param) == 'cdata' then 77 | size = 1 78 | -- Use torch's default Tensor for parameters 79 | params[paramIndex] = torch.Tensor{ param } 80 | else 81 | error("Invalid type " .. type(param) .. " for parameter " .. paramIndex .. ".") 82 | end 83 | 84 | if not (size == 1 or Nparams == 1 or Nparams == size) then 85 | error("Incoherent sizes for parameters") 86 | elseif size > 1 and Nparams == 1 then 87 | Nparams = size 88 | end 89 | end 90 | 91 | if Nresult then 92 | -- If the result size was fixed by the caller (either via tensor or integer) 93 | if Nparams == 1 then 94 | -- If only size-1 parameters, Nresult dictates the output size 95 | Nparams = Nresult 96 | else 97 | -- However, if the parameters dictate one size and the result another, error 98 | assert(Nparams == Nresult, "Parameter size (" .. Nparams ..") does not match result size (" .. Nresult ..")" ) 99 | end 100 | else 101 | -- If the result size was not fixed by the caller, parameters dictate it 102 | Nresult = Nparams 103 | result:resize(Nresult) 104 | end 105 | 106 | for paramIndex, param in ipairs(params) do 107 | if param:size(1) == 1 then 108 | local sizes = param:size() 109 | sizes[1] = Nparams 110 | params[paramIndex] = params[paramIndex]:expand(sizes) 111 | end 112 | end 113 | 114 | return result, params 115 | end 116 | 117 | torch.include("randomkit", "nonC.lua") 118 | torch.include("randomkit", "wrapC.lua") 119 | 120 | local aliases = { 121 | random_sample = 'double', 122 | standard_normal = 'gauss' 123 | } 124 | 125 | for k, v in pairs(aliases) do 126 | rawset(randomkit, k, randomkit[v]) 127 | end 128 | 129 | return randomkit 130 | 131 | -------------------------------------------------------------------------------- /luasrc/nonC.lua: -------------------------------------------------------------------------------- 1 | --[[ This file is for functions that are not direct wraps of the randomkit C routines ]] 2 | 3 | function randomkit.bytes(...) 4 | local result, params = randomkit._check1DParams(0, torch.ByteTensor, ...) 5 | if torch.typename(result) ~= "torch.ByteTensor" then 6 | error("randomkit.bytes() can only store into a ByteTensor!") 7 | end 8 | local dataPtr = torch.data(result) 9 | randomkit.ffi.rk_fill(dataPtr, result:nElement(), randomkit._state) 10 | return result 11 | end 12 | 13 | -------------------------------------------------------------------------------- /luasrc/tests/testCalls.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | 3 | require 'randomkit' 4 | local myTests = {} 5 | local tester = totem.Tester() 6 | function myTests.test_beta() 7 | tester:assert(randomkit.beta(0.5, 0.5)) 8 | tester:assert(randomkit.beta(torch.Tensor(10), 0.5, 0.5)) 9 | tester:assert(randomkit.beta(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 10 | tester:assert(randomkit.beta(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 11 | tester:assert(randomkit.beta(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 12 | tester:assert(randomkit.beta(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 13 | tester:assert(randomkit.beta(0.5, torch.Tensor(3, 4):fill(0.5))) 14 | tester:assert(randomkit.beta(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 15 | tester:assertError(function() randomkit.beta(0.5, 0.5, 0.5) end) 16 | end 17 | function myTests.test_binomial() 18 | tester:assert(randomkit.binomial(0.5, 0.5)) 19 | tester:assert(randomkit.binomial(torch.Tensor(10), 0.5, 0.5)) 20 | tester:assert(randomkit.binomial(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 21 | tester:assert(randomkit.binomial(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 22 | tester:assert(randomkit.binomial(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 23 | tester:assert(randomkit.binomial(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 24 | tester:assert(randomkit.binomial(0.5, torch.Tensor(3, 4):fill(0.5))) 25 | tester:assert(randomkit.binomial(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 26 | tester:assertError(function() randomkit.binomial(0.5, 0.5, 0.5) end) 27 | end 28 | function myTests.test_bytes() 29 | tester:assert(randomkit.bytes(torch.ByteTensor(10))) 30 | tester:assert(randomkit.bytes(torch.ByteTensor(5, 5))) 31 | tester:assertError(function() randomkit.bytes(0.5) end) 32 | end 33 | function myTests.test_chisquare() 34 | tester:assert(randomkit.chisquare(0.5)) 35 | tester:assert(randomkit.chisquare(torch.Tensor(10), 0.5)) 36 | tester:assert(randomkit.chisquare(torch.Tensor(10):fill(0.5))) 37 | tester:assert(randomkit.chisquare(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 38 | tester:assert(randomkit.chisquare(torch.Tensor(3, 4):fill(0.5))) 39 | tester:assert(randomkit.chisquare(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 40 | tester:assertError(function() randomkit.chisquare(0.5, 0.5) end) 41 | end 42 | function myTests.test_exponential() 43 | tester:assert(randomkit.exponential(0.5)) 44 | tester:assert(randomkit.exponential(torch.Tensor(10), 0.5)) 45 | tester:assert(randomkit.exponential(torch.Tensor(10):fill(0.5))) 46 | tester:assert(randomkit.exponential(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 47 | tester:assert(randomkit.exponential(torch.Tensor(3, 4):fill(0.5))) 48 | tester:assert(randomkit.exponential(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 49 | tester:assertError(function() randomkit.exponential(0.5, 0.5) end) 50 | end 51 | function myTests.test_f() 52 | tester:assert(randomkit.f(0.5, 0.5)) 53 | tester:assert(randomkit.f(torch.Tensor(10), 0.5, 0.5)) 54 | tester:assert(randomkit.f(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 55 | tester:assert(randomkit.f(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 56 | tester:assert(randomkit.f(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 57 | tester:assert(randomkit.f(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 58 | tester:assert(randomkit.f(0.5, torch.Tensor(3, 4):fill(0.5))) 59 | tester:assert(randomkit.f(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 60 | tester:assertError(function() randomkit.f(0.5, 0.5, 0.5) end) 61 | end 62 | function myTests.test_gamma() 63 | tester:assert(randomkit.gamma(0.5, 0.5)) 64 | tester:assert(randomkit.gamma(torch.Tensor(10), 0.5, 0.5)) 65 | tester:assert(randomkit.gamma(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 66 | tester:assert(randomkit.gamma(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 67 | tester:assert(randomkit.gamma(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 68 | tester:assert(randomkit.gamma(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 69 | tester:assert(randomkit.gamma(0.5, torch.Tensor(3, 4):fill(0.5))) 70 | tester:assert(randomkit.gamma(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 71 | tester:assertError(function() randomkit.gamma(0.5, 0.5, 0.5) end) 72 | end 73 | function myTests.test_geometric() 74 | tester:assert(randomkit.geometric(0.5)) 75 | tester:assert(randomkit.geometric(torch.Tensor(10), 0.5)) 76 | tester:assert(randomkit.geometric(torch.Tensor(10):fill(0.5))) 77 | tester:assert(randomkit.geometric(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 78 | tester:assert(randomkit.geometric(torch.Tensor(3, 4):fill(0.5))) 79 | tester:assert(randomkit.geometric(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 80 | tester:assertError(function() randomkit.geometric(0.5, 0.5) end) 81 | end 82 | function myTests.test_gumbel() 83 | tester:assert(randomkit.gumbel(0.5, 0.5)) 84 | tester:assert(randomkit.gumbel(torch.Tensor(10), 0.5, 0.5)) 85 | tester:assert(randomkit.gumbel(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 86 | tester:assert(randomkit.gumbel(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 87 | tester:assert(randomkit.gumbel(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 88 | tester:assert(randomkit.gumbel(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 89 | tester:assert(randomkit.gumbel(0.5, torch.Tensor(3, 4):fill(0.5))) 90 | tester:assert(randomkit.gumbel(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 91 | tester:assertError(function() randomkit.gumbel(0.5, 0.5, 0.5) end) 92 | end 93 | function myTests.test_hypergeometric() 94 | tester:assert(randomkit.hypergeometric(0.5, 0.5, 0.5)) 95 | tester:assert(randomkit.hypergeometric(torch.Tensor(10), 0.5, 0.5, 0.5)) 96 | tester:assert(randomkit.hypergeometric(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 97 | tester:assert(randomkit.hypergeometric(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 98 | tester:assert(randomkit.hypergeometric(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 99 | tester:assert(randomkit.hypergeometric(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 100 | tester:assert(randomkit.hypergeometric(0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 101 | tester:assert(randomkit.hypergeometric(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 102 | tester:assertError(function() randomkit.hypergeometric(0.5, 0.5, 0.5, 0.5) end) 103 | end 104 | function myTests.test_laplace() 105 | tester:assert(randomkit.laplace(0.5, 0.5)) 106 | tester:assert(randomkit.laplace(torch.Tensor(10), 0.5, 0.5)) 107 | tester:assert(randomkit.laplace(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 108 | tester:assert(randomkit.laplace(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 109 | tester:assert(randomkit.laplace(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 110 | tester:assert(randomkit.laplace(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 111 | tester:assert(randomkit.laplace(0.5, torch.Tensor(3, 4):fill(0.5))) 112 | tester:assert(randomkit.laplace(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 113 | tester:assertError(function() randomkit.laplace(0.5, 0.5, 0.5) end) 114 | end 115 | function myTests.test_logistic() 116 | tester:assert(randomkit.logistic(0.5, 0.5)) 117 | tester:assert(randomkit.logistic(torch.Tensor(10), 0.5, 0.5)) 118 | tester:assert(randomkit.logistic(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 119 | tester:assert(randomkit.logistic(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 120 | tester:assert(randomkit.logistic(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 121 | tester:assert(randomkit.logistic(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 122 | tester:assert(randomkit.logistic(0.5, torch.Tensor(3, 4):fill(0.5))) 123 | tester:assert(randomkit.logistic(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 124 | tester:assertError(function() randomkit.logistic(0.5, 0.5, 0.5) end) 125 | end 126 | function myTests.test_lognormal() 127 | tester:assert(randomkit.lognormal(0.5, 0.5)) 128 | tester:assert(randomkit.lognormal(torch.Tensor(10), 0.5, 0.5)) 129 | tester:assert(randomkit.lognormal(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 130 | tester:assert(randomkit.lognormal(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 131 | tester:assert(randomkit.lognormal(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 132 | tester:assert(randomkit.lognormal(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 133 | tester:assert(randomkit.lognormal(0.5, torch.Tensor(3, 4):fill(0.5))) 134 | tester:assert(randomkit.lognormal(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 135 | tester:assertError(function() randomkit.lognormal(0.5, 0.5, 0.5) end) 136 | end 137 | function myTests.test_logseries() 138 | tester:assert(randomkit.logseries(0.5)) 139 | tester:assert(randomkit.logseries(torch.Tensor(10), 0.5)) 140 | tester:assert(randomkit.logseries(torch.Tensor(10):fill(0.5))) 141 | tester:assert(randomkit.logseries(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 142 | tester:assert(randomkit.logseries(torch.Tensor(3, 4):fill(0.5))) 143 | tester:assert(randomkit.logseries(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 144 | tester:assertError(function() randomkit.logseries(0.5, 0.5) end) 145 | end 146 | function myTests.test_negative_binomial() 147 | tester:assert(randomkit.negative_binomial(0.5, 0.5)) 148 | tester:assert(randomkit.negative_binomial(torch.Tensor(10), 0.5, 0.5)) 149 | tester:assert(randomkit.negative_binomial(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 150 | tester:assert(randomkit.negative_binomial(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 151 | tester:assert(randomkit.negative_binomial(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 152 | tester:assert(randomkit.negative_binomial(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 153 | tester:assert(randomkit.negative_binomial(0.5, torch.Tensor(3, 4):fill(0.5))) 154 | tester:assert(randomkit.negative_binomial(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 155 | tester:assertError(function() randomkit.negative_binomial(0.5, 0.5, 0.5) end) 156 | end 157 | function myTests.test_noncentral_chisquare() 158 | tester:assert(randomkit.noncentral_chisquare(0.5, 0.5)) 159 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(10), 0.5, 0.5)) 160 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 161 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 162 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 163 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 164 | tester:assert(randomkit.noncentral_chisquare(0.5, torch.Tensor(3, 4):fill(0.5))) 165 | tester:assert(randomkit.noncentral_chisquare(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 166 | tester:assertError(function() randomkit.noncentral_chisquare(0.5, 0.5, 0.5) end) 167 | end 168 | function myTests.test_noncentral_f() 169 | tester:assert(randomkit.noncentral_f(0.5, 0.5, 0.5)) 170 | tester:assert(randomkit.noncentral_f(torch.Tensor(10), 0.5, 0.5, 0.5)) 171 | tester:assert(randomkit.noncentral_f(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 172 | tester:assert(randomkit.noncentral_f(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 173 | tester:assert(randomkit.noncentral_f(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 174 | tester:assert(randomkit.noncentral_f(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 175 | tester:assert(randomkit.noncentral_f(0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 176 | tester:assert(randomkit.noncentral_f(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 177 | tester:assertError(function() randomkit.noncentral_f(0.5, 0.5, 0.5, 0.5) end) 178 | end 179 | function myTests.test_normal() 180 | tester:assert(randomkit.normal(0.5, 0.5)) 181 | tester:assert(randomkit.normal(torch.Tensor(10), 0.5, 0.5)) 182 | tester:assert(randomkit.normal(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 183 | tester:assert(randomkit.normal(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 184 | tester:assert(randomkit.normal(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 185 | tester:assert(randomkit.normal(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 186 | tester:assert(randomkit.normal(0.5, torch.Tensor(3, 4):fill(0.5))) 187 | tester:assert(randomkit.normal(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 188 | tester:assertError(function() randomkit.normal(0.5, 0.5, 0.5) end) 189 | end 190 | function myTests.test_pareto() 191 | tester:assert(randomkit.pareto(0.5)) 192 | tester:assert(randomkit.pareto(torch.Tensor(10), 0.5)) 193 | tester:assert(randomkit.pareto(torch.Tensor(10):fill(0.5))) 194 | tester:assert(randomkit.pareto(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 195 | tester:assert(randomkit.pareto(torch.Tensor(3, 4):fill(0.5))) 196 | tester:assert(randomkit.pareto(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 197 | tester:assertError(function() randomkit.pareto(0.5, 0.5) end) 198 | end 199 | function myTests.test_poisson() 200 | tester:assert(randomkit.poisson(0.5)) 201 | tester:assert(randomkit.poisson(torch.Tensor(10), 0.5)) 202 | tester:assert(randomkit.poisson(torch.Tensor(10):fill(0.5))) 203 | tester:assert(randomkit.poisson(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 204 | tester:assert(randomkit.poisson(torch.Tensor(3, 4):fill(0.5))) 205 | tester:assert(randomkit.poisson(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 206 | tester:assertError(function() randomkit.poisson(0.5, 0.5) end) 207 | end 208 | function myTests.test_power() 209 | tester:assert(randomkit.power(0.5)) 210 | tester:assert(randomkit.power(torch.Tensor(10), 0.5)) 211 | tester:assert(randomkit.power(torch.Tensor(10):fill(0.5))) 212 | tester:assert(randomkit.power(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 213 | tester:assert(randomkit.power(torch.Tensor(3, 4):fill(0.5))) 214 | tester:assert(randomkit.power(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 215 | tester:assertError(function() randomkit.power(0.5, 0.5) end) 216 | end 217 | function myTests.test_randint() 218 | tester:assert(randomkit.randint(0.5, 0.5)) 219 | tester:assert(randomkit.randint(torch.Tensor(10), 0.5, 0.5)) 220 | tester:assert(randomkit.randint(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 221 | tester:assert(randomkit.randint(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 222 | tester:assert(randomkit.randint(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 223 | tester:assert(randomkit.randint(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 224 | tester:assert(randomkit.randint(0.5, torch.Tensor(3, 4):fill(0.5))) 225 | tester:assert(randomkit.randint(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 226 | tester:assertError(function() randomkit.randint(0.5, 0.5, 0.5) end) 227 | end 228 | function myTests.test_random() 229 | tester:assert(randomkit.random_sample()) 230 | tester:assert(randomkit.random_sample(torch.Tensor(10))) 231 | tester:assert(randomkit.random_sample()) 232 | tester:assert(randomkit.random_sample(torch.Tensor(10))) 233 | tester:assert(randomkit.random_sample()) 234 | tester:assert(randomkit.random_sample(torch.Tensor(2, 6))) 235 | tester:assertError(function() randomkit.random_sample(0.5) end) 236 | end 237 | function myTests.test_random_sample() 238 | tester:assert(randomkit.random_sample()) 239 | tester:assert(randomkit.random_sample(torch.Tensor(10))) 240 | tester:assert(randomkit.random_sample()) 241 | tester:assert(randomkit.random_sample(torch.Tensor(10))) 242 | tester:assert(randomkit.random_sample()) 243 | tester:assert(randomkit.random_sample(torch.Tensor(2, 6))) 244 | tester:assertError(function() randomkit.random_sample(0.5) end) 245 | end 246 | function myTests.test_rayleigh() 247 | tester:assert(randomkit.rayleigh(0.5)) 248 | tester:assert(randomkit.rayleigh(torch.Tensor(10), 0.5)) 249 | tester:assert(randomkit.rayleigh(torch.Tensor(10):fill(0.5))) 250 | tester:assert(randomkit.rayleigh(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 251 | tester:assert(randomkit.rayleigh(torch.Tensor(3, 4):fill(0.5))) 252 | tester:assert(randomkit.rayleigh(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 253 | tester:assertError(function() randomkit.rayleigh(0.5, 0.5) end) 254 | end 255 | function myTests.test_standard_cauchy() 256 | tester:assert(randomkit.standard_cauchy()) 257 | tester:assert(randomkit.standard_cauchy(torch.Tensor(10))) 258 | tester:assert(randomkit.standard_cauchy()) 259 | tester:assert(randomkit.standard_cauchy(torch.Tensor(10))) 260 | tester:assert(randomkit.standard_cauchy()) 261 | tester:assert(randomkit.standard_cauchy(torch.Tensor(2, 6))) 262 | tester:assertError(function() randomkit.standard_cauchy(0.5) end) 263 | end 264 | function myTests.test_standard_exponential() 265 | tester:assert(randomkit.standard_exponential()) 266 | tester:assert(randomkit.standard_exponential(torch.Tensor(10))) 267 | tester:assert(randomkit.standard_exponential()) 268 | tester:assert(randomkit.standard_exponential(torch.Tensor(10))) 269 | tester:assert(randomkit.standard_exponential()) 270 | tester:assert(randomkit.standard_exponential(torch.Tensor(2, 6))) 271 | tester:assertError(function() randomkit.standard_exponential(0.5) end) 272 | end 273 | function myTests.test_standard_gamma() 274 | tester:assert(randomkit.standard_gamma(0.5)) 275 | tester:assert(randomkit.standard_gamma(torch.Tensor(10), 0.5)) 276 | tester:assert(randomkit.standard_gamma(torch.Tensor(10):fill(0.5))) 277 | tester:assert(randomkit.standard_gamma(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 278 | tester:assert(randomkit.standard_gamma(torch.Tensor(3, 4):fill(0.5))) 279 | tester:assert(randomkit.standard_gamma(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 280 | tester:assertError(function() randomkit.standard_gamma(0.5, 0.5) end) 281 | end 282 | function myTests.test_standard_normal() 283 | tester:assert(randomkit.standard_normal()) 284 | tester:assert(randomkit.standard_normal(torch.Tensor(10))) 285 | tester:assert(randomkit.standard_normal()) 286 | tester:assert(randomkit.standard_normal(torch.Tensor(10))) 287 | tester:assert(randomkit.standard_normal()) 288 | tester:assert(randomkit.standard_normal(torch.Tensor(2, 6))) 289 | tester:assertError(function() randomkit.standard_normal(0.5) end) 290 | end 291 | function myTests.test_standard_t() 292 | tester:assert(randomkit.standard_t(0.5)) 293 | tester:assert(randomkit.standard_t(torch.Tensor(10), 0.5)) 294 | tester:assert(randomkit.standard_t(torch.Tensor(10):fill(0.5))) 295 | tester:assert(randomkit.standard_t(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 296 | tester:assert(randomkit.standard_t(torch.Tensor(3, 4):fill(0.5))) 297 | tester:assert(randomkit.standard_t(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 298 | tester:assertError(function() randomkit.standard_t(0.5, 0.5) end) 299 | end 300 | function myTests.test_triangular() 301 | tester:assert(randomkit.triangular(0.5, 0.5, 0.5)) 302 | tester:assert(randomkit.triangular(torch.Tensor(10), 0.5, 0.5, 0.5)) 303 | tester:assert(randomkit.triangular(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 304 | tester:assert(randomkit.triangular(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 305 | tester:assert(randomkit.triangular(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 306 | tester:assert(randomkit.triangular(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 307 | tester:assert(randomkit.triangular(0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 308 | tester:assert(randomkit.triangular(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 309 | tester:assertError(function() randomkit.triangular(0.5, 0.5, 0.5, 0.5) end) 310 | end 311 | function myTests.test_uniform() 312 | tester:assert(randomkit.uniform(0.5, 0.5)) 313 | tester:assert(randomkit.uniform(torch.Tensor(10), 0.5, 0.5)) 314 | tester:assert(randomkit.uniform(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 315 | tester:assert(randomkit.uniform(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 316 | tester:assert(randomkit.uniform(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 317 | tester:assert(randomkit.uniform(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 318 | tester:assert(randomkit.uniform(0.5, torch.Tensor(3, 4):fill(0.5))) 319 | tester:assert(randomkit.uniform(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 320 | tester:assertError(function() randomkit.uniform(0.5, 0.5, 0.5) end) 321 | end 322 | function myTests.test_vonmises() 323 | tester:assert(randomkit.vonmises(0.5, 0.5)) 324 | tester:assert(randomkit.vonmises(torch.Tensor(10), 0.5, 0.5)) 325 | tester:assert(randomkit.vonmises(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 326 | tester:assert(randomkit.vonmises(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 327 | tester:assert(randomkit.vonmises(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 328 | tester:assert(randomkit.vonmises(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 329 | tester:assert(randomkit.vonmises(0.5, torch.Tensor(3, 4):fill(0.5))) 330 | tester:assert(randomkit.vonmises(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 331 | tester:assertError(function() randomkit.vonmises(0.5, 0.5, 0.5) end) 332 | end 333 | function myTests.test_wald() 334 | tester:assert(randomkit.wald(0.5, 0.5)) 335 | tester:assert(randomkit.wald(torch.Tensor(10), 0.5, 0.5)) 336 | tester:assert(randomkit.wald(torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 337 | tester:assert(randomkit.wald(torch.Tensor(10), torch.Tensor(10):fill(0.5), torch.Tensor(10):fill(0.5))) 338 | tester:assert(randomkit.wald(torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 339 | tester:assert(randomkit.wald(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5), torch.Tensor(3, 4):fill(0.5))) 340 | tester:assert(randomkit.wald(0.5, torch.Tensor(3, 4):fill(0.5))) 341 | tester:assert(randomkit.wald(torch.Tensor(2, 6), 0.5, torch.Tensor(3, 4):fill(0.5))) 342 | tester:assertError(function() randomkit.wald(0.5, 0.5, 0.5) end) 343 | end 344 | function myTests.test_weibull() 345 | tester:assert(randomkit.weibull(0.5)) 346 | tester:assert(randomkit.weibull(torch.Tensor(10), 0.5)) 347 | tester:assert(randomkit.weibull(torch.Tensor(10):fill(0.5))) 348 | tester:assert(randomkit.weibull(torch.Tensor(10), torch.Tensor(10):fill(0.5))) 349 | tester:assert(randomkit.weibull(torch.Tensor(3, 4):fill(0.5))) 350 | tester:assert(randomkit.weibull(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(0.5))) 351 | tester:assertError(function() randomkit.weibull(0.5, 0.5) end) 352 | end 353 | function myTests.test_zipf() 354 | tester:assert(randomkit.zipf(1.5)) 355 | tester:assert(randomkit.zipf(torch.Tensor(10), 1.5)) 356 | tester:assert(randomkit.zipf(torch.Tensor(10):fill(1.5))) 357 | tester:assert(randomkit.zipf(torch.Tensor(10), torch.Tensor(10):fill(1.5))) 358 | tester:assert(randomkit.zipf(torch.Tensor(3, 4):fill(1.5))) 359 | tester:assert(randomkit.zipf(torch.Tensor(2, 6), torch.Tensor(3, 4):fill(1.5))) 360 | tester:assertError(function() randomkit.zipf(0.5, 0.5) end) 361 | end 362 | 363 | tester:add(myTests) 364 | return tester:run() 365 | -------------------------------------------------------------------------------- /luasrc/tests/testMultipleRequire.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | local myTests = {} 3 | local tester = totem.Tester() 4 | 5 | function myTests.test_beta() 6 | local N = 10000 7 | local oneRequire = torch.Tensor(N) 8 | local multipleRequire = torch.Tensor(N) 9 | 10 | 11 | -- Call N in one go 12 | require 'randomkit' 13 | local state = torch.getRNGState() 14 | randomkit.gauss(oneRequire) 15 | 16 | -- call N with require between each another 17 | torch.setRNGState(state) 18 | local multipleRequire = torch.Tensor(N) 19 | for i=1,N do 20 | require 'randomkit' 21 | multipleRequire[i] = randomkit.gauss() 22 | end 23 | 24 | -- The streams should be the same 25 | tester:assertTensorEq(oneRequire, multipleRequire, 1e-16, 'Multiple require changed the stream') 26 | 27 | end 28 | 29 | tester:add(myTests) 30 | return tester:run() 31 | -------------------------------------------------------------------------------- /luasrc/tests/testMultivariateValues.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | 3 | require 'randomkit' 4 | local myTests = {} 5 | local tester = totem.Tester() 6 | return tester:run() 7 | 8 | --[[ TODO - wrap multinomial or remove these 9 | function myTest.test_multinomial_basic() 10 | randomkit.multinomial(100, {0.2, 0.8}) 11 | end 12 | 13 | function myTest.test_multinomial_zero_probability() 14 | randomkit.multinomial(100, {0.2, 0.8, 0.0, 0.0, 0.0}) 15 | end 16 | 17 | function myTest.test_multinomial_int_negative_interval() 18 | tester:assert( -5 <= randomkit.randint(-5, -1) < -1) 19 | x = randomkit.randint(-5, -1, 5) 20 | tester:assert(all(-5 <= x)) 21 | tester:assert(all(x < -1)) 22 | end 23 | --]] 24 | 25 | --[[ TODO - wrap dirichlet or remove this 26 | function myTest.test_dirichlet() 27 | torch.manualSeed(seed) 28 | alpha = torch.Tensor({51.72840233779265162, 39.74494232180943953}) 29 | local actual = torch.Tensor(3, 2) 30 | randomkit.dirichlet(actual, alpha) 31 | local desired = torch.Tensor({{{ 0.54539444573611562, 0.45460555426388438}, 32 | { 0.62345816822039413, 0.37654183177960598}}, 33 | {{ 0.55206000085785778, 0.44793999914214233}, 34 | { 0.58964023305154301, 0.41035976694845688}}, 35 | {{ 0.59266909280647828, 0.40733090719352177}, 36 | { 0.56974431743975207, 0.43025568256024799}}}) 37 | tester:assertTensorEq(actual, desired, 1e-15) 38 | end 39 | --]] 40 | --[[ TODO: wrap multinomial or remove this 41 | function myTest.test_multinomial() 42 | torch.manualSeed(seed) 43 | local actual = torch.Tensor(3, 2) 44 | randomkit.multinomial(actual, 20, {1/6, 1/6, 1/6, 1/6, 1/6, 1/6}) 45 | local desired = torch.Tensor({{{4, 3, 5, 4, 2, 2}, 46 | {5, 2, 8, 2, 2, 1}}, 47 | {{3, 4, 3, 6, 0, 4}, 48 | {2, 1, 4, 3, 6, 4}}, 49 | {{4, 4, 2, 5, 2, 3}, 50 | {4, 3, 4, 2, 3, 4}}}) 51 | tester:assertTensorEq(actual, desired) 52 | end 53 | --]] 54 | 55 | --[[ TODO: support for multivariate distributions 56 | function myTest.test_multivariate_normal() 57 | torch.manualSeed(seed) 58 | local actual = torch.Tensor(3, 2) 59 | local mean= (.123456789, 10) 60 | local cov = {{1, 0}, {1, 0}} 61 | local size = {3, 2} 62 | local actual = randomkit.multivariate_normal(mean, cov, size) 63 | local desired = torch.Tensor({{{ -1.47027513018564449, 10. }, 64 | { -1.65915081534845532, 10. }}, 65 | {{ -2.29186329304599745, 10. }, 66 | { -1.77505606019580053, 10. }}, 67 | {{ -0.54970369430044119, 10. }, 68 | { 0.29768848031692957, 10. }}}) 69 | tester:assertTensorEq(actual, desired, 1e-15) 70 | end 71 | --]] 72 | 73 | -------------------------------------------------------------------------------- /luasrc/tests/testSeed.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | require 'randomkit' 3 | local seedTest = {} 4 | local tester = totem.Tester() 5 | 6 | function seedTest.testManualSeed() 7 | local seed = 1234567890 8 | 9 | local function test_generator(f, s) 10 | s = s or '' 11 | torch.manualSeed(seed) 12 | local before = f() 13 | torch.manualSeed(seed) 14 | local after = f() 15 | tester:assertTensorEq(before, after, 1e-16, 'manualSeed not generating same sequence for generator ' .. s) 16 | end 17 | 18 | -- Try on uniform 19 | -- Make sure we do not ruin torch's generators 20 | test_generator(function() return torch.rand(10) end, 'torch.rand') 21 | test_generator(function() return randomkit.double(torch.Tensor(10)) end, 'randomkit.double') 22 | 23 | -- Try on Gauss with odd number of variates, trickiest case due to dangling gaussian 24 | local oddN = 3 25 | test_generator(function() return randomkit.gauss(torch.Tensor(oddN)) end, 'randomkit.gauss') 26 | -- TODO: uncomment below once torch7-distro/torch#191 is fixed 27 | -- test_generator(function() return torch.randn(oddN) end, 'torch.randn') 28 | 29 | end 30 | 31 | function seedTest.testRNGState() 32 | local state, stateCloned, before, after 33 | 34 | local function test_generator(f, s) 35 | s = s or '' 36 | state = torch.getRNGState() 37 | before = f() 38 | torch.setRNGState(state) 39 | after = f() 40 | tester:assertTensorEq(before, after, 1e-16, 'getRNGState/setRNGState not generating same sequence for generator ' .. s) 41 | end 42 | 43 | -- Try on uniform 44 | -- Make sure we do not ruin torch's generators 45 | test_generator(function() return torch.rand(10) end, 'torch.rand') 46 | test_generator(function() return randomkit.double(torch.Tensor(10)) end, 'randomkit.double') 47 | 48 | -- Try on Gauss with odd number of variates, trickiest case due to dangling gaussian 49 | local oddN = 3 50 | test_generator(function() return randomkit.gauss(torch.Tensor(oddN)) end, 'randomkit.gauss') 51 | -- TODO: uncomment below once torch7-distro/torch#191 is fixed 52 | -- test_generator(function() return torch.randn(oddN) end, 'torch.randn') 53 | end 54 | 55 | local getTempFileName = function(path) 56 | path = path or '/tmp/' 57 | 58 | local ffi = require 'ffi' 59 | ffi.cdef[[char * mktemp(char *);]] 60 | local fileTemplate = ffi.new("char[100]") 61 | ffi.copy(fileTemplate, path .. '/testXXXXXX') 62 | return ffi.string(ffi.C.mktemp(fileTemplate)) 63 | end 64 | 65 | function seedTest.testSeralizeRNGState() 66 | 67 | local fileName = getTempFileName() 68 | local state = torch.getRNGState() 69 | local before = randomkit.double() 70 | torch.save(fileName, state) 71 | local loadedState = torch.load(fileName) 72 | torch.setRNGState(loadedState) 73 | local after = randomkit.double() 74 | tester:asserteq(before, after, 'Saving state to file then loading and restoring did not restore stream') 75 | os.remove(fileName) 76 | end 77 | 78 | tester:add(seedTest) 79 | return tester:run() 80 | -------------------------------------------------------------------------------- /luasrc/tests/testValues.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | require 'randomkit' 3 | local ffi = require 'ffi' 4 | 5 | local myTest = {} 6 | local tester = totem.Tester() 7 | local seed = 1234567890 8 | 9 | function myTest.test_binomial_n_zero() 10 | -- Tests the corner case of n == 0 for the binomial distribution. 11 | -- binomial(0, p) should be zero for any p in {0, 1}. 12 | -- This test addresses issue --3480. 13 | local zeros = torch.IntTensor(2):zero() 14 | for _, p in ipairs({0, .5, 1}) do 15 | tester:asserteq(randomkit.binomial(0, p), 0, "Binomial sampler does not produce desired values for corner case") 16 | end 17 | end 18 | 19 | function myTest.test_interval() 20 | torch.manualSeed(seed) 21 | local actual = randomkit.interval(torch.Tensor(3, 2), 188) 22 | 23 | local desired = torch.Tensor({{ 130, 102}, 24 | {47, 140}, 25 | {51, 33}}) 26 | tester:assertTensorEq(actual, desired, 1e-15, "Interval sampler does not produce desired values") 27 | end 28 | 29 | function myTest.test_randint() 30 | torch.manualSeed(seed) 31 | local actual = randomkit.randint(torch.Tensor(3, 2), -99, 99) 32 | local desired = torch.Tensor({{ 31, 3}, 33 | {-52, 41}, 34 | {-48, -66}}) 35 | tester:assertTensorEq(actual, desired, 1e-15, "Randint sampler does not produce desired values") 36 | end 37 | 38 | function myTest.test_random_sample() 39 | torch.manualSeed(seed) 40 | local actual = torch.Tensor(3, 2) 41 | randomkit.random_sample(actual) 42 | local desired = torch.Tensor({{ 0.61879477158567997, 0.59162362775974664}, 43 | { 0.88868358904449662, 0.89165480011560816}, 44 | { 0.4575674820298663, 0.7781880808593471 }}) 45 | tester:assertTensorEq(actual, desired, 1e-15, "random_sample sampler does not produce desired values") 46 | end 47 | 48 | function myTest.test_bytes() 49 | torch.manualSeed(seed) 50 | local actual = randomkit.bytes(torch.ByteTensor(10)):double() 51 | local desired = torch.ByteTensor({130, 85, 105, 158, 255, 151, 43, 87, 102, 165}):double() 52 | tester:assertTensorEq(actual, desired, 1e-15, "Bytes sampler doesn't produce desired values") 53 | end 54 | 55 | function myTest.test_beta() 56 | torch.manualSeed(seed) 57 | local actual = torch.Tensor(3, 2) 58 | randomkit.beta(actual, .1, .9) 59 | local desired = torch.Tensor({{ 1.45341850513746058e-02, 5.31297615662868145e-04}, 60 | { 1.85366619058432324e-06, 4.19214516800110563e-03}, 61 | { 1.58405155108498093e-04, 1.26252891949397652e-04}}) 62 | tester:assertTensorEq(actual, desired, 1e-15, "Beta sampler doesn't produce desired values") 63 | end 64 | function myTest.test_binomial() 65 | torch.manualSeed(seed) 66 | local actual = torch.Tensor(3, 2) 67 | randomkit.binomial(actual, 100.123, .456) 68 | local desired = torch.Tensor({{37, 43}, 69 | {42, 48}, 70 | {46, 45}}) 71 | tester:assertTensorEq(actual, desired, 1e-15, "Binomial sampler doesn't produce desired values") 72 | end 73 | function myTest.test_chisquare() 74 | torch.manualSeed(seed) 75 | local actual = torch.Tensor(3, 2) 76 | randomkit.chisquare(actual, 50) 77 | local desired = torch.Tensor({{ 63.87858175501090585, 68.68407748911370447}, 78 | { 65.77116116901505904, 47.09686762438974483}, 79 | { 72.3828403199695174, 74.18408615260374006}}) 80 | tester:assertTensorEq(actual, desired, 1e-13, "Chi-square sampler doesn't produce desired values") 81 | end 82 | function myTest.test_exponential() 83 | torch.manualSeed(seed) 84 | local actual = torch.Tensor(3, 2) 85 | randomkit.exponential(actual, 1.1234) 86 | local desired = torch.Tensor({{ 1.08342649775011624, 1.00607889924557314}, 87 | { 2.46628830085216721, 2.49668106809923884}, 88 | { 0.68717433461363442, 1.69175666993575979}}) 89 | tester:assertTensorEq(actual, desired, 1e-15, "Exponential sampler doesn't produce desired values") 90 | end 91 | function myTest.test_f() 92 | torch.manualSeed(seed) 93 | local actual = torch.Tensor(3, 2) 94 | randomkit.f(actual, 12, 77) 95 | local desired = torch.Tensor({{ 1.21975394418575878, 1.75135759791559775}, 96 | { 1.44803115017146489, 1.22108959480396262}, 97 | { 1.02176975757740629, 1.34431827623300415}}) 98 | tester:assertTensorEq(actual, desired, 1e-15, "F sampler doesn't produce desired values") 99 | end 100 | function myTest.test_gamma() 101 | torch.manualSeed(seed) 102 | local actual = torch.Tensor(3, 2) 103 | randomkit.gamma(actual, 5, 3) 104 | local desired = torch.Tensor({{ 24.60509188649287182, 28.54993563207210627}, 105 | { 26.13476110204064184, 12.56988482927716078}, 106 | { 31.71863275789960568, 33.30143302795922011}}) 107 | tester:assertTensorEq(actual, desired, 1e-14, "Gamma sampler doesn't produce desired values") 108 | end 109 | function myTest.test_geometric() 110 | torch.manualSeed(seed) 111 | local actual = torch.Tensor(3, 2) 112 | randomkit.geometric(actual, .123456789) 113 | local desired = torch.Tensor({{ 8, 7}, 114 | {17, 17}, 115 | { 5, 12}}) 116 | tester:assertTensorEq(actual, desired, 1e-15, "Geometric sampler doesn't produce desired values") 117 | end 118 | function myTest.test_gumbel() 119 | torch.manualSeed(seed) 120 | local actual = torch.Tensor(3, 2) 121 | randomkit.gumbel(actual, .123456789, 2.0) 122 | local desired = torch.Tensor({{ 0.19591898743416816, 0.34405539668096674}, 123 | {-1.4492522252274278, -1.47374816298446865}, 124 | { 1.10651090478803416, -0.69535848626236174}}) 125 | tester:assertTensorEq(actual, desired, 1e-15, "Gumbel sampler doesn't produce desired values") 126 | end 127 | function myTest.test_hypergeometric() 128 | torch.manualSeed(seed) 129 | local actual = torch.Tensor(3, 2) 130 | randomkit.hypergeometric(actual, 10.1, 5.5, 14) 131 | local desired = torch.Tensor({{10, 10}, 132 | {10, 10}, 133 | { 9, 9}}) 134 | tester:assertTensorEq(actual, desired, 1e-15, "Hypergeometric sampler doesn't produce desired values") 135 | 136 | -- Test nbad = 0 137 | actual = torch.Tensor(4) 138 | randomkit.hypergeometric(actual, 5, 0, 3) 139 | desired = torch.Tensor({3, 3, 3, 3}) 140 | tester:assertTensorEq(actual, desired, 1e-15, "Hypergeometric sampler doesn't produce desired values") 141 | 142 | randomkit.hypergeometric(actual, 15, 0, 12) 143 | desired = torch.Tensor({12, 12, 12, 12}) 144 | tester:assertTensorEq(actual, desired, 1e-15, "Hypergeometric sampler doesn't produce desired values") 145 | 146 | -- Test ngood = 0 147 | randomkit.hypergeometric(actual, 0, 5, 3) 148 | desired = torch.Tensor({0, 0, 0, 0}) 149 | tester:assertTensorEq(actual, desired, 1e-15, "Hypergeometric sampler doesn't produce desired values") 150 | 151 | randomkit.hypergeometric(actual, 0, 15, 12) 152 | desired = torch.Tensor({0, 0, 0, 0}) 153 | tester:assertTensorEq(actual, desired, 1e-15, "Hypergeometric sampler doesn't produce desired values") 154 | end 155 | function myTest.test_laplace() 156 | torch.manualSeed(seed) 157 | local actual = torch.Tensor(3, 2) 158 | randomkit.laplace(actual, .123456789, 2.0) 159 | local desired = torch.Tensor({{ 0.66599721112760157, 0.52829452552221945}, 160 | { 3.12791959514407125, 3.18202813572992005}, 161 | {-0.05391065675859356, 1.74901336242837324}}) 162 | tester:assertTensorEq(actual, desired, 1e-15, "Laplace sampler doesn't produce desired values") 163 | end 164 | function myTest.test_logistic() 165 | torch.manualSeed(seed) 166 | local actual = torch.Tensor(3, 2) 167 | randomkit.logistic(actual, .123456789, 2.0) 168 | local desired = torch.Tensor({{ 1.09232835305011444, 0.8648196662399954 }, 169 | { 4.27818590694950185, 4.33897006346929714}, 170 | {-0.21682183359214885, 2.63373365386060332}}) 171 | tester:assertTensorEq(actual, desired, 1e-15, "Logistic sampler doesn't produce desired values") 172 | end 173 | function myTest.test_lognormal() 174 | torch.manualSeed(seed) 175 | local actual = torch.Tensor(3, 2) 176 | randomkit.lognormal(actual, .123456789, 2.0) 177 | local desired = torch.Tensor({{ 16.50698631688883822, 36.54846706092654784}, 178 | { 22.67886599981281748, 0.71617561058995771}, 179 | { 65.72798501792723869, 86.84341601437161273}}) 180 | tester:assertTensorEq(actual, desired, 1e-13, "Log-normal sampler doesn't produce desired values") 181 | end 182 | function myTest.test_logseries() 183 | torch.manualSeed(seed) 184 | local actual = torch.Tensor(3, 2) 185 | randomkit.logseries(actual, .923456789) 186 | local desired = torch.Tensor({{ 2, 2}, 187 | { 6, 17}, 188 | { 3, 6}}) 189 | tester:assertTensorEq(actual, desired, 1e-14, "Log-series sampler doesn't produce desired values") 190 | end 191 | function myTest.test_negative_binomial() 192 | torch.manualSeed(seed) 193 | local actual = torch.Tensor(3, 2) 194 | randomkit.negative_binomial(actual, 100, .12345) 195 | local desired = torch.Tensor({{848, 841}, 196 | {892, 611}, 197 | {779, 647}}) 198 | tester:assertTensorEq(actual, desired, 1e-15, "Negative binomial sampler doesn't produce desired values") 199 | end 200 | function myTest.test_noncentral_chisquare() 201 | torch.manualSeed(seed) 202 | local actual = torch.Tensor(3, 2) 203 | randomkit.noncentral_chisquare(actual, 5, 5) 204 | local desired = torch.Tensor({{ 23.91905354498517511, 13.35324692733826346}, 205 | { 31.22452661329736401, 16.60047399466177254}, 206 | { 5.03461598262724586, 17.94973089023519464}}) 207 | tester:assertTensorEq(actual, desired, 1e-14, "Non-central Chi-square sampler doesn't produce desired values") 208 | end 209 | 210 | function myTest.test_noncentral_f() 211 | torch.manualSeed(seed) 212 | local actual = torch.Tensor(3, 2) 213 | randomkit.noncentral_f(actual, 5, 2, 1) 214 | local desired = torch.Tensor({{ 1.40598099674926669, 0.34207973179285761}, 215 | { 3.57715069265772545, 7.92632662577829805}, 216 | { 0.43741599463544162, 1.1774208752428319 }}) 217 | tester:assertTensorEq(actual, desired, 1e-14, "Non-central F sampler doesn't produce desired values") 218 | end 219 | function myTest.test_normal() 220 | torch.manualSeed(seed) 221 | local actual = torch.Tensor(3, 2) 222 | randomkit.normal(actual, .123456789, 2.0) 223 | local desired = torch.Tensor({{ 2.80378370443726244, 3.59863924443872163}, 224 | { 3.121433477601256, -0.33382987590723379}, 225 | { 4.18552478636557357, 4.46410668111310471}}) 226 | tester:assertTensorEq(actual, desired, 1e-15, "Gaussian sampler doesn't produce desired values") 227 | end 228 | function myTest.test_pareto() 229 | torch.manualSeed(seed) 230 | local actual = torch.Tensor(3, 2) 231 | randomkit.pareto(actual, .123456789) 232 | local desired = torch.Tensor({{ 2.46852460439034849e+03, 1.41286880810518346e+03}, 233 | { 5.28287797029485181e+07, 6.57720981047328785e+07}, 234 | { 1.40840323350391515e+02, 1.98390255135251704e+05}}) 235 | tester:assertTensorEq(actual, desired, 1e-15, "Pareto sampler doesn't produce desired values") 236 | end 237 | function myTest.test_poisson() 238 | torch.manualSeed(seed) 239 | local actual = torch.Tensor(3, 2) 240 | randomkit.poisson(actual, .123456789) 241 | local desired = torch.Tensor({{0, 0}, 242 | {1, 0}, 243 | {0, 0}}) 244 | tester:assertTensorEq(actual, desired, 1e-15, "Poisson sampler doesn't produce desired values") 245 | end 246 | --[[ TODO enable error handling 247 | function myTest.test_poisson_exceptions() 248 | lambig = iinfo('l').max 249 | lamneg = -1 250 | tester:assertError(ValueError, randomkit.poisson, lamneg) 251 | tester:assertError(ValueError, randomkit.poisson, {lamneg}*10) 252 | tester:assertError(ValueError, randomkit.poisson, lambig) 253 | tester:assertError(ValueError, randomkit.poisson, {lambig}*10) 254 | end 255 | --]] 256 | function myTest.test_power() 257 | torch.manualSeed(seed) 258 | local actual = torch.Tensor(3, 2) 259 | randomkit.power(actual, .123456789) 260 | local desired = torch.Tensor({{ 0.02048932883240791, 0.01424192241128213}, 261 | { 0.38446073748535298, 0.39499689943484395}, 262 | { 0.00177699707563439, 0.13115505880863756}}) 263 | tester:assertTensorEq(actual, desired, 1e-15, "Power sampler doesn't produce desired values") 264 | end 265 | function myTest.test_rayleigh() 266 | torch.manualSeed(seed) 267 | local actual = torch.Tensor(3, 2) 268 | randomkit.rayleigh(actual, 10) 269 | local desired = torch.Tensor({{ 13.8882496494248393, 13.383318339044731 }, 270 | { 20.95413364294492098, 21.08285015800712614}, 271 | { 11.06066537006854311, 17.35468505778271009}}) 272 | tester:assertTensorEq(actual, desired, 1e-14, "Rayleigh sampler doesn't produce desired values") 273 | end 274 | function myTest.test_standard_cauchy() 275 | torch.manualSeed(seed) 276 | local actual = torch.Tensor(3, 2) 277 | randomkit.standard_cauchy(actual) 278 | local desired = torch.Tensor({{ 0.77127660196445336, -6.55601161955910605}, 279 | { 0.93582023391158309, -2.07479293013759447}, 280 | {-4.74601644297011926, 0.18338989290760804}}) 281 | tester:assertTensorEq(actual, desired, 1e-15, "Standard Cauchy sampler doesn't produce desired values") 282 | end 283 | function myTest.test_standard_exponential() 284 | torch.manualSeed(seed) 285 | local actual = torch.Tensor(3, 2) 286 | randomkit.standard_exponential(actual) 287 | local desired = torch.Tensor({{ 0.96441739162374596, 0.89556604882105506}, 288 | { 2.1953785836319808, 2.22243285392490542}, 289 | { 0.6116915921431676, 1.50592546727413201}}) 290 | tester:assertTensorEq(actual, desired, 1e-15, "Standard exponential sampler doesn't produce desired values") 291 | end 292 | function myTest.test_standard_gamma() 293 | torch.manualSeed(seed) 294 | local actual = torch.Tensor(3, 2) 295 | randomkit.standard_gamma(actual, 3) 296 | local desired = torch.Tensor({{ 5.50841531318455058, 6.62953470301903103}, 297 | { 5.93988484943779227, 2.31044849402133989}, 298 | { 7.54838614231317084, 8.012756093271868 }}) 299 | tester:assertTensorEq(actual, desired, 1e-14, "Standard Gamma sampler doesn't produce desired values") 300 | 301 | end 302 | function myTest.test_standard_normal() 303 | torch.manualSeed(seed) 304 | local actual = torch.Tensor(3, 2) 305 | randomkit.standard_normal(actual) 306 | local desired = torch.Tensor({{ 1.34016345771863121, 1.73759122771936081}, 307 | { 1.498988344300628, -0.2286433324536169 }, 308 | { 2.031033998682787, 2.17032494605655257}}) 309 | tester:assertTensorEq(actual, desired, 1e-15, "Standard normal sampler doesn't produce desired values") 310 | end 311 | function myTest.test_standard_t() 312 | torch.manualSeed(seed) 313 | local actual = torch.Tensor(3, 2) 314 | randomkit.standard_t(actual, 10) 315 | local desired = torch.Tensor({{ 0.97140611862659965, -0.08830486548450577}, 316 | { 1.36311143689505321, -0.55317463909867071}, 317 | {-0.18473749069684214, 0.61181537341755321}}) 318 | tester:assertTensorEq(actual, desired, 1e-15, "Standard T sampler doesn't produce desired values") 319 | 320 | end 321 | function myTest.test_triangular() 322 | torch.manualSeed(seed) 323 | local actual = torch.Tensor(3, 2) 324 | randomkit.triangular(actual, 5.12, 10.23, 20.34) 325 | local desired = torch.Tensor({{ 12.68117178949215784, 12.4129206149193152 }, 326 | { 16.20131377335158263, 16.25692138747600524}, 327 | { 11.20400690911820263, 14.4978144835829923 }}) 328 | tester:assertTensorEq(actual, desired, 1e-14, "Triangular sampler doesn't produce desired values") 329 | end 330 | function myTest.test_uniform() 331 | torch.manualSeed(seed) 332 | local actual = torch.Tensor(3, 2) 333 | randomkit.uniform(actual, 1.23, 10.54) 334 | local desired = torch.Tensor({{ 6.99097932346268003, 6.73801597444323974}, 335 | { 9.50364421400426274, 9.53130618907631089}, 336 | { 5.48995325769805476, 8.47493103280052118}}) 337 | tester:assertTensorEq(actual, desired, 1e-15, "Uniform sampler doesn't produce desired values") 338 | end 339 | function myTest.test_vonmises() 340 | torch.manualSeed(seed) 341 | local actual = torch.Tensor(3, 2) 342 | randomkit.vonmises(actual, 1.23, 1.54) 343 | local desired = torch.Tensor({{ 2.28567572673902042, 2.89163838442285037}, 344 | { 0.38198375564286025, 2.57638023113890746}, 345 | { 1.19153771588353052, 1.83509849681825354}}) 346 | tester:assertTensorEq(actual, desired, 1e-15, "Von Mises sampler doesn't produce desired values") 347 | end 348 | function myTest.test_wald() 349 | torch.manualSeed(seed) 350 | local actual = torch.Tensor(3, 2) 351 | randomkit.wald(actual, 1.23, 1.54) 352 | local desired = torch.Tensor({{ 3.82935265715889983, 5.13125249184285526}, 353 | { 0.35045403618358717, 1.50832396872003538}, 354 | { 0.24124319895843183, 0.22031101461955038}}) 355 | tester:assertTensorEq(actual, desired, 1e-14, "Wald sampler doesn't produce desired values") 356 | 357 | end 358 | function myTest.test_weibull() 359 | torch.manualSeed(seed) 360 | local actual = torch.Tensor(3, 2) 361 | randomkit.weibull(actual, 1.23) 362 | local desired = torch.Tensor({{ 0.97097342648766727, 0.91422896443565516}, 363 | { 1.89517770034962929, 1.91414357960479564}, 364 | { 0.67057783752390987, 1.39494046635066793}}) 365 | tester:assertTensorEq(actual, desired, 1e-15, "Weibull sampler doesn't produce desired values") 366 | 367 | end 368 | function myTest.test_zipf() 369 | torch.manualSeed(seed) 370 | local actual = torch.Tensor(3, 2) 371 | randomkit.zipf(actual, 1.23) 372 | local desired = torch.Tensor({{66, 29}, 373 | { 1, 1}, 374 | { 3, 13}}) 375 | tester:assertTensorEq(actual, desired, 1e-15, "Zipf sampler doesn't produce desired values") 376 | end 377 | 378 | function myTest.test_returnType() 379 | tester:asserteq(type(randomkit.binomial(10, 0.5)), 'number') 380 | end 381 | 382 | tester:add(myTest) 383 | return tester:run() 384 | -------------------------------------------------------------------------------- /luasrc/tests/testWrap.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | require 'randomkit' 3 | local ffi = require 'ffi' 4 | 5 | local myTest = {} 6 | local tester = totem.Tester() 7 | 8 | function myTest.testFFICall() 9 | local state = ffi.new('rk_state') 10 | state.torch_state = ffi.cast("THGenerator*", torch.pointer(torch._gen)) 11 | randomkit.ffi.rk_seed(0, state) 12 | local x 13 | for i=1, 10 do 14 | tester:assert(tonumber(randomkit.ffi.rk_binomial(state, 10, 0.4))) 15 | end 16 | end 17 | 18 | function myTest.testWrappedCall() 19 | local N = 1000 20 | local x = torch.Tensor(N) 21 | local y = torch.Tensor(N) 22 | local state = torch.getRNGState() 23 | for i=1,N do 24 | x[i] = randomkit.binomial(10, 0.4) 25 | end 26 | torch.setRNGState(state) 27 | for i=1,N do 28 | y[i] = randomkit.binomial(10, 0.4) 29 | end 30 | tester:assertTensorEq(x,y,1e-16,'RK sequence is not a deterministic function of state') 31 | -- TODO: check distribtution 32 | 33 | end 34 | 35 | 36 | function myTest.callgetRNGWithGenerator() 37 | local generator = torch.Generator() 38 | local ok, msg = pcall( torch.getRNGState, generator) 39 | tester:assert(ok, 'Failed to get RNG state') 40 | end 41 | 42 | function myTest.callManualSeedWithGenerator() 43 | local generator = torch.Generator() 44 | local ok, msg = pcall( torch.manualSeed, generator,1) 45 | tester:assert(ok, 'Failed to set seed') 46 | end 47 | 48 | 49 | function myTest.callsetRNGWithGenerator() 50 | local generator = torch.Generator() 51 | local ok, state = pcall( torch.getRNGState, generator) 52 | tester:assert(ok, 'Failed to getRNG State') 53 | local ok, msg = pcall( torch.setRNGState, generator, state) 54 | tester:assert(ok, 'Failed to set RNG state') 55 | end 56 | 57 | function myTest.setRNGWithBadPointer() 58 | -- To simulate restoring the state from a previous run, we invalidate the 59 | -- pointer to the main Torch generator in a state that we are passing to 60 | -- setRNGState, and check that this doesn't break things. 61 | local state = torch.getRNGState() 62 | local x = tonumber(randomkit.binomial(10, 0.4)) 63 | local badState = ffi.cast("rk_state *", state.randomkit) 64 | badState.torch_state = ffi.cast("THGenerator*", 0) 65 | torch.setRNGState{ 66 | torch = state.torch, 67 | randomkit = badState 68 | } 69 | tester:asserteq(x, tonumber(randomkit.binomial(10, 0.4))) 70 | end 71 | 72 | 73 | tester:add(myTest) 74 | return tester:run() 75 | -------------------------------------------------------------------------------- /luasrc/tests/testWrongState.lua: -------------------------------------------------------------------------------- 1 | require "totem" 2 | 3 | local seedTest = {} 4 | local tester = totem.Tester() 5 | 6 | function seedTest.testStateBeforeRequire() 7 | if randomkit then 8 | print('Randomkit already loaded, skipping test, please run individually') 9 | return 10 | end 11 | local state = torch.getRNGState() 12 | require 'randomkit' 13 | tester:assertError(function() torch.setRNGState(state) end, 'Failed to generate error') 14 | tester:assertErrorPattern(function() torch.setRNGState(state) end, '.*State was not saved with randomkit, cannot set it back.*', 'Generated wrong error') 15 | end 16 | 17 | 18 | tester:add(seedTest) 19 | return tester:run() 20 | -------------------------------------------------------------------------------- /luasrc/wrapC.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | randomkit.ffi = ffi.load(package.searchpath('librandomkit', package.cpath)) 4 | 5 | ffi.cdef[[ 6 | typedef struct THGenerator THGenerator; 7 | typedef struct rk_state_ 8 | { 9 | THGenerator *torch_state; 10 | unsigned long key[624]; 11 | int pos; 12 | int has_gauss; /* !=0: gauss contains a gaussian deviate */ 13 | double gauss; 14 | 15 | /* The rk_state structure has been extended to store the following 16 | * information for the binomial generator. If the input values of n or p 17 | * are different than nsave and psave, then the other parameters will be 18 | * recomputed. RTK 2005-09-02 */ 19 | 20 | int has_binomial; /* !=0: following parameters initialized for 21 | binomial */ 22 | double psave; 23 | long nsave; 24 | double r; 25 | double q; 26 | double fm; 27 | long m; 28 | double p1; 29 | double xm; 30 | double xl; 31 | double xr; 32 | double c; 33 | double laml; 34 | double lamr; 35 | double p2; 36 | double p3; 37 | double p4; 38 | 39 | } 40 | rk_state; 41 | 42 | typedef enum { 43 | RK_NOERR = 0, /* no error */ 44 | RK_ENODEV = 1, /* no RK_DEV_RANDOM device */ 45 | RK_ERR_MAX = 2 46 | } rk_error; 47 | 48 | /* error strings */ 49 | char *rk_strerror[2]; 50 | ]] 51 | 52 | -- Declare the functions, spearately since this string 53 | -- is reused for automatic wrapping 54 | local fun_cdef = [[ 55 | void rk_seed(unsigned long seed, rk_state *state); 56 | long rk_random(rk_state *state); 57 | long rk_long(rk_state *state); 58 | unsigned long rk_ulong(rk_state *state); 59 | unsigned long rk_interval(unsigned long max, rk_state *state); 60 | double rk_double(rk_state *state); 61 | void rk_fill(void *buffer, size_t size, rk_state *state); 62 | rk_error rk_devfill(void *buffer, size_t size, int strong); 63 | rk_error rk_altfill(void *buffer, size_t size, int strong, rk_state *state); 64 | double rk_gauss(rk_state *state); 65 | double rk_normal(rk_state *state, double loc, double scale); 66 | double rk_standard_exponential(rk_state *state); 67 | double rk_exponential(rk_state *state, double scale); 68 | double rk_uniform(rk_state *state, double loc, double scale); 69 | double rk_standard_gamma(rk_state *state, double shape); 70 | double rk_gamma(rk_state *state, double shape, double scale); 71 | double rk_beta(rk_state *state, double a, double b); 72 | double rk_chisquare(rk_state *state, double df); 73 | double rk_noncentral_chisquare(rk_state *state, double df, double nonc); 74 | double rk_f(rk_state *state, double dfnum, double dfden); 75 | double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc); 76 | long rk_binomial(rk_state *state, long n, double p); 77 | long rk_binomial_btpe(rk_state *state, long n, double p); 78 | long rk_binomial_inversion(rk_state *state, long n, double p); 79 | long rk_negative_binomial(rk_state *state, double n, double p); 80 | long rk_poisson(rk_state *state, double lam); 81 | long rk_poisson_mult(rk_state *state, double lam); 82 | long rk_poisson_ptrs(rk_state *state, double lam); 83 | double rk_standard_cauchy(rk_state *state); 84 | double rk_standard_t(rk_state *state, double df); 85 | double rk_vonmises(rk_state *state, double mu, double kappa); 86 | double rk_pareto(rk_state *state, double a); 87 | double rk_weibull(rk_state *state, double a); 88 | double rk_power(rk_state *state, double a); 89 | double rk_laplace(rk_state *state, double loc, double scale); 90 | double rk_gumbel(rk_state *state, double loc, double scale); 91 | double rk_logistic(rk_state *state, double loc, double scale); 92 | double rk_lognormal(rk_state *state, double mean, double sigma); 93 | double rk_rayleigh(rk_state *state, double mode); 94 | double rk_wald(rk_state *state, double mean, double scale); 95 | long rk_zipf(rk_state *state, double a); 96 | long rk_geometric(rk_state *state, double p); 97 | long rk_geometric_search(rk_state *state, double p); 98 | long rk_geometric_inversion(rk_state *state, double p); 99 | long rk_hypergeometric(rk_state *state, long good, long bad, long sample); 100 | long rk_hypergeometric_hyp(rk_state *state, long good, long bad, long sample); 101 | long rk_hypergeometric_hrua(rk_state *state, long good, long bad, long sample); 102 | double rk_triangular(rk_state *state, double left, double mode, double right); 103 | long rk_logseries(rk_state *state, double p); 104 | ]] 105 | 106 | -- Function that should not have a lua wrapper 107 | local doNotWrap = {'rk_seed', 108 | 'rk_altfill', 109 | 'rk_devfill', 110 | 'rk_fill' 111 | } 112 | 113 | -- Declare the functions to FFI 114 | ffi.cdef(fun_cdef) 115 | 116 | -- Extract the list of function and their types 117 | local funs = {} 118 | local returnType, functionName, paramName, paramType 119 | for line in string.gmatch(fun_cdef, "[^\n]+") do 120 | -- Split words 121 | local words = {} 122 | line:gsub("([^ (,);\n\r]+)", function(c) table.insert(words, c) end) 123 | 124 | -- get the return type (long or double, no multiword, easy) and the name 125 | 126 | local type = words[1] 127 | -- ignore unsigned, not supported in Torch Tensors 128 | if type == 'unsigned' then 129 | table.remove(words, 1) 130 | type = words[1] 131 | end 132 | local name = words[2] 133 | funs[name] = { 134 | returnType = type, 135 | name = name, 136 | arguments = {} 137 | } 138 | -- get the parameters 139 | -- skip words 3 and 4: they are the 'rkstate *state' 140 | local j = 5 141 | while j + 1 <= #words do 142 | table.insert(funs[name].arguments, {name = words[j+1], type = words[j]}) 143 | j = j + 2 144 | end 145 | end 146 | 147 | -- Remove not-to-wrap functions 148 | for k,v in pairs(doNotWrap) do 149 | funs[v] = nil 150 | end 151 | 152 | funs['rk_interval'] = { 153 | name = 'interval', 154 | arguments = { { name = 'max', type = 'long' } }, 155 | returnType = 'long' 156 | } 157 | funs['rk_randint'] = { 158 | name = 'randint', 159 | arguments = { { name = 'low', type = 'int' }, { name = 'high', type = 'int' } }, 160 | returnType = 'int' 161 | } 162 | funs['rk_uniform'] = { 163 | name = 'uniform', 164 | arguments = { { name = 'low', type = 'int' }, { name = 'high', type = 'int' } }, 165 | returnType = 'int' 166 | } 167 | 168 | --[[ Initialize the state structure (which is not really seeding, 169 | since we have replaced randomkit's own Mersenne-Twister by 170 | Torch's ]] 171 | randomkit._state = ffi.new('rk_state') 172 | randomkit._state.torch_state = ffi.cast("THGenerator*", torch.pointer(torch._gen)) 173 | randomkit.ffi.rk_seed(0, randomkit._state) 174 | 175 | -- Extend torch state handling to handle randomkit's state too 176 | local _manualSeed = torch.manualSeed 177 | torch.manualSeed = function(generator, seed) 178 | if seed then 179 | return _manualSeed(generator, seed) 180 | else 181 | seed = generator 182 | end 183 | randomkit.ffi.rk_seed(0, randomkit._state) 184 | return _manualSeed(seed) 185 | end 186 | 187 | local _getRNGState = torch.getRNGState 188 | torch.getRNGState = function(generator) 189 | if generator then 190 | return _getRNGState(generator) 191 | end 192 | -- Serialize to string, required to write to file 193 | local clonedState = ffi.string(randomkit._state, ffi.sizeof(randomkit._state)) 194 | return { 195 | torch = _getRNGState(), 196 | randomkit = clonedState 197 | } 198 | end 199 | 200 | local _setRNGState = torch.setRNGState 201 | torch.setRNGState = function(generator, state) 202 | if state then 203 | return _setRNGState(generator, state) 204 | else 205 | state = generator 206 | end 207 | if not type(state) == 'table' or not state.torch or not state.randomkit then 208 | error('State was not saved with randomkit, cannot set it back') 209 | end 210 | _setRNGState(state.torch) 211 | -- Deserialize from string 212 | ffi.copy(randomkit._state, state.randomkit, ffi.sizeof(randomkit._state)) 213 | 214 | -- If the state being set is from a previous run, the pointer to the main 215 | -- Torch generator will no longer be valid. So we will explicitly update the 216 | -- pointer to be current. 217 | randomkit._state.torch_state = 218 | ffi.cast("THGenerator*", torch.pointer(torch._gen)) 219 | end 220 | 221 | local returnTypeMapping = { 222 | int = torch.IntTensor, 223 | double = torch.DoubleTensor 224 | } 225 | local function generateIntoTensor(output, func) 226 | if not output:isContiguous() then 227 | error("generateIntoTensor only supports contiguous tensors") 228 | end 229 | 230 | local outputdata = torch.data(output) 231 | local offset = output:storageOffset() 232 | -- A zero-based index is used to access the data. 233 | -- The end index is (startIndex + nElements - 1). 234 | for i0 = offset - 1, offset - 1 + output:nElement() - 1 do 235 | outputdata[i0] = tonumber(func(randomkit._state)) or outputdata[i0] 236 | end 237 | return output 238 | end 239 | local function applyNotInPlace(input, output, func) 240 | if not input:isContiguous() or not output:isContiguous() then 241 | error("applyNotInPlace only supports contiguous tensors") 242 | end 243 | 244 | if input:nElement() ~= output:nElement() then 245 | error("applyNotInPlace: tensor element counts are not consistent") 246 | end 247 | 248 | local inputdata = torch.data(input) 249 | local outputdata = torch.data(output) 250 | local offset = input:storageOffset() 251 | -- A zero-based index is used to access the data. 252 | -- The end index is (startIndex + nElements - 1). 253 | for i0 = offset - 1, offset - 1 + input:nElement() - 1 do 254 | outputdata[i0] = tonumber(func(randomkit._state, inputdata[i0])) or outputdata[i0] 255 | end 256 | return output 257 | end 258 | local function mapNotInPlace(inputA, inputB, output, func) 259 | if not inputA:isContiguous() or not inputB:isContiguous() or not output:isContiguous() then 260 | error("mapNotInPlace only supports contiguous tensors") 261 | end 262 | 263 | if inputA:nElement() ~= inputB:nElement() or inputB:nElement() ~= output:nElement() then 264 | error("mapNotInPlace: tensor element counts are not consistent") 265 | end 266 | 267 | local inputAdata = torch.data(inputA) 268 | local inputBdata = torch.data(inputB) 269 | local outputdata = torch.data(output) 270 | local offset = inputA:storageOffset() 271 | -- A zero-based index is used to access the data. 272 | -- The end index is (startIndex + nElements - 1). 273 | for i0 = offset - 1, offset - 1 + inputA:nElement() - 1 do 274 | outputdata[i0] = tonumber(func(randomkit._state, inputAdata[i0], inputBdata[i0])) or outputdata[i0] 275 | end 276 | return output 277 | end 278 | local function map2NotInPlace(inputA, inputB, inputC, output, func) 279 | if not inputA:isContiguous() or not inputB:isContiguous() or not inputC:isContiguous() or not output:isContiguous() then 280 | error("map2NotInPlace only supports contiguous tensors") 281 | end 282 | 283 | if inputA:nElement() ~= inputB:nElement() 284 | or inputB:nElement() ~= output:nElement() 285 | or inputC:nElement() ~= output:nElement() then 286 | error("map2NotInPlace: tensor element counts are not consistent") 287 | end 288 | 289 | local inputAdata = torch.data(inputA) 290 | local inputBdata = torch.data(inputB) 291 | local inputCdata = torch.data(inputC) 292 | local outputdata = torch.data(output) 293 | local offset = inputA:storageOffset() 294 | -- A zero-based index is used to access the data. 295 | -- The end index is (startIndex + nElements - 1). 296 | for i0 = offset - 1, offset - 1 + inputA:nElement() - 1 do 297 | outputdata[i0] = tonumber(func(randomkit._state, inputAdata[i0], inputBdata[i0], inputCdata[i0])) or outputdata[i0] 298 | end 299 | return output 300 | end 301 | 302 | local function create_wrapper(name, randomkitFunction, parameters, returnType) 303 | 304 | -- Note: default to DoubleTensor for arguments we don't know how to deal with 305 | local tensorReturnType = returnTypeMapping[returnType] or torch.DoubleTensor 306 | 307 | local function help() 308 | local argNames = "" 309 | if #parameters > 0 then 310 | argNames = argNames .. parameters[1].name 311 | end 312 | for i = 2,#parameters do 313 | argNames = argNames .. ", " .. parameters[i].name 314 | 315 | end 316 | 317 | print("Usage: randomkit." .. name .. "(" .. argNames .. ")") 318 | print("Returns: " .. returnType) 319 | end 320 | 321 | local function wrapper(...) 322 | local result, params = randomkit._check1DParams(#parameters, tensorReturnType, ...) 323 | 324 | if result then 325 | if #params == 0 then 326 | generateIntoTensor(result, randomkitFunction) 327 | elseif #params == 1 then 328 | params[1] = params[1]:contiguous() 329 | applyNotInPlace(params[1], result, randomkitFunction) 330 | elseif #params == 2 then 331 | params[1] = params[1]:contiguous() 332 | params[2] = params[2]:contiguous() 333 | mapNotInPlace(params[1], params[2], result, randomkitFunction) 334 | elseif #params == 3 then 335 | params[1] = params[1]:contiguous() 336 | params[2] = params[2]:contiguous() 337 | params[3] = params[3]:contiguous() 338 | map2NotInPlace(params[1], params[2], params[3], result, randomkitFunction) 339 | else 340 | error('TODO: need to implement map for ' .. #params .. 'arguments') 341 | end 342 | else 343 | result = tonumber(randomkitFunction(randomkit._state, unpack(params))) 344 | end 345 | 346 | return result 347 | end 348 | return wrapper 349 | end 350 | 351 | local customWrappers = {} 352 | customWrappers.interval = function(state, max) 353 | return randomkit.ffi.rk_interval(max, state) 354 | end 355 | customWrappers.randint = function(state, low, high) 356 | return low + tonumber(randomkit.ffi.rk_interval(high - low, state)) 357 | end 358 | customWrappers.uniform = function(state, low, high) 359 | return randomkit.ffi.rk_uniform(state, low, high - low) 360 | end 361 | 362 | -- Wrap by passing the state as first argument 363 | for k, v in pairs(funs) do 364 | local randomkitFunction 365 | if customWrappers[v.name] then 366 | randomkitFunction = customWrappers[v.name] 367 | else 368 | randomkitFunction = randomkit.ffi[v.name] 369 | end 370 | randomkit[string.sub(k, 4)] = create_wrapper(v.name, randomkitFunction, v.arguments, v.returnType) 371 | end 372 | 373 | -------------------------------------------------------------------------------- /randomkit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | FILE(GLOB src "*.c") 2 | ADD_TORCH_PACKAGE(randomkit "${src}" "") 3 | TARGET_LINK_LIBRARIES(randomkit TH) 4 | -------------------------------------------------------------------------------- /randomkit/README: -------------------------------------------------------------------------------- 1 | The randomkit library in this folder is used under 2 | BSD License courtesy of Numpy: 3 | https://github.com/numpy/numpy/tree/master/numpy/random/mtrand 4 | 5 | Thanks guys! 6 | -------------------------------------------------------------------------------- /randomkit/distributions.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2005 Robert Kern (robert.kern@gmail.com) 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a 4 | * copy of this software and associated documentation files (the 5 | * "Software"), to deal in the Software without restriction, including 6 | * without limitation the rights to use, copy, modify, merge, publish, 7 | * distribute, sublicense, and/or sell copies of the Software, and to 8 | * permit persons to whom the Software is furnished to do so, subject to 9 | * the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /* The implementations of rk_hypergeometric_hyp(), rk_hypergeometric_hrua(), 24 | * and rk_triangular() were adapted from Ivan Frohne's rv.py which has this 25 | * license: 26 | * 27 | * Copyright 1998 by Ivan Frohne; Wasilla, Alaska, U.S.A. 28 | * All Rights Reserved 29 | * 30 | * Permission to use, copy, modify and distribute this software and its 31 | * documentation for any purpose, free of charge, is granted subject to the 32 | * following conditions: 33 | * The above copyright notice and this permission notice shall be included in 34 | * all copies or substantial portions of the software. 35 | * 36 | * THE SOFTWARE AND DOCUMENTATION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, 37 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO MERCHANTABILITY, FITNESS 38 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR 39 | * OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM OR DAMAGES IN A CONTRACT 40 | * ACTION, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 41 | * SOFTWARE OR ITS DOCUMENTATION. 42 | */ 43 | 44 | #include 45 | #include "distributions.h" 46 | #include 47 | #include 48 | 49 | #ifndef min 50 | #define min(x,y) ((xy)?x:y) 52 | #endif 53 | 54 | #ifndef M_PI 55 | #define M_PI 3.14159265358979323846264338328 56 | #endif 57 | 58 | /* 59 | * log-gamma function to support some of these distributions. The 60 | * algorithm comes from SPECFUN by Shanjie Zhang and Jianming Jin and their 61 | * book "Computation of Special Functions", 1996, John Wiley & Sons, Inc. 62 | */ 63 | static double loggam(double x) 64 | { 65 | double x0, x2, xp, gl, gl0; 66 | long k, n; 67 | 68 | static double a[10] = {8.333333333333333e-02,-2.777777777777778e-03, 69 | 7.936507936507937e-04,-5.952380952380952e-04, 70 | 8.417508417508418e-04,-1.917526917526918e-03, 71 | 6.410256410256410e-03,-2.955065359477124e-02, 72 | 1.796443723688307e-01,-1.39243221690590e+00}; 73 | x0 = x; 74 | n = 0; 75 | if ((x == 1.0) || (x == 2.0)) 76 | { 77 | return 0.0; 78 | } 79 | else if (x <= 7.0) 80 | { 81 | n = (long)(7 - x); 82 | x0 = x + n; 83 | } 84 | x2 = 1.0/(x0*x0); 85 | xp = 2*M_PI; 86 | gl0 = a[9]; 87 | for (k=8; k>=0; k--) 88 | { 89 | gl0 *= x2; 90 | gl0 += a[k]; 91 | } 92 | gl = gl0/x0 + 0.5*log(xp) + (x0-0.5)*log(x0) - x0; 93 | if (x <= 7.0) 94 | { 95 | for (k=1; k<=n; k++) 96 | { 97 | gl -= log(x0-1.0); 98 | x0 -= 1.0; 99 | } 100 | } 101 | return gl; 102 | } 103 | 104 | double rk_normal(rk_state *state, double loc, double scale) 105 | { 106 | return loc + scale*rk_gauss(state); 107 | } 108 | 109 | double rk_standard_exponential(rk_state *state) 110 | { 111 | /* We use -log(1-U) since U is [0, 1) */ 112 | return -log(1.0 - rk_double(state)); 113 | } 114 | 115 | double rk_exponential(rk_state *state, double scale) 116 | { 117 | return scale * rk_standard_exponential(state); 118 | } 119 | 120 | double rk_uniform(rk_state *state, double loc, double scale) 121 | { 122 | return loc + scale*rk_double(state); 123 | } 124 | 125 | double rk_standard_gamma(rk_state *state, double shape) 126 | { 127 | double b, c; 128 | double U, V, X, Y; 129 | 130 | if (shape == 1.0) 131 | { 132 | return rk_standard_exponential(state); 133 | } 134 | else if (shape < 1.0) 135 | { 136 | for (;;) 137 | { 138 | U = rk_double(state); 139 | V = rk_standard_exponential(state); 140 | if (U <= 1.0 - shape) 141 | { 142 | X = pow(U, 1./shape); 143 | if (X <= V) 144 | { 145 | return X; 146 | } 147 | } 148 | else 149 | { 150 | Y = -log((1-U)/shape); 151 | X = pow(1.0 - shape + shape*Y, 1./shape); 152 | if (X <= (V + Y)) 153 | { 154 | return X; 155 | } 156 | } 157 | } 158 | } 159 | else 160 | { 161 | b = shape - 1./3.; 162 | c = 1./sqrt(9*b); 163 | for (;;) 164 | { 165 | do 166 | { 167 | X = rk_gauss(state); 168 | V = 1.0 + c*X; 169 | } while (V <= 0.0); 170 | 171 | V = V*V*V; 172 | U = rk_double(state); 173 | if (U < 1.0 - 0.0331*(X*X)*(X*X)) return (b*V); 174 | if (log(U) < 0.5*X*X + b*(1. - V + log(V))) return (b*V); 175 | } 176 | } 177 | } 178 | 179 | double rk_gamma(rk_state *state, double shape, double scale) 180 | { 181 | return scale * rk_standard_gamma(state, shape); 182 | } 183 | 184 | double rk_beta(rk_state *state, double a, double b) 185 | { 186 | double Ga, Gb; 187 | 188 | if ((a <= 1.0) && (b <= 1.0)) 189 | { 190 | double U, V, X, Y; 191 | /* Use Jonk's algorithm */ 192 | 193 | while (1) 194 | { 195 | U = rk_double(state); 196 | V = rk_double(state); 197 | X = pow(U, 1.0/a); 198 | Y = pow(V, 1.0/b); 199 | 200 | if ((X + Y) <= 1.0) 201 | { 202 | return X / (X + Y); 203 | } 204 | } 205 | } 206 | else 207 | { 208 | Ga = rk_standard_gamma(state, a); 209 | Gb = rk_standard_gamma(state, b); 210 | return Ga/(Ga + Gb); 211 | } 212 | } 213 | 214 | double rk_chisquare(rk_state *state, double df) 215 | { 216 | return 2.0*rk_standard_gamma(state, df/2.0); 217 | } 218 | 219 | double rk_noncentral_chisquare(rk_state *state, double df, double nonc) 220 | { 221 | double Chi2, N; 222 | 223 | Chi2 = rk_chisquare(state, df-1); 224 | N = rk_gauss(state) + sqrt(nonc); 225 | return Chi2 + N*N; 226 | } 227 | 228 | double rk_f(rk_state *state, double dfnum, double dfden) 229 | { 230 | return ((rk_chisquare(state, dfnum) * dfden) / 231 | (rk_chisquare(state, dfden) * dfnum)); 232 | } 233 | 234 | double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc) 235 | { 236 | double t = rk_noncentral_chisquare(state, dfnum, nonc) * dfden; 237 | return t / (rk_chisquare(state, dfden) * dfnum); 238 | } 239 | 240 | long rk_binomial_btpe(rk_state *state, long n, double p) 241 | { 242 | double r,q,fm,p1,xm,xl,xr,c,laml,lamr,p2,p3,p4; 243 | double a,u,v,s,F,rho,t,A,nrq,x1,x2,f1,f2,z,z2,w,w2,x; 244 | long m,y,k,i; 245 | 246 | if (!(state->has_binomial) || 247 | (state->nsave != n) || 248 | (state->psave != p)) 249 | { 250 | /* initialize */ 251 | state->nsave = n; 252 | state->psave = p; 253 | state->has_binomial = 1; 254 | state->r = r = min(p, 1.0-p); 255 | state->q = q = 1.0 - r; 256 | state->fm = fm = n*r+r; 257 | state->m = m = (long)floor(state->fm); 258 | state->p1 = p1 = floor(2.195*sqrt(n*r*q)-4.6*q) + 0.5; 259 | state->xm = xm = m + 0.5; 260 | state->xl = xl = xm - p1; 261 | state->xr = xr = xm + p1; 262 | state->c = c = 0.134 + 20.5/(15.3 + m); 263 | a = (fm - xl)/(fm-xl*r); 264 | state->laml = laml = a*(1.0 + a/2.0); 265 | a = (xr - fm)/(xr*q); 266 | state->lamr = lamr = a*(1.0 + a/2.0); 267 | state->p2 = p2 = p1*(1.0 + 2.0*c); 268 | state->p3 = p3 = p2 + c/laml; 269 | state->p4 = p4 = p3 + c/lamr; 270 | } 271 | else 272 | { 273 | r = state->r; 274 | q = state->q; 275 | fm = state->fm; 276 | m = state->m; 277 | p1 = state->p1; 278 | xm = state->xm; 279 | xl = state->xl; 280 | xr = state->xr; 281 | c = state->c; 282 | laml = state->laml; 283 | lamr = state->lamr; 284 | p2 = state->p2; 285 | p3 = state->p3; 286 | p4 = state->p4; 287 | } 288 | 289 | /* sigh ... */ 290 | Step10: 291 | nrq = n*r*q; 292 | u = rk_double(state)*p4; 293 | v = rk_double(state); 294 | if (u > p1) goto Step20; 295 | y = (long)floor(xm - p1*v + u); 296 | goto Step60; 297 | 298 | Step20: 299 | if (u > p2) goto Step30; 300 | x = xl + (u - p1)/c; 301 | v = v*c + 1.0 - fabs(m - x + 0.5)/p1; 302 | if (v > 1.0) goto Step10; 303 | y = (long)floor(x); 304 | goto Step50; 305 | 306 | Step30: 307 | if (u > p3) goto Step40; 308 | y = (long)floor(xl + log(v)/laml); 309 | if (y < 0) goto Step10; 310 | v = v*(u-p2)*laml; 311 | goto Step50; 312 | 313 | Step40: 314 | y = (int)floor(xr - log(v)/lamr); 315 | if (y > n) goto Step10; 316 | v = v*(u-p3)*lamr; 317 | 318 | Step50: 319 | k = labs(y - m); 320 | if ((k > 20) && (k < ((nrq)/2.0 - 1))) goto Step52; 321 | 322 | s = r/q; 323 | a = s*(n+1); 324 | F = 1.0; 325 | if (m < y) 326 | { 327 | for (i=m; i<=y; i++) 328 | { 329 | F *= (a/i - s); 330 | } 331 | } 332 | else if (m > y) 333 | { 334 | for (i=y; i<=m; i++) 335 | { 336 | F /= (a/i - s); 337 | } 338 | } 339 | else 340 | { 341 | if (v > F) goto Step10; 342 | goto Step60; 343 | } 344 | 345 | Step52: 346 | rho = (k/(nrq))*((k*(k/3.0 + 0.625) + 0.16666666666666666)/nrq + 0.5); 347 | t = -k*k/(2*nrq); 348 | A = log(v); 349 | if (A < (t - rho)) goto Step60; 350 | if (A > (t + rho)) goto Step10; 351 | 352 | x1 = y+1; 353 | f1 = m+1; 354 | z = n+1-m; 355 | w = n-y+1; 356 | x2 = x1*x1; 357 | f2 = f1*f1; 358 | z2 = z*z; 359 | w2 = w*w; 360 | if (A > (xm*log(f1/x1) 361 | + (n-m+0.5)*log(z/w) 362 | + (y-m)*log(w*r/(x1*q)) 363 | + (13680.-(462.-(132.-(99.-140./f2)/f2)/f2)/f2)/f1/166320. 364 | + (13680.-(462.-(132.-(99.-140./z2)/z2)/z2)/z2)/z/166320. 365 | + (13680.-(462.-(132.-(99.-140./x2)/x2)/x2)/x2)/x1/166320. 366 | + (13680.-(462.-(132.-(99.-140./w2)/w2)/w2)/w2)/w/166320.)) 367 | { 368 | goto Step10; 369 | } 370 | 371 | Step60: 372 | if (p > 0.5) 373 | { 374 | y = n - y; 375 | } 376 | 377 | return y; 378 | } 379 | 380 | long rk_binomial_inversion(rk_state *state, long n, double p) 381 | { 382 | double q, qn, np, px, U; 383 | long X, bound; 384 | 385 | if (!(state->has_binomial) || 386 | (state->nsave != n) || 387 | (state->psave != p)) 388 | { 389 | state->nsave = n; 390 | state->psave = p; 391 | state->has_binomial = 1; 392 | state->q = q = 1.0 - p; 393 | state->r = qn = exp(n * log(q)); 394 | state->c = np = n*p; 395 | state->m = bound = min(n, np + 10.0*sqrt(np*q + 1)); 396 | } else 397 | { 398 | q = state->q; 399 | qn = state->r; 400 | np = state->c; 401 | bound = state->m; 402 | } 403 | X = 0; 404 | px = qn; 405 | U = rk_double(state); 406 | while (U > px) 407 | { 408 | X++; 409 | if (X > bound) 410 | { 411 | X = 0; 412 | px = qn; 413 | U = rk_double(state); 414 | } else 415 | { 416 | U -= px; 417 | px = ((n-X+1) * p * px)/(X*q); 418 | } 419 | } 420 | return X; 421 | } 422 | 423 | long rk_binomial(rk_state *state, long n, double p) 424 | { 425 | double q; 426 | 427 | if (p <= 0.5) 428 | { 429 | if (p*n <= 30.0) 430 | { 431 | return rk_binomial_inversion(state, n, p); 432 | } 433 | else 434 | { 435 | return rk_binomial_btpe(state, n, p); 436 | } 437 | } 438 | else 439 | { 440 | q = 1.0-p; 441 | if (q*n <= 30.0) 442 | { 443 | return n - rk_binomial_inversion(state, n, q); 444 | } 445 | else 446 | { 447 | return n - rk_binomial_btpe(state, n, q); 448 | } 449 | } 450 | 451 | } 452 | 453 | long rk_negative_binomial(rk_state *state, double n, double p) 454 | { 455 | double Y; 456 | 457 | Y = rk_gamma(state, n, (1-p)/p); 458 | return rk_poisson(state, Y); 459 | } 460 | 461 | long rk_poisson_mult(rk_state *state, double lam) 462 | { 463 | long X; 464 | double prod, U, enlam; 465 | 466 | enlam = exp(-lam); 467 | X = 0; 468 | prod = 1.0; 469 | while (1) 470 | { 471 | U = rk_double(state); 472 | prod *= U; 473 | if (prod > enlam) 474 | { 475 | X += 1; 476 | } 477 | else 478 | { 479 | return X; 480 | } 481 | } 482 | } 483 | 484 | #define LS2PI 0.91893853320467267 485 | #define TWELFTH 0.083333333333333333333333 486 | long rk_poisson_ptrs(rk_state *state, double lam) 487 | { 488 | long k; 489 | double U, V, slam, loglam, a, b, invalpha, vr, us; 490 | 491 | slam = sqrt(lam); 492 | loglam = log(lam); 493 | b = 0.931 + 2.53*slam; 494 | a = -0.059 + 0.02483*b; 495 | invalpha = 1.1239 + 1.1328/(b-3.4); 496 | vr = 0.9277 - 3.6224/(b-2); 497 | 498 | while (1) 499 | { 500 | U = rk_double(state) - 0.5; 501 | V = rk_double(state); 502 | us = 0.5 - fabs(U); 503 | k = (long)floor((2*a/us + b)*U + lam + 0.43); 504 | if ((us >= 0.07) && (V <= vr)) 505 | { 506 | return k; 507 | } 508 | if ((k < 0) || 509 | ((us < 0.013) && (V > us))) 510 | { 511 | continue; 512 | } 513 | if ((log(V) + log(invalpha) - log(a/(us*us)+b)) <= 514 | (-lam + k*loglam - loggam(k+1))) 515 | { 516 | return k; 517 | } 518 | 519 | 520 | } 521 | 522 | } 523 | 524 | long rk_poisson(rk_state *state, double lam) 525 | { 526 | if (lam >= 10) 527 | { 528 | return rk_poisson_ptrs(state, lam); 529 | } 530 | else if (lam == 0) 531 | { 532 | return 0; 533 | } 534 | else 535 | { 536 | return rk_poisson_mult(state, lam); 537 | } 538 | } 539 | 540 | double rk_standard_cauchy(rk_state *state) 541 | { 542 | return rk_gauss(state) / rk_gauss(state); 543 | } 544 | 545 | double rk_standard_t(rk_state *state, double df) 546 | { 547 | double N, G, X; 548 | 549 | N = rk_gauss(state); 550 | G = rk_standard_gamma(state, df/2); 551 | X = sqrt(df/2)*N/sqrt(G); 552 | return X; 553 | } 554 | 555 | /* Uses the rejection algorithm compared against the wrapped Cauchy 556 | distribution suggested by Best and Fisher and documented in 557 | Chapter 9 of Luc's Non-Uniform Random Variate Generation. 558 | http://cg.scs.carleton.ca/~luc/rnbookindex.html 559 | (but corrected to match the algorithm in R and Python) 560 | */ 561 | double rk_vonmises(rk_state *state, double mu, double kappa) 562 | { 563 | double r, rho, s; 564 | double U, V, W, Y, Z; 565 | double result, mod; 566 | int neg; 567 | 568 | if (kappa < 1e-8) 569 | { 570 | return M_PI * (2*rk_double(state)-1); 571 | } 572 | else 573 | { 574 | r = 1 + sqrt(1 + 4*kappa*kappa); 575 | rho = (r - sqrt(2*r))/(2*kappa); 576 | s = (1 + rho*rho)/(2*rho); 577 | 578 | while (1) 579 | { 580 | U = rk_double(state); 581 | Z = cos(M_PI*U); 582 | W = (1 + s*Z)/(s + Z); 583 | Y = kappa * (s - W); 584 | V = rk_double(state); 585 | if ((Y*(2-Y) - V >= 0) || (log(Y/V)+1 - Y >= 0)) 586 | { 587 | break; 588 | } 589 | } 590 | 591 | U = rk_double(state); 592 | 593 | result = acos(W); 594 | if (U < 0.5) 595 | { 596 | result = -result; 597 | } 598 | result += mu; 599 | neg = (result < 0); 600 | mod = fabs(result); 601 | mod = (fmod(mod+M_PI, 2*M_PI)-M_PI); 602 | if (neg) 603 | { 604 | mod *= -1; 605 | } 606 | 607 | return mod; 608 | } 609 | } 610 | 611 | double rk_pareto(rk_state *state, double a) 612 | { 613 | return exp(rk_standard_exponential(state)/a) - 1; 614 | } 615 | 616 | double rk_weibull(rk_state *state, double a) 617 | { 618 | return pow(rk_standard_exponential(state), 1./a); 619 | } 620 | 621 | double rk_power(rk_state *state, double a) 622 | { 623 | return pow(1 - exp(-rk_standard_exponential(state)), 1./a); 624 | } 625 | 626 | double rk_laplace(rk_state *state, double loc, double scale) 627 | { 628 | double U; 629 | 630 | U = rk_double(state); 631 | if (U < 0.5) 632 | { 633 | U = loc + scale * log(U + U); 634 | } else 635 | { 636 | U = loc - scale * log(2.0 - U - U); 637 | } 638 | return U; 639 | } 640 | 641 | double rk_gumbel(rk_state *state, double loc, double scale) 642 | { 643 | double U; 644 | 645 | U = 1.0 - rk_double(state); 646 | return loc - scale * log(-log(U)); 647 | } 648 | 649 | double rk_logistic(rk_state *state, double loc, double scale) 650 | { 651 | double U; 652 | 653 | U = rk_double(state); 654 | return loc + scale * log(U/(1.0 - U)); 655 | } 656 | 657 | double rk_lognormal(rk_state *state, double mean, double sigma) 658 | { 659 | return exp(rk_normal(state, mean, sigma)); 660 | } 661 | 662 | double rk_rayleigh(rk_state *state, double mode) 663 | { 664 | return mode*sqrt(-2.0 * log(1.0 - rk_double(state))); 665 | } 666 | 667 | double rk_wald(rk_state *state, double mean, double scale) 668 | { 669 | double U, X, Y; 670 | double mu_2l; 671 | 672 | mu_2l = mean / (2*scale); 673 | Y = rk_gauss(state); 674 | Y = mean*Y*Y; 675 | X = mean + mu_2l*(Y - sqrt(4*scale*Y + Y*Y)); 676 | U = rk_double(state); 677 | if (U <= mean/(mean+X)) 678 | { 679 | return X; 680 | } else 681 | { 682 | return mean*mean/X; 683 | } 684 | } 685 | 686 | long rk_zipf(rk_state *state, double a) 687 | { 688 | double T, U, V; 689 | long X; 690 | double am1, b; 691 | 692 | am1 = a - 1.0; 693 | b = pow(2.0, am1); 694 | do 695 | { 696 | U = 1.0-rk_double(state); 697 | V = rk_double(state); 698 | X = (long)floor(pow(U, -1.0/am1)); 699 | /* The real result may be above what can be represented in a signed 700 | * long. It will get casted to -sys.maxint-1. Since this is 701 | * a straightforward rejection algorithm, we can just reject this value 702 | * in the rejection condition below. This function then models a Zipf 703 | * distribution truncated to sys.maxint. 704 | */ 705 | T = pow(1.0 + 1.0/X, am1); 706 | } while (((V*X*(T-1.0)/(b-1.0)) > (T/b)) || X < 1); 707 | return X; 708 | } 709 | 710 | long rk_geometric_search(rk_state *state, double p) 711 | { 712 | double U; 713 | long X; 714 | double sum, prod, q; 715 | 716 | X = 1; 717 | sum = prod = p; 718 | q = 1.0 - p; 719 | U = rk_double(state); 720 | while (U > sum) 721 | { 722 | prod *= q; 723 | sum += prod; 724 | X++; 725 | } 726 | return X; 727 | } 728 | 729 | long rk_geometric_inversion(rk_state *state, double p) 730 | { 731 | return (long)ceil(log(1.0-rk_double(state))/log(1.0-p)); 732 | } 733 | 734 | long rk_geometric(rk_state *state, double p) 735 | { 736 | if (p >= 0.333333333333333333333333) 737 | { 738 | return rk_geometric_search(state, p); 739 | } else 740 | { 741 | return rk_geometric_inversion(state, p); 742 | } 743 | } 744 | 745 | long rk_hypergeometric_hyp(rk_state *state, long good, long bad, long sample) 746 | { 747 | long d1, K, Z; 748 | double d2, U, Y; 749 | 750 | d1 = bad + good - sample; 751 | d2 = (double)min(bad, good); 752 | 753 | Y = d2; 754 | K = sample; 755 | while (Y > 0.0) 756 | { 757 | U = rk_double(state); 758 | Y -= (long)floor(U + Y/(d1 + K)); 759 | K--; 760 | if (K == 0) break; 761 | } 762 | Z = (long)(d2 - Y); 763 | if (good > bad) Z = sample - Z; 764 | return Z; 765 | } 766 | 767 | /* D1 = 2*sqrt(2/e) */ 768 | /* D2 = 3 - 2*sqrt(3/e) */ 769 | #define D1 1.7155277699214135 770 | #define D2 0.8989161620588988 771 | long rk_hypergeometric_hrua(rk_state *state, long good, long bad, long sample) 772 | { 773 | long mingoodbad, maxgoodbad, popsize, m, d9; 774 | double d4, d5, d6, d7, d8, d10, d11; 775 | long Z; 776 | double T, W, X, Y; 777 | 778 | mingoodbad = min(good, bad); 779 | popsize = good + bad; 780 | maxgoodbad = max(good, bad); 781 | m = min(sample, popsize - sample); 782 | d4 = ((double)mingoodbad) / popsize; 783 | d5 = 1.0 - d4; 784 | d6 = m*d4 + 0.5; 785 | d7 = sqrt((popsize - m) * sample * d4 *d5 / (popsize-1) + 0.5); 786 | d8 = D1*d7 + D2; 787 | d9 = (long)floor((double)((m+1)*(mingoodbad+1))/(popsize+2)); 788 | d10 = (loggam(d9+1) + loggam(mingoodbad-d9+1) + loggam(m-d9+1) + 789 | loggam(maxgoodbad-m+d9+1)); 790 | d11 = min(min(m, mingoodbad)+1.0, floor(d6+16*d7)); 791 | /* 16 for 16-decimal-digit precision in D1 and D2 */ 792 | 793 | while (1) 794 | { 795 | X = rk_double(state); 796 | Y = rk_double(state); 797 | W = d6 + d8*(Y- 0.5)/X; 798 | 799 | /* fast rejection: */ 800 | if ((W < 0.0) || (W >= d11)) continue; 801 | 802 | Z = (long)floor(W); 803 | T = d10 - (loggam(Z+1) + loggam(mingoodbad-Z+1) + loggam(m-Z+1) + 804 | loggam(maxgoodbad-m+Z+1)); 805 | 806 | /* fast acceptance: */ 807 | if ((X*(4.0-X)-3.0) <= T) break; 808 | 809 | /* fast rejection: */ 810 | if (X*(X-T) >= 1) continue; 811 | 812 | if (2.0*log(X) <= T) break; /* acceptance */ 813 | } 814 | 815 | /* this is a correction to HRUA* by Ivan Frohne in rv.py */ 816 | if (good > bad) Z = m - Z; 817 | 818 | /* another fix from rv.py to allow sample to exceed popsize/2 */ 819 | if (m < sample) Z = good - Z; 820 | 821 | return Z; 822 | } 823 | #undef D1 824 | #undef D2 825 | 826 | long rk_hypergeometric(rk_state *state, long good, long bad, long sample) 827 | { 828 | if (sample > 10) 829 | { 830 | return rk_hypergeometric_hrua(state, good, bad, sample); 831 | } else 832 | { 833 | return rk_hypergeometric_hyp(state, good, bad, sample); 834 | } 835 | } 836 | 837 | double rk_triangular(rk_state *state, double left, double mode, double right) 838 | { 839 | double base, leftbase, ratio, leftprod, rightprod; 840 | double U; 841 | 842 | base = right - left; 843 | leftbase = mode - left; 844 | ratio = leftbase / base; 845 | leftprod = leftbase*base; 846 | rightprod = (right - mode)*base; 847 | 848 | U = rk_double(state); 849 | if (U <= ratio) 850 | { 851 | return left + sqrt(U*leftprod); 852 | } else 853 | { 854 | return right - sqrt((1.0 - U) * rightprod); 855 | } 856 | } 857 | 858 | long rk_logseries(rk_state *state, double p) 859 | { 860 | double q, r, U, V; 861 | long result; 862 | 863 | r = log(1.0 - p); 864 | 865 | while (1) { 866 | V = rk_double(state); 867 | if (V >= p) { 868 | return 1; 869 | } 870 | U = rk_double(state); 871 | q = 1.0 - exp(r*U); 872 | if (V <= q*q) { 873 | result = (long)floor(1 + log(V)/log(q)); 874 | if (result < 1) { 875 | continue; 876 | } 877 | else { 878 | return result; 879 | } 880 | } 881 | if (V >= q) { 882 | return 1; 883 | } 884 | return 2; 885 | } 886 | } 887 | -------------------------------------------------------------------------------- /randomkit/distributions.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2005 Robert Kern (robert.kern@gmail.com) 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a 4 | * copy of this software and associated documentation files (the 5 | * "Software"), to deal in the Software without restriction, including 6 | * without limitation the rights to use, copy, modify, merge, publish, 7 | * distribute, sublicense, and/or sell copies of the Software, and to 8 | * permit persons to whom the Software is furnished to do so, subject to 9 | * the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included 12 | * in all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef _RK_DISTR_ 24 | #define _RK_DISTR_ 25 | 26 | #include "randomkit.h" 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /* References: 33 | * 34 | * Devroye, Luc. _Non-Uniform Random Variate Generation_. 35 | * Springer-Verlag, New York, 1986. 36 | * http://cgm.cs.mcgill.ca/~luc/rnbookindex.html 37 | * 38 | * Kachitvichyanukul, V. and Schmeiser, B. W. Binomial Random Variate 39 | * Generation. Communications of the ACM, 31, 2 (February, 1988) 216. 40 | * 41 | * Hoermann, W. The Transformed Rejection Method for Generating Poisson Random 42 | * Variables. Insurance: Mathematics and Economics, (to appear) 43 | * http://citeseer.csail.mit.edu/151115.html 44 | * 45 | * Marsaglia, G. and Tsang, W. W. A Simple Method for Generating Gamma 46 | * Variables. ACM Transactions on Mathematical Software, Vol. 26, No. 3, 47 | * September 2000, Pages 363–372. 48 | */ 49 | 50 | /* Normal distribution with mean=loc and standard deviation=scale. */ 51 | extern double rk_normal(rk_state *state, double loc, double scale); 52 | 53 | /* Standard exponential distribution (mean=1) computed by inversion of the 54 | * CDF. */ 55 | extern double rk_standard_exponential(rk_state *state); 56 | 57 | /* Exponential distribution with mean=scale. */ 58 | extern double rk_exponential(rk_state *state, double scale); 59 | 60 | /* Uniform distribution on interval [loc, loc+scale). */ 61 | extern double rk_uniform(rk_state *state, double loc, double scale); 62 | 63 | /* Standard gamma distribution with shape parameter. 64 | * When shape < 1, the algorithm given by (Devroye p. 304) is used. 65 | * When shape == 1, a Exponential variate is generated. 66 | * When shape > 1, the small and fast method of (Marsaglia and Tsang 2000) 67 | * is used. 68 | */ 69 | extern double rk_standard_gamma(rk_state *state, double shape); 70 | 71 | /* Gamma distribution with shape and scale. */ 72 | extern double rk_gamma(rk_state *state, double shape, double scale); 73 | 74 | /* Beta distribution computed by combining two gamma variates (Devroye p. 432). 75 | */ 76 | extern double rk_beta(rk_state *state, double a, double b); 77 | 78 | /* Chi^2 distribution computed by transforming a gamma variate (it being a 79 | * special case Gamma(df/2, 2)). */ 80 | extern double rk_chisquare(rk_state *state, double df); 81 | 82 | /* Noncentral Chi^2 distribution computed by modifying a Chi^2 variate. */ 83 | extern double rk_noncentral_chisquare(rk_state *state, double df, double nonc); 84 | 85 | /* F distribution computed by taking the ratio of two Chi^2 variates. */ 86 | extern double rk_f(rk_state *state, double dfnum, double dfden); 87 | 88 | /* Noncentral F distribution computed by taking the ratio of a noncentral Chi^2 89 | * and a Chi^2 variate. */ 90 | extern double rk_noncentral_f(rk_state *state, double dfnum, double dfden, double nonc); 91 | 92 | /* Binomial distribution with n Bernoulli trials with success probability p. 93 | * When n*p <= 30, the "Second waiting time method" given by (Devroye p. 525) is 94 | * used. Otherwise, the BTPE algorithm of (Kachitvichyanukul and Schmeiser 1988) 95 | * is used. */ 96 | extern long rk_binomial(rk_state *state, long n, double p); 97 | 98 | /* Binomial distribution using BTPE. */ 99 | extern long rk_binomial_btpe(rk_state *state, long n, double p); 100 | 101 | /* Binomial distribution using inversion and chop-down */ 102 | extern long rk_binomial_inversion(rk_state *state, long n, double p); 103 | 104 | /* Negative binomial distribution computed by generating a Gamma(n, (1-p)/p) 105 | * variate Y and returning a Poisson(Y) variate (Devroye p. 543). */ 106 | extern long rk_negative_binomial(rk_state *state, double n, double p); 107 | 108 | /* Poisson distribution with mean=lam. 109 | * When lam < 10, a basic algorithm using repeated multiplications of uniform 110 | * variates is used (Devroye p. 504). 111 | * When lam >= 10, algorithm PTRS from (Hoermann 1992) is used. 112 | */ 113 | extern long rk_poisson(rk_state *state, double lam); 114 | 115 | /* Poisson distribution computed by repeated multiplication of uniform variates. 116 | */ 117 | extern long rk_poisson_mult(rk_state *state, double lam); 118 | 119 | /* Poisson distribution computer by the PTRS algorithm. */ 120 | extern long rk_poisson_ptrs(rk_state *state, double lam); 121 | 122 | /* Standard Cauchy distribution computed by dividing standard gaussians 123 | * (Devroye p. 451). */ 124 | extern double rk_standard_cauchy(rk_state *state); 125 | 126 | /* Standard t-distribution with df degrees of freedom (Devroye p. 445 as 127 | * corrected in the Errata). */ 128 | extern double rk_standard_t(rk_state *state, double df); 129 | 130 | /* von Mises circular distribution with center mu and shape kappa on [-pi,pi] 131 | * (Devroye p. 476 as corrected in the Errata). */ 132 | extern double rk_vonmises(rk_state *state, double mu, double kappa); 133 | 134 | /* Pareto distribution via inversion (Devroye p. 262) */ 135 | extern double rk_pareto(rk_state *state, double a); 136 | 137 | /* Weibull distribution via inversion (Devroye p. 262) */ 138 | extern double rk_weibull(rk_state *state, double a); 139 | 140 | /* Power distribution via inversion (Devroye p. 262) */ 141 | extern double rk_power(rk_state *state, double a); 142 | 143 | /* Laplace distribution */ 144 | extern double rk_laplace(rk_state *state, double loc, double scale); 145 | 146 | /* Gumbel distribution */ 147 | extern double rk_gumbel(rk_state *state, double loc, double scale); 148 | 149 | /* Logistic distribution */ 150 | extern double rk_logistic(rk_state *state, double loc, double scale); 151 | 152 | /* Log-normal distribution */ 153 | extern double rk_lognormal(rk_state *state, double mean, double sigma); 154 | 155 | /* Rayleigh distribution */ 156 | extern double rk_rayleigh(rk_state *state, double mode); 157 | 158 | /* Wald distribution */ 159 | extern double rk_wald(rk_state *state, double mean, double scale); 160 | 161 | /* Zipf distribution */ 162 | extern long rk_zipf(rk_state *state, double a); 163 | 164 | /* Geometric distribution */ 165 | extern long rk_geometric(rk_state *state, double p); 166 | extern long rk_geometric_search(rk_state *state, double p); 167 | extern long rk_geometric_inversion(rk_state *state, double p); 168 | 169 | /* Hypergeometric distribution */ 170 | extern long rk_hypergeometric(rk_state *state, long good, long bad, long sample); 171 | extern long rk_hypergeometric_hyp(rk_state *state, long good, long bad, long sample); 172 | extern long rk_hypergeometric_hrua(rk_state *state, long good, long bad, long sample); 173 | 174 | /* Triangular distribution */ 175 | extern double rk_triangular(rk_state *state, double left, double mode, double right); 176 | 177 | /* Logarithmic series distribution */ 178 | extern long rk_logseries(rk_state *state, double p); 179 | 180 | #ifdef __cplusplus 181 | } 182 | #endif 183 | 184 | 185 | #endif /* _RK_DISTR_ */ 186 | -------------------------------------------------------------------------------- /randomkit/randomkit.c: -------------------------------------------------------------------------------- 1 | /* Random kit 1.3 */ 2 | 3 | /* 4 | * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org) 5 | * 6 | * The rk_random and rk_seed functions algorithms and the original design of 7 | * the Mersenne Twister RNG: 8 | * 9 | * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 10 | * All rights reserved. 11 | * 12 | * Redistribution and use in source and binary forms, with or without 13 | * modification, are permitted provided that the following conditions 14 | * are met: 15 | * 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 19 | * 2. Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in the 21 | * documentation and/or other materials provided with the distribution. 22 | * 23 | * 3. The names of its contributors may not be used to endorse or promote 24 | * products derived from this software without specific prior written 25 | * permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 31 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 32 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 33 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 34 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 35 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 36 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | * 39 | * Original algorithm for the implementation of rk_interval function from 40 | * Richard J. Wagner's implementation of the Mersenne Twister RNG, optimised by 41 | * Magnus Jonsson. 42 | * 43 | * Constants used in the rk_double implementation by Isaku Wada. 44 | * 45 | * Permission is hereby granted, free of charge, to any person obtaining a 46 | * copy of this software and associated documentation files (the 47 | * "Software"), to deal in the Software without restriction, including 48 | * without limitation the rights to use, copy, modify, merge, publish, 49 | * distribute, sublicense, and/or sell copies of the Software, and to 50 | * permit persons to whom the Software is furnished to do so, subject to 51 | * the following conditions: 52 | * 53 | * The above copyright notice and this permission notice shall be included 54 | * in all copies or substantial portions of the Software. 55 | * 56 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 57 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 58 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 59 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 60 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 61 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 62 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 63 | */ 64 | 65 | /* static char const rcsid[] = 66 | "@(#) $Jeannot: randomkit.c,v 1.28 2005/07/21 22:14:09 js Exp $"; */ 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | #include 74 | 75 | #ifdef _WIN32 76 | /* 77 | * Windows 78 | * XXX: we have to use this ugly defined(__GNUC__) because it is not easy to 79 | * detect the compiler used in distutils itself 80 | */ 81 | #if (defined(__GNUC__) && defined(NPY_NEEDS_MINGW_TIME_WORKAROUND)) 82 | 83 | /* 84 | * FIXME: ideally, we should set this to the real version of MSVCRT. We need 85 | * something higher than 0x601 to enable _ftime64 and co 86 | */ 87 | #define __MSVCRT_VERSION__ 0x0700 88 | #include 89 | #include 90 | 91 | /* 92 | * mingw msvcr lib import wrongly export _ftime, which does not exist in the 93 | * actual msvc runtime for version >= 8; we make it an alias to _ftime64, which 94 | * is available in those versions of the runtime 95 | */ 96 | #define _FTIME(x) _ftime64((x)) 97 | #else 98 | #include 99 | #include 100 | #define _FTIME(x) _ftime((x)) 101 | #endif 102 | 103 | #ifndef RK_NO_WINCRYPT 104 | /* Windows crypto */ 105 | #ifndef _WIN32_WINNT 106 | #define _WIN32_WINNT 0x0400 107 | #endif 108 | #include 109 | #include 110 | #endif 111 | 112 | #else 113 | /* Unix */ 114 | #include 115 | #include 116 | #include 117 | #endif 118 | 119 | #include "randomkit.h" 120 | 121 | #ifndef RK_DEV_URANDOM 122 | #define RK_DEV_URANDOM "/dev/urandom" 123 | #endif 124 | 125 | #ifndef RK_DEV_RANDOM 126 | #define RK_DEV_RANDOM "/dev/random" 127 | #endif 128 | 129 | char *rk_strerror[RK_ERR_MAX] = 130 | { 131 | "no error", 132 | "random device unvavailable" 133 | }; 134 | 135 | /* static functions */ 136 | static unsigned long rk_hash(unsigned long key); 137 | 138 | void 139 | rk_seed(unsigned long seed, rk_state *state) 140 | { 141 | int pos; 142 | seed &= 0xffffffffUL; 143 | 144 | /* Knuth's PRNG as used in the Mersenne Twister reference implementation */ 145 | for (pos = 0; pos < RK_STATE_LEN; pos++) { 146 | state->key[pos] = seed; 147 | seed = (1812433253UL * (seed ^ (seed >> 30)) + pos + 1) & 0xffffffffUL; 148 | } 149 | state->pos = RK_STATE_LEN; 150 | state->gauss = 0; 151 | state->has_gauss = 0; 152 | state->has_binomial = 0; 153 | } 154 | 155 | /* Thomas Wang 32 bits integer hash function */ 156 | unsigned long 157 | rk_hash(unsigned long key) 158 | { 159 | key += ~(key << 15); 160 | key ^= (key >> 10); 161 | key += (key << 3); 162 | key ^= (key >> 6); 163 | key += ~(key << 11); 164 | key ^= (key >> 16); 165 | return key; 166 | } 167 | 168 | rk_error 169 | rk_randomseed(rk_state *state) 170 | { 171 | #ifndef _WIN32 172 | struct timeval tv; 173 | #else 174 | struct _timeb tv; 175 | #endif 176 | int i; 177 | 178 | if (rk_devfill(state->key, sizeof(state->key), 0) == RK_NOERR) { 179 | /* ensures non-zero key */ 180 | state->key[0] |= 0x80000000UL; 181 | state->pos = RK_STATE_LEN; 182 | state->gauss = 0; 183 | state->has_gauss = 0; 184 | state->has_binomial = 0; 185 | 186 | for (i = 0; i < 624; i++) { 187 | state->key[i] &= 0xffffffffUL; 188 | } 189 | return RK_NOERR; 190 | } 191 | 192 | #ifndef _WIN32 193 | gettimeofday(&tv, NULL); 194 | rk_seed(rk_hash(getpid()) ^ rk_hash(tv.tv_sec) ^ rk_hash(tv.tv_usec) 195 | ^ rk_hash(clock()), state); 196 | #else 197 | _FTIME(&tv); 198 | rk_seed(rk_hash(tv.time) ^ rk_hash(tv.millitm) ^ rk_hash(clock()), state); 199 | #endif 200 | 201 | return RK_ENODEV; 202 | } 203 | 204 | /* Magic Mersenne Twister constants */ 205 | #define N 624 206 | #define M 397 207 | #define MATRIX_A 0x9908b0dfUL 208 | #define UPPER_MASK 0x80000000UL 209 | #define LOWER_MASK 0x7fffffffUL 210 | 211 | /* Slightly optimised reference implementation of the Mersenne Twister */ 212 | unsigned long 213 | rk_random(rk_state *state) 214 | { 215 | return THRandom_random(state->torch_state); 216 | 217 | /* if(state->pos == RK_STATE_LEN) { 218 | int i; 219 | 220 | for (i = 0; i < N - M; i++) { 221 | y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK); 222 | state->key[i] = state->key[i+M] ^ (y>>1) ^ (-(y & 1) & MATRIX_A); 223 | } 224 | for (; i < N - 1; i++) { 225 | y = (state->key[i] & UPPER_MASK) | (state->key[i+1] & LOWER_MASK); 226 | state->key[i] = state->key[i+(M-N)] ^ (y>>1) ^ (-(y & 1) & MATRIX_A); 227 | } 228 | y = (state->key[N - 1] & UPPER_MASK) | (state->key[0] & LOWER_MASK); 229 | state->key[N - 1] = state->key[M - 1] ^ (y >> 1) ^ (-(y & 1) & MATRIX_A); 230 | 231 | state->pos = 0; 232 | } 233 | y = state->key[state->pos++]; 234 | */ 235 | /* Tempering */ 236 | /* y ^= (y >> 11); 237 | y ^= (y << 7) & 0x9d2c5680UL; 238 | y ^= (y << 15) & 0xefc60000UL; 239 | y ^= (y >> 18); 240 | 241 | return y; */ 242 | } 243 | 244 | long 245 | rk_long(rk_state *state) 246 | { 247 | return rk_ulong(state) >> 1; 248 | } 249 | 250 | unsigned long 251 | rk_ulong(rk_state *state) 252 | { 253 | #if ULONG_MAX <= 0xffffffffUL 254 | return rk_random(state); 255 | #else 256 | return (rk_random(state) << 32) | (rk_random(state)); 257 | #endif 258 | } 259 | 260 | unsigned long 261 | rk_interval(unsigned long max, rk_state *state) 262 | { 263 | unsigned long mask = max, value; 264 | 265 | if (max == 0) { 266 | return 0; 267 | } 268 | /* Smallest bit mask >= max */ 269 | mask |= mask >> 1; 270 | mask |= mask >> 2; 271 | mask |= mask >> 4; 272 | mask |= mask >> 8; 273 | mask |= mask >> 16; 274 | #if ULONG_MAX > 0xffffffffUL 275 | mask |= mask >> 32; 276 | #endif 277 | 278 | /* Search a random value in [0..mask] <= max */ 279 | #if ULONG_MAX > 0xffffffffUL 280 | if (max <= 0xffffffffUL) { 281 | while ((value = (rk_random(state) & mask)) > max); 282 | } 283 | else { 284 | while ((value = (rk_ulong(state) & mask)) > max); 285 | } 286 | #else 287 | while ((value = (rk_ulong(state) & mask)) > max); 288 | #endif 289 | return value; 290 | } 291 | 292 | double 293 | rk_double(rk_state *state) 294 | { 295 | /* shifts : 67108864 = 0x4000000, 9007199254740992 = 0x20000000000000 */ 296 | long a = rk_random(state) >> 5, b = rk_random(state) >> 6; 297 | return (a * 67108864.0 + b) / 9007199254740992.0; 298 | } 299 | 300 | void 301 | rk_fill(void *buffer, size_t size, rk_state *state) 302 | { 303 | unsigned long r; 304 | unsigned char *buf = buffer; 305 | 306 | for (; size >= 4; size -= 4) { 307 | r = rk_random(state); 308 | *(buf++) = r & 0xFF; 309 | *(buf++) = (r >> 8) & 0xFF; 310 | *(buf++) = (r >> 16) & 0xFF; 311 | *(buf++) = (r >> 24) & 0xFF; 312 | } 313 | 314 | if (!size) { 315 | return; 316 | } 317 | r = rk_random(state); 318 | for (; size; r >>= 8, size --) { 319 | *(buf++) = (unsigned char)(r & 0xFF); 320 | } 321 | } 322 | 323 | rk_error 324 | rk_devfill(void *buffer, size_t size, int strong) 325 | { 326 | #ifndef _WIN32 327 | FILE *rfile; 328 | int done; 329 | 330 | if (strong) { 331 | rfile = fopen(RK_DEV_RANDOM, "rb"); 332 | } 333 | else { 334 | rfile = fopen(RK_DEV_URANDOM, "rb"); 335 | } 336 | if (rfile == NULL) { 337 | return RK_ENODEV; 338 | } 339 | done = fread(buffer, size, 1, rfile); 340 | fclose(rfile); 341 | if (done) { 342 | return RK_NOERR; 343 | } 344 | #else 345 | 346 | #ifndef RK_NO_WINCRYPT 347 | HCRYPTPROV hCryptProv; 348 | BOOL done; 349 | 350 | if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 351 | CRYPT_VERIFYCONTEXT) || !hCryptProv) { 352 | return RK_ENODEV; 353 | } 354 | done = CryptGenRandom(hCryptProv, size, (unsigned char *)buffer); 355 | CryptReleaseContext(hCryptProv, 0); 356 | if (done) { 357 | return RK_NOERR; 358 | } 359 | #endif 360 | 361 | #endif 362 | return RK_ENODEV; 363 | } 364 | 365 | rk_error 366 | rk_altfill(void *buffer, size_t size, int strong, rk_state *state) 367 | { 368 | rk_error err; 369 | 370 | err = rk_devfill(buffer, size, strong); 371 | if (err) { 372 | rk_fill(buffer, size, state); 373 | } 374 | return err; 375 | } 376 | 377 | double 378 | rk_gauss(rk_state *state) 379 | { 380 | if (state->has_gauss) { 381 | const double tmp = state->gauss; 382 | state->gauss = 0; 383 | state->has_gauss = 0; 384 | return tmp; 385 | } 386 | else { 387 | double f, x1, x2, r2; 388 | 389 | do { 390 | x1 = 2.0*rk_double(state) - 1.0; 391 | x2 = 2.0*rk_double(state) - 1.0; 392 | r2 = x1*x1 + x2*x2; 393 | } 394 | while (r2 >= 1.0 || r2 == 0.0); 395 | 396 | /* Box-Muller transform */ 397 | f = sqrt(-2.0*log(r2)/r2); 398 | /* Keep for next call */ 399 | state->gauss = f*x1; 400 | state->has_gauss = 1; 401 | return f*x2; 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /randomkit/randomkit.h: -------------------------------------------------------------------------------- 1 | /* Random kit 1.3 */ 2 | 3 | /* 4 | * Copyright (c) 2003-2005, Jean-Sebastien Roy (js@jeannot.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the 8 | * "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* @(#) $Jeannot: randomkit.h,v 1.24 2005/07/21 22:14:09 js Exp $ */ 27 | 28 | /* 29 | * Typical use: 30 | * 31 | * { 32 | * rk_state state; 33 | * unsigned long seed = 1, random_value; 34 | * 35 | * rk_seed(seed, &state); // Initialize the RNG 36 | * ... 37 | * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] 38 | * } 39 | * 40 | * Instead of rk_seed, you can use rk_randomseed which will get a random seed 41 | * from /dev/urandom (or the clock, if /dev/urandom is unavailable): 42 | * 43 | * { 44 | * rk_state state; 45 | * unsigned long random_value; 46 | * 47 | * rk_randomseed(&state); // Initialize the RNG with a random seed 48 | * ... 49 | * random_value = rk_random(&state); // Generate random values in [0..RK_MAX] 50 | * } 51 | */ 52 | 53 | /* 54 | * Useful macro: 55 | * RK_DEV_RANDOM: the device used for random seeding. 56 | * defaults to "/dev/urandom" 57 | */ 58 | 59 | #include 60 | 61 | #ifndef _RANDOMKIT_ 62 | #define _RANDOMKIT_ 63 | 64 | #define RK_STATE_LEN 624 65 | 66 | typedef struct rk_state_ 67 | { 68 | struct THGenerator *torch_state; 69 | unsigned long key[RK_STATE_LEN]; 70 | int pos; 71 | int has_gauss; /* !=0: gauss contains a gaussian deviate */ 72 | double gauss; 73 | 74 | /* The rk_state structure has been extended to store the following 75 | * information for the binomial generator. If the input values of n or p 76 | * are different than nsave and psave, then the other parameters will be 77 | * recomputed. RTK 2005-09-02 */ 78 | 79 | int has_binomial; /* !=0: following parameters initialized for 80 | binomial */ 81 | double psave; 82 | long nsave; 83 | double r; 84 | double q; 85 | double fm; 86 | long m; 87 | double p1; 88 | double xm; 89 | double xl; 90 | double xr; 91 | double c; 92 | double laml; 93 | double lamr; 94 | double p2; 95 | double p3; 96 | double p4; 97 | 98 | } 99 | rk_state; 100 | 101 | typedef enum { 102 | RK_NOERR = 0, /* no error */ 103 | RK_ENODEV = 1, /* no RK_DEV_RANDOM device */ 104 | RK_ERR_MAX = 2 105 | } rk_error; 106 | 107 | /* error strings */ 108 | extern char *rk_strerror[RK_ERR_MAX]; 109 | 110 | /* Maximum generated random value */ 111 | #define RK_MAX 0xFFFFFFFFUL 112 | 113 | #ifdef __cplusplus 114 | extern "C" { 115 | #endif 116 | 117 | /* 118 | * Initialize the RNG state using the given seed. 119 | */ 120 | extern void rk_seed(unsigned long seed, rk_state *state); 121 | 122 | /* 123 | * Initialize the RNG state using a random seed. 124 | * Uses /dev/random or, when unavailable, the clock (see randomkit.c). 125 | * Returns RK_NOERR when no errors occurs. 126 | * Returns RK_ENODEV when the use of RK_DEV_RANDOM failed (for example because 127 | * there is no such device). In this case, the RNG was initialized using the 128 | * clock. 129 | */ 130 | extern rk_error rk_randomseed(rk_state *state); 131 | 132 | /* 133 | * Returns a random unsigned long between 0 and RK_MAX inclusive 134 | */ 135 | extern unsigned long rk_random(rk_state *state); 136 | 137 | /* 138 | * Returns a random long between 0 and LONG_MAX inclusive 139 | */ 140 | extern long rk_long(rk_state *state); 141 | 142 | /* 143 | * Returns a random unsigned long between 0 and ULONG_MAX inclusive 144 | */ 145 | extern unsigned long rk_ulong(rk_state *state); 146 | 147 | /* 148 | * Returns a random unsigned long between 0 and max inclusive. 149 | */ 150 | extern unsigned long rk_interval(unsigned long max, rk_state *state); 151 | 152 | /* 153 | * Returns a random double between 0.0 and 1.0, 1.0 excluded. 154 | */ 155 | extern double rk_double(rk_state *state); 156 | 157 | /* 158 | * fill the buffer with size random bytes 159 | */ 160 | extern void rk_fill(void *buffer, size_t size, rk_state *state); 161 | 162 | /* 163 | * fill the buffer with randombytes from the random device 164 | * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is 165 | * On Unix, if strong is defined, RK_DEV_RANDOM is used. If not, RK_DEV_URANDOM 166 | * is used instead. This parameter has no effect on Windows. 167 | * Warning: on most unixes RK_DEV_RANDOM will wait for enough entropy to answer 168 | * which can take a very long time on quiet systems. 169 | */ 170 | extern rk_error rk_devfill(void *buffer, size_t size, int strong); 171 | 172 | /* 173 | * fill the buffer using rk_devfill if the random device is available and using 174 | * rk_fill if is is not 175 | * parameters have the same meaning as rk_fill and rk_devfill 176 | * Returns RK_ENODEV if the device is unavailable, or RK_NOERR if it is 177 | */ 178 | extern rk_error rk_altfill(void *buffer, size_t size, int strong, 179 | rk_state *state); 180 | 181 | /* 182 | * return a random gaussian deviate with variance unity and zero mean. 183 | */ 184 | extern double rk_gauss(rk_state *state); 185 | 186 | #ifdef __cplusplus 187 | } 188 | #endif 189 | 190 | #endif /* _RANDOMKIT_ */ 191 | -------------------------------------------------------------------------------- /rocks/randomkit-0-0.rockspec: -------------------------------------------------------------------------------- 1 | package = 'randomkit' 2 | version = '0-0' 3 | 4 | source = { 5 | url = 'git://github.com/deepmind/torch-randomkit.git', 6 | branch = 'v0.0' 7 | } 8 | 9 | description = { 10 | summary = "Numpy's randomkit, wrapped for Torch", 11 | homepage = "http://deepmind.github.io/torch-randomkit", 12 | detailed = "Provides and wraps the wide array of non-uniform random variate generators from the Randomkit C library, used at the heart of NumPy and distributed with permission. Interfaced with Torch's RNG functions to keep one single stream.", 13 | license = "BSD", 14 | maintainer = "Julien Cornebise " 15 | } 16 | 17 | dependencies = { 'torch >= 7.0', 'cephes'} 18 | build = { 19 | type = "command", 20 | build_command = [[ 21 | cmake -E make_directory build; 22 | cd build; 23 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$(LUA_BINDIR)/.." -DCMAKE_INSTALL_PREFIX="$(PREFIX)"; 24 | $(MAKE) 25 | ]], 26 | install_command = "cd build && $(MAKE) install" 27 | } 28 | -------------------------------------------------------------------------------- /rocks/randomkit-0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = 'randomkit' 2 | version = '0-1' 3 | 4 | source = { 5 | url = 'git://github.com/deepmind/torch-randomkit.git', 6 | branch = 'v0.1' 7 | } 8 | 9 | description = { 10 | summary = "Numpy's randomkit, wrapped for Torch", 11 | homepage = "http://deepmind.github.io/torch-randomkit", 12 | detailed = "Provides and wraps the wide array of non-uniform random variate generators from the Randomkit C library, used at the heart of NumPy and distributed with permission. Interfaced with Torch's RNG functions to keep one single stream.", 13 | license = "BSD", 14 | maintainer = "Julien Cornebise " 15 | } 16 | 17 | dependencies = { 'torch >= 7.0', 'cephes'} 18 | build = { 19 | type = "command", 20 | build_command = [[ 21 | cmake -E make_directory build; 22 | cd build; 23 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$(LUA_BINDIR)/.." -DCMAKE_INSTALL_PREFIX="$(PREFIX)"; 24 | $(MAKE) 25 | ]], 26 | install_command = "cd build && $(MAKE) install" 27 | } 28 | -------------------------------------------------------------------------------- /rocks/randomkit-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = 'randomkit' 2 | version = 'scm-1' 3 | 4 | source = { 5 | url = 'git://github.com/deepmind/torch-randomkit.git', 6 | branch = 'master' 7 | } 8 | 9 | description = { 10 | summary = "Numpy's randomkit, wrapped for Torch", 11 | homepage = "http://deepmind.github.io/torch-randomkit", 12 | detailed = "Provides and wraps the wide array of non-uniform random variate generators from the Randomkit C library, used at the heart of NumPy and distributed with permission. Interfaced with Torch's RNG functions to keep one single stream.", 13 | license = "BSD", 14 | maintainer = "Julien Cornebise " 15 | } 16 | 17 | dependencies = { 'torch >= 7.0', 'cephes', 'totem'} 18 | build = { 19 | type = "command", 20 | build_command = [[ 21 | cmake -E make_directory build; 22 | cd build; 23 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$(LUA_BINDIR)/.." -DCMAKE_INSTALL_PREFIX="$(PREFIX)"; 24 | $(MAKE) 25 | ]], 26 | install_command = "cd build && $(MAKE) install" 27 | } 28 | --------------------------------------------------------------------------------