Compare commits
No commits in common. "1.99.0" and "master" have entirely different histories.
|
@ -0,0 +1,13 @@
|
|||
# template
|
||||
/docs/*.py export-ignore
|
||||
/docs/*.txt export-ignore
|
||||
/docs/_* export-ignore
|
||||
/tests export-ignore
|
||||
/.git* export-ignore
|
||||
/*.yml export-ignore
|
||||
/*.yaml export-ignore
|
||||
/*.xml export-ignore
|
||||
/*.xml.dist export-ignore
|
||||
|
||||
# project
|
||||
/debug export-ignore
|
|
@ -0,0 +1,7 @@
|
|||
/.idea
|
||||
/docs/build
|
||||
/docs/html
|
||||
/vendor
|
||||
/composer.lock
|
||||
/.phpunit.result.cache
|
||||
/reports
|
|
@ -0,0 +1,90 @@
|
|||
stages:
|
||||
- test
|
||||
- report
|
||||
|
||||
cache:
|
||||
key: composer-cache
|
||||
paths:
|
||||
- .composer-cache/
|
||||
|
||||
.test:
|
||||
before_script:
|
||||
# display PHP version
|
||||
- php -v
|
||||
# install system packages
|
||||
- apt-get update && apt-get install -y git unzip libgmp-dev
|
||||
# install extensions
|
||||
- if [ "$INSTALL_XDEBUG" -eq 1 ]; then pecl install xdebug; docker-php-ext-enable xdebug; fi
|
||||
# install composer
|
||||
- php -r "copy('https://composer.github.io/installer.sig', '/tmp/composer.sig');"
|
||||
- php -r "copy('https://getcomposer.org/installer', '/tmp/composer-setup.php');"
|
||||
- php -r '$expected = file_get_contents("/tmp/composer.sig"); $actual = hash_file("sha384", "/tmp/composer-setup.php"); exit(intval(!hash_equals($expected, $actual)));'
|
||||
- php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
|
||||
- chmod +x /usr/local/bin/composer
|
||||
- rm /tmp/composer-setup.php /tmp/composer.sig
|
||||
# cache dependencies
|
||||
- composer config -g cache-dir "$(pwd)/.composer-cache"
|
||||
script:
|
||||
- composer update
|
||||
- vendor/bin/phpunit
|
||||
|
||||
# coverage
|
||||
coverage:
|
||||
variables:
|
||||
INSTALL_XDEBUG: 1
|
||||
extends: .test
|
||||
stage: report
|
||||
only:
|
||||
- master
|
||||
- tags
|
||||
image: php:8.1
|
||||
script:
|
||||
- composer update
|
||||
- docker-php-ext-install gmp
|
||||
- XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-clover coverage.xml
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
# test in every version
|
||||
test:
|
||||
extends: .test
|
||||
stage: test
|
||||
image: ${ARCH}/php:${PHP_VERSION}
|
||||
parallel:
|
||||
matrix:
|
||||
- PHP_VERSION:
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
ARCH:
|
||||
- amd64
|
||||
- i386
|
||||
|
||||
test-gmp:
|
||||
extends: .test
|
||||
stage: test
|
||||
image: ${ARCH}/php:${PHP_VERSION}
|
||||
parallel:
|
||||
matrix:
|
||||
- PHP_VERSION:
|
||||
- '7.4'
|
||||
- '8.0'
|
||||
- '8.1'
|
||||
ARCH:
|
||||
- amd64
|
||||
- i386
|
||||
script:
|
||||
- docker-php-ext-install gmp
|
||||
- composer update
|
||||
- vendor/bin/phpunit
|
||||
|
||||
# control that our tests are valid
|
||||
test-8.2-control:
|
||||
extends: .test
|
||||
stage: test
|
||||
image: php:8.2
|
||||
script:
|
||||
- composer update
|
||||
- vendor/bin/phpunit
|
|
@ -0,0 +1,13 @@
|
|||
version: 2
|
||||
|
||||
build:
|
||||
os: 'ubuntu-22.04'
|
||||
tools:
|
||||
python: '3.11'
|
||||
|
||||
sphinx:
|
||||
configuration: 'docs/conf.py'
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: 'docs/requirements.txt'
|
|
@ -0,0 +1,136 @@
|
|||
# Changelog
|
||||
|
||||
[gh@TimWolla]: https://github.com/TimWolla
|
||||
[gh@nicolas-grekas]: https://github.com/nicolas-grekas
|
||||
|
||||
## 1.x
|
||||
|
||||
### 1.0.2
|
||||
|
||||
*Sep 7, 2023*
|
||||
|
||||
* Bump arokettu/unsigned to 1.2.1, previous versions may cause invalid results in Mersenne Twister on 32-bit systems.
|
||||
|
||||
### 1.0.1
|
||||
|
||||
*Nov 12, 2022*
|
||||
|
||||
* Rely on symfony/polyfill-php82 for interface implementations and Random\Engine\Secure ([#6][gh#6]),
|
||||
thanks to [Nicolas Grekas][gh@nicolas-grekas]
|
||||
* Added compatibility with PHP regression fix: [PHP#9839] ([#5][gh#5])
|
||||
|
||||
[gh#6]: https://github.com/arokettu/php-random-polyfill/pull/6
|
||||
[PHP#9839]: https://github.com/php/php-src/pull/9839
|
||||
[gh#5]: https://github.com/arokettu/php-random-polyfill/pull/5
|
||||
|
||||
### 1.0.0
|
||||
|
||||
*Oct 26, 2022*
|
||||
|
||||
Since RC1/RC2 are compatible with last 4 release candidates of PHP 8.2 (RC2-RC5),
|
||||
RC2 is re-released as stable.
|
||||
|
||||
* No user facing changes since RC2
|
||||
|
||||
### 1.0.0-rc2
|
||||
|
||||
*Oct 1, 2022*
|
||||
|
||||
* Speed up 32 bit calculations in 64 bit envs
|
||||
|
||||
### 1.0.0-rc1
|
||||
|
||||
*Sep 14, 2022*
|
||||
|
||||
* `Secure` engine throws `RandomException` instead of `Exception`
|
||||
* Added verification of the number of elements in serialized data
|
||||
* Generated data is truncated to 64 bits in `Randomizer::getBytes()`
|
||||
* Fixed integer overflow in the upstream math lib
|
||||
|
||||
### 1.0.0-beta1
|
||||
|
||||
*Sep 2, 2022*
|
||||
|
||||
* Fix incompatibility with PHP 8.2.0 RC1
|
||||
|
||||
## 0.x
|
||||
|
||||
### 0.5.0
|
||||
|
||||
*Sep 1, 2022*
|
||||
|
||||
Hopefully the last alpha
|
||||
|
||||
* Exceptions are now compatible in most known cases
|
||||
* Full coverage
|
||||
* GMP is now an optional dependency (but highly recommended)
|
||||
|
||||
### 0.4.0
|
||||
|
||||
*Aug 19, 2022*
|
||||
|
||||
* Verified compatibility with PHP 8.2.0 beta 3
|
||||
* Tests ported from the PHP engine
|
||||
* Various compatibility fixes
|
||||
* Exceptions compatibility (mostly)
|
||||
|
||||
### 0.3.0
|
||||
|
||||
*Aug 5, 2022*
|
||||
|
||||
* Verified compatibility with PHP 8.2.0 beta 2
|
||||
* `PcgOneseq128XslRr64`
|
||||
* `Xoshiro256StarStar`
|
||||
* Split `nextInt()` and `getInt($min, $max)` like in beta 2
|
||||
|
||||
### 0.2.1
|
||||
|
||||
*Jul 31, 2022*
|
||||
|
||||
* Verified compatibility of custom engines with the current PHP 8.2 master
|
||||
* ``getInt()`` now has proper signature ``getInt(int $min, int $max)``
|
||||
* ``arrayPickKeys()`` throws a warning because full compatibility is not achievable.
|
||||
Thanks to [Tim Düsterhus][gh@TimWolla] for [the explanation][gh#1]
|
||||
* No warning if the engine is ``CryptoSafeEngine``
|
||||
* Fixed incorrect range function selection ([#1][gh#1]), thanks to [Tim Düsterhus][gh@TimWolla]
|
||||
* Fixed byte selection in range64
|
||||
|
||||
[gh#1]: https://github.com/arokettu/php-random-polyfill/issues/1
|
||||
|
||||
### 0.2.0
|
||||
|
||||
*Jul 27, 2022*
|
||||
|
||||
NOTE: 0.2.0 currently is not fully compatible when using custom engines.
|
||||
This will be fixed in 0.3.0 after PHP 8.2.0 beta 2 is released with some critical fixes.
|
||||
|
||||
* `Randomizer`
|
||||
* `$engine`
|
||||
* `getBytes($length)`
|
||||
* `shuffleArray($array)`
|
||||
* `shuffleBytes($bytes)`
|
||||
* `arrayPickKeys($array, $num)`
|
||||
* Serialization and unserialization are now compatible with PHP 8.2
|
||||
if performed in PHP 7.4+
|
||||
* `Mt19937`
|
||||
* Serialization and unserialization are now compatible with PHP 8.2
|
||||
if performed in PHP 7.4+
|
||||
|
||||
### 0.1.1
|
||||
|
||||
*Jul 23, 2022*
|
||||
|
||||
* Fixed Mt not generating enough data sometimes
|
||||
|
||||
### 0.1.0
|
||||
|
||||
*Jul 23, 2022*
|
||||
|
||||
* First release
|
||||
* Compatible with PHP 8.2.0 beta 1
|
||||
* Engines:
|
||||
* Secure Random
|
||||
* Mersenne Twister
|
||||
* Randomizer features:
|
||||
* `getInt()`
|
||||
* `getInt($min, $max)`
|
|
@ -34,7 +34,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
....
|
||||
|
||||
## PHP
|
||||
== PHP
|
||||
|
||||
The library includes code taken from the PHP 8.1.0 beta 1 and rewritten from C to PHP.
|
||||
|
||||
|
@ -111,9 +111,9 @@ PHP includes the Zend Engine, freely available at
|
|||
<http://www.zend.com>.
|
||||
....
|
||||
|
||||
## Mersenne Twister
|
||||
== Mersenne Twister
|
||||
|
||||
Mersenne Twister code is adapted from C++ code distributed under the 3-Clause BSD License.
|
||||
Mersenne Twister code in PHP is adapted from C++ code distributed under the 3-Clause BSD License.
|
||||
|
||||
....
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
# BSD 3-Clause "New" or "Revised" License
|
||||
|
||||
_This is a license for the product as a whole, see `COPYING.adoc` for additional licenses._
|
||||
|
||||
Copyright © 2022 Anton Smirnov
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
46
README.md
46
README.md
|
@ -1,5 +1,47 @@
|
|||
# Random Extension Polyfill for PHP
|
||||
|
||||
This is a special empty version of the polyfill for PHP 8.2+.
|
||||
[](https://packagist.org/packages/arokettu/random-polyfill)
|
||||
[][COPYING]
|
||||
[](https://gitlab.com/sandfox/php-random-polyfill/-/pipelines)
|
||||
[](https://codecov.io/gl/sandfox/php-random-polyfill/)
|
||||
|
||||
https://sandfox.dev/php/random-polyfill.html
|
||||
This is a polyfill for the new `ext-random` extension that was released with PHP 8.2.
|
||||
|
||||
## Requirements
|
||||
|
||||
* PHP 7.1
|
||||
* GMP extension is strongly recommended on PHP 7
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
composer require 'arokettu/random-polyfill'
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
|
||||
The library aims to be compatible with `ext-random` as released in PHP 8.2.0 and subsequent patch releases.
|
||||
|
||||
## Documentation
|
||||
|
||||
### Random Extension
|
||||
|
||||
Read the official PHP doc: https://www.php.net/manual/en/book.random.php
|
||||
|
||||
### The Polyfill
|
||||
|
||||
Read full documentation here: <https://sandfox.dev/php/random-polyfill.html>
|
||||
|
||||
Also on Read the Docs: <https://php-random-polyfill.readthedocs.io/>
|
||||
|
||||
## Support
|
||||
|
||||
Please file issues on our main repo at GitHub: <https://github.com/arokettu/php-random-polyfill/issues>
|
||||
|
||||
## License
|
||||
|
||||
The library is available as open source under the terms of the [3-Clause BSD License].
|
||||
See [COPYING.adoc][COPYING] for additional licenses.
|
||||
|
||||
[3-Clause BSD License]: LICENSE.md
|
||||
[COPYING]: COPYING.adoc
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
"name": "arokettu/random-polyfill",
|
||||
"description": "Random Extension Polyfill for PHP",
|
||||
"keywords": ["random", "polyfill"],
|
||||
"type": "metapackage",
|
||||
"type": "library",
|
||||
"license": "BSD-3-Clause",
|
||||
"homepage": "https://sandfox.dev/php/random-polyfill.html",
|
||||
"support": {
|
||||
"issues": "https://gitlab.com/sandfox/php-random-polyfill/-/issues",
|
||||
"source": "https://gitlab.com/sandfox/php-random-polyfill",
|
||||
"issues": "https://github.com/arokettu/php-random-polyfill/issues",
|
||||
"source": "https://github.com/arokettu/php-random-polyfill",
|
||||
"docs": "https://php-random-polyfill.readthedocs.io/",
|
||||
"chat": "https://gitter.im/arokettu/community"
|
||||
},
|
||||
|
@ -24,7 +24,35 @@
|
|||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Arokettu\\Random\\": "src",
|
||||
"Random\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Arokettu\\Random\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": ">= 8.2"
|
||||
"php": "^7.1 | ^8.0",
|
||||
"arokettu/unsigned": "^1.2.1",
|
||||
"symfony/polyfill-php80": "^1.22",
|
||||
"symfony/polyfill-php81": "^1.22",
|
||||
"symfony/polyfill-php82": "^1.27"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5 | ^8.5 | 9.5.*",
|
||||
"psy/psysh": "*",
|
||||
"sandfox.dev/code-standard": "^1",
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
"vimeo/psalm": "^4.24"
|
||||
},
|
||||
"provide": {
|
||||
"ext-random": "8.2.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gmp": "For significantly faster calculation"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
*.txt
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Secure());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Xorshift32(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_PHP));
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Zeros());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Fail());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\SingleByte());
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64('1234567890123456'));
|
||||
|
||||
//$rnd->getBytes(0);
|
||||
|
||||
$bs = 1;
|
||||
|
||||
echo bin2hex($rnd->getBytes($bs)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs <<= 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs <<= 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs <<= 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs <<= 1)), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$bs = 3;
|
||||
|
||||
echo bin2hex($rnd->getBytes($bs)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs = $bs * 2 - 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs = $bs * 2 - 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs = $bs * 2 - 1)), PHP_EOL;
|
||||
echo bin2hex($rnd->getBytes($bs = $bs * 2 - 1)), PHP_EOL;
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
var_dump(
|
||||
unserialize(
|
||||
'O:17:"Random\Randomizer":1:{i:0;a:2:{s:3:"foo";N;s:6:"engine";O:32:"Random\Engine\Xoshiro256StarStar":2:' .
|
||||
'{i:0;a:0:{}i:1;a:4:{i:0;s:16:"7520fbc2d6f8de46";i:1;s:16:"84d2d2b9d7ba0a34";i:2;s:16:"d975f36db6490b32";i:3;' .
|
||||
's:16:"c19991ee16785b94";}}}}'
|
||||
)
|
||||
);
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Secure());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Xorshift32(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_PHP));
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Zeros());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Fail());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\SingleByte());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\ThreeBytes());
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64('1234567890123456'));
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('12345678901234567890123456789012'));
|
||||
|
||||
//var_dump($rnd->engine);
|
||||
//var_dump($rnd->engine->__serialize());
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
//try {
|
||||
// $rnd->getInt(1000, 1);
|
||||
//} catch (ValueError $e) {
|
||||
// var_dump($e);
|
||||
//}
|
||||
|
||||
//var_dump($rnd->engine);
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//mt_srand(123, MT_RAND_MT19937);
|
||||
//$rnd = new \Random\Randomizer($e = new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
|
||||
mt_srand(123, MT_RAND_PHP);
|
||||
$rnd = new \Random\Randomizer($e = new \Random\Engine\Mt19937(123, MT_RAND_PHP));
|
||||
|
||||
file_put_contents('test_mt_' . PHP_VERSION_ID . '.txt', var_export($e->__debugInfo(), true));
|
||||
|
||||
echo mt_rand(), PHP_EOL;
|
||||
echo mt_rand(), PHP_EOL;
|
||||
echo mt_rand(), PHP_EOL;
|
||||
echo mt_rand(), PHP_EOL;
|
||||
echo mt_rand(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo mt_rand(1, 1000), PHP_EOL;
|
||||
echo mt_rand(1, 1000), PHP_EOL;
|
||||
echo mt_rand(1, 1000), PHP_EOL;
|
||||
echo mt_rand(1, 1000), PHP_EOL;
|
||||
echo mt_rand(1, 1000), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
echo $rnd->getInt(1, 1000), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
//var_dump($e->__serialize());
|
||||
//var_dump($e->__debugInfo());
|
||||
//var_dump($e->__serialize()[1] == $e->__debugInfo()['__states']);
|
||||
|
||||
//try {
|
||||
// $rnd->getInt(1000, 1);
|
||||
//} catch (ValueError $e) {
|
||||
// var_dump($e);
|
||||
//}
|
||||
//
|
||||
//echo PHP_EOL;
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64('1234567890123456'));
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$rnd->engine->jump(1);
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$rnd->engine->jump(126);
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$rnd->engine->jump(0);
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
var_export($rnd->engine->__debugInfo());
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Secure());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Xorshift32(123));
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_PHP));
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Zeros());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Fail());
|
||||
|
||||
//$rnd->pickArrayKeys([], 0);
|
||||
//$rnd->pickArrayKeys([1], -1);
|
||||
|
||||
// [0 => 1, 9 => 10]
|
||||
$a1 = range(1, 10);
|
||||
// ['a' => 'aa', 'j' => 'jj']
|
||||
$a2 = array_combine($a2k = range('a', 'j'), array_map(function ($v) { return $v . $v; }, $a2k));
|
||||
|
||||
$i = 1;
|
||||
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a1, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a1, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a1, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a1, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a1, $i++)), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$i = 1;
|
||||
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a2, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a2, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a2, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a2, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a2, $i++)), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$a3 = $a1 + $a2;
|
||||
unset($a3[0], $a3[2], $a3[3], $a3[4], $a3[6], $a3[8], $a3['a'], $a3['c'], $a3['d'], $a3['f'], $a3['j'], $a3['d']);
|
||||
|
||||
$i = 1;
|
||||
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a3, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a3, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a3, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a3, $i++)), PHP_EOL;
|
||||
echo implode(', ', @$rnd->pickArrayKeys($a3, $i++)), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$r1 = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
$r2 = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
|
||||
$a = [ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, ];
|
||||
unset($a['b']);
|
||||
|
||||
$b = [ 'a' => 1, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, ];
|
||||
|
||||
var_dump(
|
||||
@$r1->pickArrayKeys($a, 1), // [ 0 => 'e' ]
|
||||
@$r2->pickArrayKeys($b, 1) // [ 0 => 'd' ]
|
||||
);
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$rnd = new \Random\Randomizer();
|
||||
|
||||
var_dump($rnd->engine);
|
||||
var_dump($rnd->something);
|
||||
|
||||
var_dump(isset($rnd->engine));
|
||||
var_dump(isset($rnd->something));
|
||||
|
||||
try {
|
||||
$rnd->something = 123;
|
||||
} catch (Throwable $e) {
|
||||
var_dump($e);
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$e = new \Random\Engine\PcgOneseq128XslRr64(4546546);
|
||||
$e->generate();
|
||||
$e->generate();
|
||||
|
||||
var_dump($e->__serialize());
|
||||
echo base64_encode(serialize($e)), PHP_EOL;
|
||||
|
||||
$php82serialized = 'TzozMzoiUmFuZG9tXEVuZ2luZVxQY2dPbmVzZXExMjhYc2xScjY0IjoyOntpOjA7YTowOnt9aToxO2E6Mjp7aTowO3M6MTY6IjQyY2JkMzI1OGZjMDdiMmYiO2k6MTtzOjE2OiI0ZTQxZDFlNjBhYzY1NTk5Ijt9fQ==';
|
||||
|
||||
$e2 = unserialize(base64_decode($php82serialized));
|
||||
|
||||
var_dump(bin2hex($e->generate()), bin2hex($e2->generate()));
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Zeros());
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\PcgOneseq128XslRr64(123));
|
||||
|
||||
$rnd->nextInt();
|
||||
$rnd->nextInt();
|
||||
|
||||
echo base64_encode(serialize($rnd)), PHP_EOL;
|
||||
|
||||
$php82serialized = 'TzoxNzoiUmFuZG9tXFJhbmRvbWl6ZXIiOjE6e2k6MDthOjE6e3M6NjoiZW5naW5lIjtPOjMzOiJSYW5kb21cRW5naW5lXFBjZ09uZXNlcTEyOFhzbFJyNjQiOjI6e2k6MDthOjA6e31pOjE7YToyOntpOjA7czoxNjoiOGYwN2I5Y2Q0YTFlNDJjZSI7aToxO3M6MTY6ImYzYmVjNjVkMzAyMGQ0ZGUiO319fX0=';
|
||||
$rnd2 = unserialize(base64_decode($php82serialized));
|
||||
|
||||
var_dump(bin2hex($rnd->nextInt()), bin2hex($rnd2->nextInt()));
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$e = new \Random\Engine\Xoshiro256StarStar(4546546);
|
||||
$e->generate();
|
||||
$e->generate();
|
||||
|
||||
var_dump($e->__serialize());
|
||||
echo base64_encode(serialize($e)), PHP_EOL;
|
||||
|
||||
$php82serialized = 'TzozMjoiUmFuZG9tXEVuZ2luZVxYb3NoaXJvMjU2U3RhclN0YXIiOjI6e2k6MDthOjA6e31pOjE7YTo0OntpOjA7czoxNjoiZGY5Yzk3NmQ3NTYzMTFiOCI7aToxO3M6MTY6IjY5MTA5ZjFhNjc0MTNjYWYiO2k6MjtzOjE2OiJmY2JmOGZlNjc0OTQ0N2UyIjtpOjM7czoxNjoiMmJkMGE4MTk3NGZmMTk1NyI7fX0=';
|
||||
|
||||
$e2 = unserialize(base64_decode($php82serialized));
|
||||
|
||||
var_dump(bin2hex($e->generate()), bin2hex($e2->generate()));
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Secure());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Xorshift32(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_MT19937));
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\Mt19937(123, MT_RAND_PHP));
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Zeros());
|
||||
//$rnd = new \Random\Randomizer(new \Arokettu\Random\Tests\DevEngines\Fail());
|
||||
|
||||
echo implode(', ', $rnd->shuffleArray([1,2,3,4,5,6,7,8,9,10])), PHP_EOL;
|
||||
echo implode(', ', $rnd->shuffleArray([1,2,3,4,5,6,7,8,9,10])), PHP_EOL;
|
||||
echo implode(', ', $rnd->shuffleArray([1,2,3,4,5,6,7,8,9,10])), PHP_EOL;
|
||||
echo implode(', ', $rnd->shuffleArray([1,2,3,4,5,6,7,8,9,10])), PHP_EOL;
|
||||
echo implode(', ', $rnd->shuffleArray([1,2,3,4,5,6,7,8,9,10])), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
echo $rnd->shuffleBytes('1234567890'), PHP_EOL;
|
||||
echo $rnd->shuffleBytes('1234567890'), PHP_EOL;
|
||||
echo $rnd->shuffleBytes('1234567890'), PHP_EOL;
|
||||
echo $rnd->shuffleBytes('1234567890'), PHP_EOL;
|
||||
echo $rnd->shuffleBytes('1234567890'), PHP_EOL;
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$rnd = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar(123));
|
||||
//$rnd = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('12345678901234567890123456789012'));
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$rnd->engine->jump();
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$rnd->engine->jumpLong();
|
||||
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
echo $rnd->nextInt(), PHP_EOL;
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
var_export($rnd->engine->__debugInfo());
|
|
@ -0,0 +1,3 @@
|
|||
{%- if current_version -%}
|
||||
<div class="sidebar-brand">{{ current_version }}</div>
|
||||
{%- endif -%}
|
|
@ -0,0 +1,98 @@
|
|||
Compatibility Notes
|
||||
###################
|
||||
|
||||
PHP
|
||||
===
|
||||
|
||||
.. note::
|
||||
Random Extension doc on the PHP website:
|
||||
https://www.php.net/manual/en/book.random.php
|
||||
|
||||
The library aims to be compatible with ``ext-random`` as released in PHP 8.2.0 and subsequent patch releases.
|
||||
The library will not be a full replacement for ``ext-random`` and total compatibility does not seem to be achievable.
|
||||
|
||||
Available classes:
|
||||
|
||||
* This polyfill:
|
||||
|
||||
* `Random\\Randomizer <https://www.php.net/manual/en/class.random-randomizer.php>`__
|
||||
* `Random\\Engine\\Mt19937 <https://www.php.net/manual/en/class.random-engine-mt19937.php>`__
|
||||
* `Random\\Engine\\PcgOneseq128XslRr64 <https://www.php.net/manual/en/class.random-engine-pcgoneseq128xslrr64.php>`__
|
||||
* `Random\\Engine\\Xoshiro256StarStar <https://www.php.net/manual/en/class.random-engine-xoshiro256starstar.php>`__
|
||||
|
||||
* From `symfony/polyfill-php82 <https://packagist.org/packages/symfony/polyfill-php82>`__:
|
||||
|
||||
* `Random\\Engine <https://www.php.net/manual/en/class.random-engine.php>`__
|
||||
* `Random\\Engine\\CryptoSafeEngine <https://www.php.net/manual/en/class.random-cryptosafeengine.php>`__
|
||||
* `Random\\Engine\\Secure <https://www.php.net/manual/en/class.random-engine-secure.php>`__
|
||||
|
||||
Version 1.99.0
|
||||
==============
|
||||
|
||||
Version 1.99.0 is an empty package for PHP >= 8.2.
|
||||
It ensures that no overhead or extra code will be used for PHP 8.2+ apps.
|
||||
|
||||
Known differences
|
||||
=================
|
||||
|
||||
These differences are considered to be permanent features.
|
||||
However if you know how to fix them, ideas are welcome.
|
||||
|
||||
Serialization
|
||||
-------------
|
||||
|
||||
* Serialization is only compatible if done in PHP 7.4 and later.
|
||||
* Serializable entities implement ``\Serializable`` for controlled serialization in PHP 7.1 - 7.3.
|
||||
* Entities serialized in PHP 7.1 - 7.3 can be unserialized with the polyfill under any version of PHP but will not be
|
||||
unserializable by the native extension.
|
||||
* Serialization in PHP 7.1 - 7.3 will trigger a warning.
|
||||
Silence it with ``@`` if you don't care.
|
||||
* Does not throw in GH-9186_ case but also does not create a dynamic property (PHP 7.4+)
|
||||
Undefined behavior for PHP <7.4 (returns false with a warning for the given code)
|
||||
|
||||
.. _GH-9186: https://github.com/php/php-src/issues/9186
|
||||
|
||||
Randomizer
|
||||
----------
|
||||
|
||||
* ``pickArrayKeys()`` messes a lot with the internal structure of the PHP hash tables and therefore
|
||||
may produce different results in the userland.
|
||||
Example from `Tim Düsterhus`__:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
<?php
|
||||
|
||||
$r1 = new Random\Randomizer(new Random\Engine\Xoshiro256StarStar(1));
|
||||
$r2 = new Random\Randomizer(new Random\Engine\Xoshiro256StarStar(1));
|
||||
|
||||
$a = [ 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, ];
|
||||
unset($a['b']);
|
||||
|
||||
$b = [ 'a' => 1, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, ];
|
||||
|
||||
var_dump($a === $b); // bool(true)
|
||||
|
||||
var_dump(
|
||||
$r1->pickArrayKeys($a, 1), // native: [ 0 => 'e' ], lib: [ 0 => 'd' ]
|
||||
$r2->pickArrayKeys($b, 1), // [ 0 => 'd' ]
|
||||
);
|
||||
|
||||
The interpreter operates on the actual hash table that looks different for these arrays.
|
||||
The lib "repacks" arrays and therefore returns ``['d']`` in both cases.
|
||||
|
||||
.. __: https://github.com/php/doc-en/issues/1731
|
||||
|
||||
* using ``pickArrayKeys()`` will trigger a warning if the engine is not CryptoSafeEngine.
|
||||
Silence it with ``@`` if you don't care.
|
||||
|
||||
Mt19937
|
||||
-------
|
||||
|
||||
* Generating integers with ``$max - $min >= mt_getrandmax()`` with ``MT_RAND_PHP`` is considered undefined behavior.
|
||||
This library is consistent with PHP 8.2 behavior, not the version it runs under.
|
||||
|
||||
Warnings
|
||||
--------
|
||||
|
||||
For obvious reasons, native extension produces ``E_WARNING`` and the library produces ``E_USER_WARNING``.
|
|
@ -0,0 +1,28 @@
|
|||
from datetime import datetime
|
||||
|
||||
# import specific project config
|
||||
import os, sys
|
||||
sys.path.append(os.curdir)
|
||||
from conf_project import *
|
||||
|
||||
author = 'Anton Smirnov'
|
||||
copyright = '{} {}'.format(datetime.now().year, author)
|
||||
language = 'en'
|
||||
|
||||
html_title = project
|
||||
html_theme = 'furo'
|
||||
templates_path = ["_templates"]
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"sidebar/brand.html",
|
||||
"rtd-version.html",
|
||||
"sidebar/search.html",
|
||||
"sidebar/scroll-start.html",
|
||||
"sidebar/navigation.html",
|
||||
"sidebar/ethical-ads.html",
|
||||
"sidebar/scroll-end.html",
|
||||
"sidebar/variant-selector.html",
|
||||
]
|
||||
}
|
||||
|
||||
exclude_patterns = ['venv/*']
|
|
@ -0,0 +1 @@
|
|||
project = 'Random Extension Polyfill'
|
|
@ -0,0 +1,54 @@
|
|||
Random Extension Polyfill
|
||||
#########################
|
||||
|
||||
|Packagist| |GitLab| |GitHub| |Bitbucket| |Gitea|
|
||||
|
||||
This is a polyfill for the new ``ext-random`` extension that was released with PHP 8.2.
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
* PHP 7.1
|
||||
* GMP extension is strongly recommended on PHP 7 and somewhat recommended on PHP 8
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
composer require 'arokettu/random-polyfill'
|
||||
|
||||
Random Extension Documentation
|
||||
==============================
|
||||
|
||||
On the PHP website: https://www.php.net/manual/en/book.random.php
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
compatibility
|
||||
performance
|
||||
license
|
||||
thanks
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
The library is available as open source under the terms of the `3-Clause BSD License`__.
|
||||
See :ref:`license` for additional licenses.
|
||||
|
||||
.. __: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
.. |Packagist| image:: https://img.shields.io/packagist/v/arokettu/random-polyfill.svg?style=flat-square
|
||||
:target: https://packagist.org/packages/arokettu/random-polyfill
|
||||
.. |GitHub| image:: https://img.shields.io/badge/get%20on-GitHub-informational.svg?style=flat-square&logo=github
|
||||
:target: https://github.com/arokettu/php-random-polyfill
|
||||
.. |GitLab| image:: https://img.shields.io/badge/get%20on-GitLab-informational.svg?style=flat-square&logo=gitlab
|
||||
:target: https://gitlab.com/sandfox/php-random-polyfill
|
||||
.. |Bitbucket| image:: https://img.shields.io/badge/get%20on-Bitbucket-informational.svg?style=flat-square&logo=bitbucket
|
||||
:target: https://bitbucket.org/sandfox/php-random-polyfill
|
||||
.. |Gitea| image:: https://img.shields.io/badge/get%20on-Gitea-informational.svg?style=flat-square&logo=gitea
|
||||
:target: https://sandfox.org/sandfox/php-random-polyfill
|
|
@ -0,0 +1,156 @@
|
|||
.. _license:
|
||||
|
||||
License
|
||||
#######
|
||||
|
||||
The library itself is distributed under the 3-Clause BSD License but it also uses some code under other licenses.
|
||||
Here are all the terms on one page.
|
||||
|
||||
Random Extension Polyfill for PHP
|
||||
=================================
|
||||
|
||||
The library itself.
|
||||
|
||||
Copyright © 2022 Anton Smirnov
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
PHP
|
||||
===
|
||||
|
||||
The library includes code taken from the PHP 8.1.0 beta 1 and rewritten from C to PHP.
|
||||
|
||||
PHP is distributed under the PHP License.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, version 3.01
|
||||
Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, is permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. The name "PHP" must not be used to endorse or promote products
|
||||
derived from this software without prior written permission. For
|
||||
written permission, please contact group@php.net.
|
||||
|
||||
4. Products derived from this software may not be called "PHP", nor
|
||||
may "PHP" appear in their name, without prior written permission
|
||||
from group@php.net. You may indicate that your software works in
|
||||
conjunction with PHP by saying "Foo for PHP" instead of calling
|
||||
it "PHP Foo" or "phpfoo"
|
||||
|
||||
5. The PHP Group may publish revised and/or new versions of the
|
||||
license from time to time. Each version will be given a
|
||||
distinguishing version number.
|
||||
Once covered code has been published under a particular version
|
||||
of the license, you may always continue to use it under the terms
|
||||
of that version. You may also choose to use such covered code
|
||||
under the terms of any subsequent version of the license
|
||||
published by the PHP Group. No one other than the PHP Group has
|
||||
the right to modify the terms applicable to covered code created
|
||||
under this License.
|
||||
|
||||
6. Redistributions of any form whatsoever must retain the following
|
||||
acknowledgment:
|
||||
"This product includes PHP software, freely available from
|
||||
<http://www.php.net/software/>".
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
|
||||
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
|
||||
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals on behalf of the PHP Group.
|
||||
|
||||
The PHP Group can be contacted via Email at group@php.net.
|
||||
|
||||
For more information on the PHP Group and the PHP project,
|
||||
please see <http://www.php.net>.
|
||||
|
||||
PHP includes the Zend Engine, freely available at
|
||||
<http://www.zend.com>.
|
||||
|
||||
Mersenne Twister
|
||||
================
|
||||
|
||||
Mersenne Twister code in PHP is adapted from C++ code distributed under the 3-Clause BSD License.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
Copyright (C) 2000 - 2003, Richard J. Wagner
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of its contributors may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,22 @@
|
|||
Performance Notes
|
||||
#################
|
||||
|
||||
Well, even with GMP, it's guaranteed to be slow.
|
||||
Good enough if you need a dozen numbers or so.
|
||||
|
||||
Performance test
|
||||
================
|
||||
|
||||
https://github.com/arokettu/random-polyfill-perf
|
||||
|
||||
* Secure engine is mostly unaffected by the choice of backend (except for nextInt() case)
|
||||
* PHP 7:
|
||||
|
||||
* With GMP installed, all engines are approximately 400 times slower than native
|
||||
* Mersenne Twister is consistently 400 times slower than native, whether you use GMP or not
|
||||
* PCG is 100 times slower without GMP and xoshiro256** is 50 times slower without GMP
|
||||
* PHP 8:
|
||||
|
||||
* 100-150 times slower than native
|
||||
* GMP presence does not affect performance that much, but PCG will run twice as fast
|
||||
* JIT helps almost as much as GMP (use both for max performance)
|
|
@ -0,0 +1,2 @@
|
|||
sphinx>=7
|
||||
furo
|
|
@ -0,0 +1,7 @@
|
|||
Thanks
|
||||
######
|
||||
|
||||
* Random extension developers:
|
||||
Go Kudo, Tim Düsterhus, Guilliam Xavier, Christoph M. Becker, Jakub Zelenka, Bob Weinand, Máté Kocsis,
|
||||
and Original RNG implementators
|
||||
* Tim Düsterhus for reviews, issue reports and useful advices
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
@see https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset
|
||||
-->
|
||||
<ruleset name="Custom Standard" namespace="MyProject\CS\Standard">
|
||||
<rule ref="SandFox_PHP71">
|
||||
<!-- crashes -->
|
||||
<exclude name="Security.BadFunctions.CallbackFunctions"/>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalFunctions">
|
||||
<properties>
|
||||
<!-- Reset to default (include all functions) -->
|
||||
<property name="includeSpecialFunctions" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.Namespaces.FullyQualifiedGlobalConstants"/>
|
||||
<!-- no need to cover 8.2 and later -->
|
||||
<config name="testVersion" value="7.1-8.1"/>
|
||||
<file>src</file>
|
||||
<file>tests</file>
|
||||
</ruleset>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
convertDeprecationsToExceptions="true"
|
||||
executionOrder="random"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd">
|
||||
<testsuites>
|
||||
<testsuite name="all">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<coverage>
|
||||
<include>
|
||||
<directory>src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="2"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright © 2022 Anton Smirnov
|
||||
* @license BSD-3-Clause https://spdx.org/licenses/BSD-3-Clause.html
|
||||
*
|
||||
* @noinspection PhpComposerExtensionStubsInspection
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Arokettu\Random;
|
||||
|
||||
use GMP;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore We don't care about math that was not used
|
||||
*/
|
||||
abstract class Math
|
||||
{
|
||||
public const SIZEOF_UINT32_T = 4;
|
||||
public const SIZEOF_UINT64_T = 8;
|
||||
public const SIZEOF_UINT128_T = 16;
|
||||
|
||||
/** @var Math[] */
|
||||
private static $maths = [];
|
||||
|
||||
public static function create(int $sizeof): self
|
||||
{
|
||||
return self::$maths[$sizeof] ?? self::$maths[$sizeof] = self::build($sizeof);
|
||||
}
|
||||
|
||||
protected static function build(int $sizeof): self
|
||||
{
|
||||
// only less because PHP int is always signed
|
||||
if ($sizeof < \PHP_INT_SIZE) {
|
||||
return new MathNative($sizeof);
|
||||
}
|
||||
|
||||
if (\extension_loaded('gmp')) {
|
||||
return new MathGMP($sizeof);
|
||||
}
|
||||
|
||||
return new MathUnsigned($sizeof);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sizeof
|
||||
*/
|
||||
abstract protected function __construct(int $sizeof);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
* @param int $shift
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function shiftLeft($value, int $shift);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
* @param int $shift
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function shiftRight($value, int $shift);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int|string|GMP $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function add($value1, $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function addInt($value1, int $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int|string|GMP $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function sub($value1, $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function subInt($value1, int $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int|string|GMP $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function mul($value1, $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function mulInt($value1, int $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int|string|GMP $value2
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function mod($value1, $value2);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value1
|
||||
* @param int|string|GMP $value2
|
||||
* @return int
|
||||
*/
|
||||
abstract public function compare($value1, $value2): int;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function fromHex(string $value);
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function fromInt(int $value);
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return int|string|GMP
|
||||
*/
|
||||
abstract public function fromBinary(string $value);
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
*/
|
||||
abstract public function toInt($value): int;
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
*/
|
||||
abstract public function toSignedInt($value): int;
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
*/
|
||||
abstract public function toBinary($value): string;
|
||||
|
||||
/**
|
||||
* @param int|string|GMP $value
|
||||
* @return int[]|string[]|GMP[]
|
||||
*/
|
||||
abstract public function splitHiLo($value): array;
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright © 2022 Anton Smirnov
|
||||
* @license BSD-3-Clause https://spdx.org/licenses/BSD-3-Clause.html
|
||||
*
|
||||
* @noinspection PhpComposerExtensionStubsInspection
|
||||
* @noinspection PhpReturnDocTypeMismatchInspection
|
||||
* @noinspection PhpIncompatibleReturnTypeInspection
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Arokettu\Random;
|
||||
|
||||
use GMP;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @psalm-suppress MoreSpecificImplementedParamType
|
||||
* @codeCoverageIgnore We don't care about math that was not used
|
||||
*/
|
||||
// phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
|
||||
// phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
|
||||
final class MathGMP extends Math
|
||||
{
|
||||
/** @var GMP */
|
||||
private $mask;
|
||||
/** @var int */
|
||||
private $sizeof;
|
||||
|
||||
/**
|
||||
* @param int $sizeof
|
||||
*/
|
||||
public function __construct(int $sizeof)
|
||||
{
|
||||
$this->mask = \gmp_pow(2, $sizeof * 8) - 1;
|
||||
$this->sizeof = $sizeof;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value
|
||||
* @param int $shift
|
||||
* @return GMP
|
||||
*/
|
||||
public function shiftLeft($value, int $shift)
|
||||
{
|
||||
return ($value << $shift) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value
|
||||
* @param int $shift
|
||||
* @return GMP
|
||||
*/
|
||||
public function shiftRight($value, int $shift)
|
||||
{
|
||||
return $value >> $shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param GMP $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function add($value1, $value2)
|
||||
{
|
||||
return ($value1 + $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param int $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function addInt($value1, int $value2)
|
||||
{
|
||||
return ($value1 + $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param GMP $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function sub($value1, $value2)
|
||||
{
|
||||
return ($value1 - $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param int $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function subInt($value1, int $value2)
|
||||
{
|
||||
return ($value1 - $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param GMP $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function mul($value1, $value2)
|
||||
{
|
||||
return ($value1 * $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param int $value2
|
||||
* @return GMP
|
||||
*/
|
||||
public function mulInt($value1, int $value2)
|
||||
{
|
||||
return ($value1 * $value2) & $this->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GMP $value1
|
||||
* @param GMP $value2
|
||||
* @return GMP
|
||||
*/
|