{"id":17737745,"url":"https://github.com/tdegeus/prrng","last_synced_at":"2026-02-28T06:14:56.100Z","repository":{"id":40316675,"uuid":"357600708","full_name":"tdegeus/prrng","owner":"tdegeus","description":"Portable Reconstructible (Pseudo!) Random Number Generator","archived":false,"fork":false,"pushed_at":"2023-11-28T09:45:40.000Z","size":819,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-04-16T06:53:19.275Z","etag":null,"topics":["conda","cpp","python","random-number-generators","xtensor"],"latest_commit_sha":null,"homepage":"https://tdegeus.github.io/prrng","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tdegeus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-04-13T15:24:44.000Z","updated_at":"2022-02-18T15:59:56.000Z","dependencies_parsed_at":"2023-01-31T23:46:51.078Z","dependency_job_id":"cfd7c5bd-c1d4-4f13-9a2a-10978ab893e5","html_url":"https://github.com/tdegeus/prrng","commit_stats":{"total_commits":187,"total_committers":3,"mean_commits":"62.333333333333336","dds":0.106951871657754,"last_synced_commit":"0fa25df4d3378a57dfc0c2c2a1268cf2b726a396"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdegeus%2Fprrng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdegeus%2Fprrng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdegeus%2Fprrng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tdegeus%2Fprrng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tdegeus","download_url":"https://codeload.github.com/tdegeus/prrng/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247631832,"owners_count":20970069,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["conda","cpp","python","random-number-generators","xtensor"],"created_at":"2024-10-26T01:42:34.388Z","updated_at":"2026-02-28T06:14:51.081Z","avatar_url":"https://github.com/tdegeus.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# prrng\n\n[![CI](https://github.com/tdegeus/prrng/workflows/CI/badge.svg)](https://github.com/tdegeus/prrng/actions)\n[![Doxygen -\u003e gh-pages](https://github.com/tdegeus/prrng/workflows/gh-pages/badge.svg)](https://tdegeus.github.io/prrng)\n[![Conda Version](https://img.shields.io/conda/vn/conda-forge/prrng.svg)](https://anaconda.org/conda-forge/prrng)\n[![Conda Version](https://img.shields.io/conda/vn/conda-forge/python-prrng.svg)](https://anaconda.org/conda-forge/python-prrng)\n\nPortable Reconstructible (Pseudo) Random Number Generator.\n\nDocumentation: https://tdegeus.github.io/prrng\n\n### Credits\n\nThis library is a wrapper around [imneme/pcg-c-basic](https://github.com/imneme/pcg-c-basic), see also [pcg-random.org](http://www.pcg-random.org), and uses some features from [wjakob/pcg32](https://github.com/wjakob/pcg32).\n\n### Basic example\n\nThe idea is to provide a random number generator that can return nd-distributions of random numbers. Example:\n\n```cpp\n#include \u003cctime\u003e\n#include \u003cxtensor/xtensor.h\u003e\n#include \u003cprrng.h\u003e\n\nint main()\n{\n    auto seed = std::time(0);\n    prrng::pcg32 generator(seed);\n    auto a = generator.random({10, 40});\n    return 0;\n}\n```\n\n### pcg32\n\nOne of the hallmark features of the pcg32 generator is that the state of the random generator (the position in random sequence set by the seed) can be saved and restored at any point\n\n```cpp\n#include \u003cxtensor/xtensor.h\u003e\n#include \u003cprrng.h\u003e\n\nint main()\n{\n    prrng::pcg32 generator();\n    auto state = generator.state();\n    auto a = generator.random({10, 40});\n    generator.restore(state);\n    auto b = generator.random({10, 40});\n    assert(xt::allclose(a, b));\n    return 0;\n}\n```\n\nor in Python\n\n```python\nimport prrng\nimport time\n\nseed = int(time.time())\ngenerator = prrng.pcg32(seed)\na = generator.random([10, 40])\n```\n\nNote that a seed gives the exact same random sequence from C++ as from Python.\n\n#### Features\n\n*   Language and platform independence.\n*   Several distributions implemented.\n*   Advance by `n` in the random sequence in a less costly way that drawing the numbers.\n*   Compute the distance between two states.\n\n**Important (C++):** A very important and hallmark features of pcg32 is that, internally, types of fixed bit size are used. Notably the state is (re)stored as `uint64_t`. This makes that restoring can be\nuniquely done on any system and any compiler, on any platform (as long as you save the `uint64_t` properly, naturally).\nAs a convenience the output can be recast by specifying a template parameter, while static assertions shield you from losing data. For example, `auto state = generator.state\u003csize_t\u003e();` would be allowed, but `auto state = generator.state\u003cint\u003e();` would not.\n\nNote that the Python API ensure the right types at all times.\n\n### cumsum\n\nThe advantage of being able to restore and advance the random number generator is exploited in a wrapper in which the cumulative sum of the sequence of random numbers can be accessed in chunks.\n\n#### Basic usage\n\nFor example (Python):\n```python\nk = 2\nscale = 5\noffset = 0.1\ngenerator = prrng.pcg32()\nx = np.cumsum(offset + generator.weibull([10000], k, scale))\n```\nThe sequence `x` can potentially be very long, and one might want to access it in chunks. This can be done using:\n```python\nk = 2\nscale = 5\noffset = 0.1\nnchunk = 100\n\n# initialise the generator, allocate the chunk\nchunk = prrng.pcg32_cumsum(\n    shape = [nchunk],\n    distribution = prrng.weibull,\n    parameters = [k, scale, offset],\n)\n\n# access the sequence at some location\n# if the target is far away, this can be costly\n# (especially if the target is 'left' of the chunk)\ntarget = 12345.6\nchunk.align(target)\n```\n\n#### Customisation\n\nYou can modify the sequence by modifying the chunk. For example, to apply an offset:\n```python\nchunk = prrng.pcg32_cumsum(\n    shape = [nchunk],\n    distribution = prrng.weibull,\n    parameters = [k, scale, offset],\n)\n\nchunk -= dx0\n```\n\n### Array of tensors\n\nIn addition a bunch of random number generators can be collected in an nd-array,\nsuch that a composite array of random numbers is returned.\nExample:\n\n```cpp\n#include \u003cxtensor/xtensor.h\u003e\n#include \u003cprrng.h\u003e\n\nint main()\n{\n    xt::xtensor\u003cuint64_t, 2\u003e seed = {{0, 1, 2}, {3, 4, 5}};\n    prrng::pcg32_array generator(seed);\n    auto state = generator.state();\n    auto a = generator.random({4, 5}); // shape {2, 3, 4, 5}\n    generator.restore(state);\n    auto b = generator.random({4, 5});\n    assert(xt::allclose(a, b));\n    return 0;\n}\n```\n\n### Random distributions\n\nEach random generator can return a random sequence according to a certain distribution.\nThe most basic behaviour is to just convert a random integer to a random double `[0, 1]`,\nas was already done in the examples using `generator.random\u003c...\u003e(...)`.\nAlso this feature is included in the Python API, allowing to get a reproducible distribution.\n\n### More information\n\n*   The documentation of the code.\n*   The code itself.\n*   The unit tests, under [tests](./tests).\n*   The examples, under [examples](./examples).\n\n## Implementation\n\n### C++ and Python\n\nThe code is a C++ header-only library,\nbut a Python module is also provided.\nThe interfaces are identical except:\n\n+   All *xtensor* objects (`xt::xtensor\u003c...\u003e`) are *NumPy* arrays in Python.\n+   All `::` in C++ are `.` in Python.\n\n### Installation\n\n#### C++ headers\n\n##### Using conda\n\n```bash\nconda install -c conda-forge prrng\n```\n\n##### From source\n\n```bash\n# Download prrng\ngit checkout https://github.com/tdegeus/prrng.git\ncd prrng\n\n# Install headers, CMake and pkg-config support\ncmake .\nmake install\n```\n\n#### Python module\n\n##### Using conda\n\n```bash\nconda install -c conda-forge python-prrng\n```\n\nNote that *xsimd* and hardware optimisation are **not enabled**.\nTo enable them you have to compile on your system, as is discussed next.\n\n##### From source\n\n```bash\n# Download prrng\ngit checkout https://github.com/tdegeus/prrng.git\ncd prrng\n\n# Get prerequisites. An example is given using conda, but there are many other ways\nconda activate myenv\nconda env update --file environment.yaml\n# (if you use hardware optimisation, below, you also want)\nconda install -c conda-forge xsimd\n\n# Compile and install the Python module\n# (-v can be omitted as is controls just the verbosity)\npython -m pip install . -v\n\n# Or, compile with hardware optimisation (fastest), see scikit-build docs\nSKBUILD_CONFIGURE_OPTIONS=\"-DUSE_SIMD=1\" python -m pip install . -v\n\n# Note that you can also compile with debug assertions (very slow)\nSKBUILD_CONFIGURE_OPTIONS=\"-USE_DEBUG=1\" python -m pip install . -v\n\n# Or, without any assertions (slightly faster, but more dangerous)\nSKBUILD_CONFIGURE_OPTIONS=\"-USE_ASSERT=1\" python -m pip install . -v\n```\n\n### Compiling user code\n\n#### Using CMake\n\n##### Example\n\nUsing *prrng* your `CMakeLists.txt` can be as follows\n\n```cmake\ncmake_minimum_required(VERSION 3.1)\nproject(example)\nfind_package(prrng REQUIRED)\nadd_executable(example example.cpp)\ntarget_link_libraries(example PRIVATE prrng)\n```\n\n##### Targets\n\nThe following targets are available:\n\n*   `prrng`\n    Includes *prrng* and the *xtensor* dependency.\n\n*   `prrng::assert`\n    Enables assertions by defining `QPOT_ENABLE_ASSERT`.\n\n*   `prrng::debug`\n    Enables all assertions by defining\n    `QPOT_ENABLE_ASSERT` and `XTENSOR_ENABLE_ASSERT`.\n\n*   `prrng::compiler_warings`\n    Enables compiler warnings (generic).\n\n##### Optimisation\n\nIt is advised to think about compiler optimisation and enabling *xsimd*.\nUsing *CMake* this can be done using the `xtensor::optimize` and `xtensor::use_xsimd` targets.\nThe above example then becomes:\n\n```cmake\ncmake_minimum_required(VERSION 3.1)\nproject(example)\nfind_package(prrng REQUIRED)\nfind_package(xtensor REQUIRED)\nfind_package(xsimd REQUIRED)\nadd_executable(example example.cpp)\ntarget_link_libraries(example PRIVATE\n    prrng\n    xtensor::optimize\n    xtensor::use_xsimd)\n```\n\nSee the [documentation of xtensor](https://xtensor.readthedocs.io/en/latest/) concerning optimisation.\n\n#### By hand\n\nPresuming that the compiler is `c++`, compile using:\n\n```\nc++ -I/path/to/prrng/include ...\n```\n\nNote that you have to take care of the *xtensor* dependency, the C++ version, optimisation,\nenabling *xsimd*, ...\n\n#### Using pkg-config\n\nPresuming that the compiler is `c++`, compile using:\n\n```\nc++ `pkg-config --cflags prrng` ...\n```\n\nNote that you have to take care of the *xtensor* dependency, the C++ version, optimization,\nenabling *xsimd*, ...\n\n## Change-log\n\n### v1.2.0\n\n#### New features\n\n*   Allow scalar return type where possible\n*   Adding `randint`\n*   Adding `delta` distribution (just to provide a quick API)\n*   [docs] Using default doxygen theme\n\n#### Internal changes\n\n*   Making `normal_distribution::quantile` more robust\n*   Omitting unneeded `is_xtensor`\n*   [tests] Updating catch2 v3\n\n### v0.6.1\n\n*   Switching to scikit-build, clean-up of CMake (#24)\n\n### v0.6.0\n\n*   [Python] setup.py: support cross-compilation, allowing customization\n*   [CMake] allowing simd\n*   [CMake] Avoiding setuptools_scm dependency if SETUPTOOLS_SCM_PRETEND_VERSION is defined\n*   [CI] Minor updates\n*   [docs] Updating doxystyle\n*   [docs] Building docs on release\n*   Using new operators xtensor\n*   Minor style update\n*   Fixing weibull_distribution::cdf. Plotting CDF\n*   [CMake] Minor updates\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdegeus%2Fprrng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftdegeus%2Fprrng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftdegeus%2Fprrng/lists"}