PseudoRandom::getMinNumber()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
/**
4
 * The pseudo-random generator class.
5
 */
6
7
namespace CryptoManana\Randomness;
8
9
use CryptoManana\Core\Abstractions\Randomness\AbstractGenerator as RandomnessSource;
10
use CryptoManana\Core\Interfaces\Randomness\SeedableGeneratorInterface as SeedAction;
11
use CryptoManana\Core\StringBuilder as StringBuilder;
12
13
/**
14
 * Class PseudoRandom - The pseudo-random generator object.
15
 *
16
 * @package CryptoManana\Randomness
17
 */
18
class PseudoRandom extends RandomnessSource implements SeedAction
19
{
20
    /**
21
     * The initialization seed value property storage for all instances.
22
     *
23
     * @var bool|int The generator's seed value.
24
     */
25
    protected static $seed = false;
26
27
    /**
28
     * Validates the given seed value and converts it to an integer.
29
     *
30
     * @param int|mixed $seed The initialization value.
31
     *
32
     * @return int The valid initialization value.
33
     * @throws \Exception Validation errors.
34
     */
35 11
    protected static function validateSeedValue($seed)
36
    {
37 11
        $seed = filter_var(
38 11
            $seed,
39 11
            FILTER_VALIDATE_INT,
40 11
            [
41 11
                "options" => [
42 11
                    "min_range" => -mt_getrandmax() - 1,
43 11
                    "max_range" => mt_getrandmax(),
44 11
                ],
45 11
            ]
46 11
        );
47
48 11
        if ($seed === false) {
49 1
            throw new \DomainException(
50 1
                "The provided seed value is of invalid type or is out of the supported range."
51 1
            );
52
        }
53
54 11
        return $seed;
55
    }
56
57
    /**
58
     * Internal static method for single point consumption of the randomness source that outputs integers.
59
     *
60
     * @param int $minimum The lowest value to be returned.
61
     * @param int $maximum The highest value to be returned.
62
     *
63
     * @return int Randomly generated integer number.
64
     */
65 19
    protected static function getInteger($minimum, $maximum)
66
    {
67 19
        return mt_rand($minimum, $maximum);
68
    }
69
70
    /**
71
     * Internal static method for single point consumption of the randomness source that outputs bytes.
72
     *
73
     * @param int $count The output string length based on the requested number of bytes.
74
     *
75
     * @return string Randomly generated string containing the requested number of bytes.
76
     */
77 10
    protected static function getEightBits($count)
78
    {
79 10
        $tmpBytes = '';
80
81 10
        for ($i = 1; $i <= $count; $i++) {
82 10
            $tmpBytes .= StringBuilder::getChr(self::getInteger(0, 255));
83
        }
84
85 10
        return $tmpBytes;
86
    }
87
88
    /**
89
     * The maximum supported integer.
90
     *
91
     * @return int The upper integer generation border.
92
     */
93 25
    public function getMaxNumber()
94
    {
95 25
        return mt_getrandmax();
96
    }
97
98
    /**
99
     * The minimum supported integer.
100
     *
101
     * @return int The lower integer generation border.
102
     */
103 26
    public function getMinNumber()
104
    {
105 26
        return -mt_getrandmax() - 1;
106
    }
107
108
    /**
109
     * The pseudo-random generator constructor.
110
     *
111
     * Note: This type of generator is auto-seeded on the first object creation.
112
     */
113 42
    public function __construct()
114
    {
115 42
        parent::__construct();
116
117 42
        if (self::$seed === false) {
118 1
            self::setSeed();
119
        }
120
    }
121
122
    /**
123
     * Get debug information for the class instance.
124
     *
125
     * @return array Debug information.
126
     */
127 1
    public function __debugInfo()
128
    {
129 1
        return [
130 1
            'systemPrecision' => self::$systemPrecision,
131 1
            'seed' => self::$seed,
132 1
        ];
133
    }
134
135
    /**
136
     * Seed the generator initialization or invoke auto-seeding.
137
     *
138
     * Note: Invokes auto-seeding if the `null` value is passed.
139
     *
140
     * @param null|int $seed The initialization value.
141
     *
142
     * @throws \Exception Validation errors.
143
     */
144 12
    public static function setSeed($seed = null)
145
    {
146 12
        if (!is_null($seed)) {
147 11
            $seed = self::validateSeedValue($seed);
148
        } else {
149
            // Get time information
150 2
            list($microSeconds, $seconds) = explode(' ', microtime());
151
152
            // Get microseconds as integer first
153 2
            $seed = (int)($microSeconds * 1000000) - 1;
154
155
            // A 32bit integer overflow  workaround for the UNIX timestamp format
156 2
            $seed = (PHP_MAJOR_VERSION === 5) ? abs($seconds - $seed) : $seconds + $seed;
157
        }
158
159 12
        $seed = (int)$seed;
160
161
        // Set the used seed value for history
162 12
        self::$seed = $seed;
163
164
        /**
165
         * {@internal Backward compatibility algorithm for seed must be used. }}
166
         */
167 12
        (PHP_VERSION_ID < 70100) ? mt_srand($seed) : ((PHP_VERSION_ID < 80300) ? mt_srand($seed, 1) : mt_srand($seed));
168
    }
169
170
    /**
171
     * Generate a random integer number in a certain range.
172
     *
173
     * Note: Passing `null` will use the default parameter value.
174
     *
175
     * @param null|int $from The lowest value to be returned (default => 0).
176
     * @param null|int $to The highest value to be returned (default => $this->getMaxNumber()).
177
     *
178
     * @return int Randomly generated integer number.
179
     * @throws \Exception Validation errors.
180
     */
181 22
    public function getInt($from = 0, $to = null)
182
    {
183 22
        $from = ($from === null) ? 0 : $from;
184 22
        $to = ($to === null) ? $this->getMaxNumber() : $to;
185
186 22
        $this->validateIntegerRange($from, $to);
187
188 17
        return self::getInteger($from, $to);
189
    }
190
191
    /**
192
     * Generate a random byte string.
193
     *
194
     * Note: PHP represents bytes as characters to make byte strings.
195
     *
196
     * @param int $length The output string length (default => 1).
197
     *
198
     * @return string Randomly generated string containing the requested number of bytes.
199
     * @throws \Exception Validation errors.
200
     */
201 11
    public function getBytes($length = 1)
202
    {
203 11
        $this->validatePositiveInteger($length);
204
205 10
        return self::getEightBits($length);
206
    }
207
}
208