GmpMath::isPrime()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
namespace Mdanter\Ecc\Math;
4
5
use Mdanter\Ecc\Util\BinaryString;
6
use Mdanter\Ecc\Util\NumberSize;
7
8
class GmpMath implements GmpMathInterface
9
{
10
    /**
11
     * {@inheritDoc}
12
     * @see GmpMathInterface::cmp()
13
     */
14
    public function cmp(\GMP $first, \GMP $other): int
15
    {
16
        return gmp_cmp($first, $other);
17
    }
18
19
    /**
20
     * @param \GMP $first
21
     * @param \GMP $other
22
     * @return bool
23
     */
24
    public function equals(\GMP $first, \GMP $other): bool
25
    {
26
        return gmp_cmp($first, $other) === 0;
27
    }
28
    
29
    /**
30
     * {@inheritDoc}
31
     * @see GmpMathInterface::mod()
32
     */
33
    public function mod(\GMP $number, \GMP $modulus): \GMP
34
    {
35
        return gmp_mod($number, $modulus);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_mod($number, $modulus) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
36
    }
37
38
    /**
39
     * {@inheritDoc}
40
     * @see GmpMathInterface::add()
41
     */
42
    public function add(\GMP $augend, \GMP $addend): \GMP
43
    {
44
        return gmp_add($augend, $addend);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_add($augend, $addend) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
45
    }
46
47
    /**
48
     * {@inheritDoc}
49
     * @see GmpMathInterface::sub()
50
     */
51
    public function sub(\GMP $minuend, \GMP $subtrahend): \GMP
52
    {
53
        return gmp_sub($minuend, $subtrahend);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_sub($minuend, $subtrahend) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
54
    }
55
56
    /**
57
     * {@inheritDoc}
58
     * @see GmpMathInterface::mul()
59
     */
60
    public function mul(\GMP $multiplier, \GMP $multiplicand): \GMP
61
    {
62
        return gmp_mul($multiplier, $multiplicand);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_mul($multiplier, $multiplicand) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     * @see GmpMathInterface::div()
68
     */
69
    public function div(\GMP $dividend, \GMP $divisor): \GMP
70
    {
71
        return gmp_div($dividend, $divisor);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_div($dividend, $divisor) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
72
    }
73
74
    /**
75
     * {@inheritDoc}
76
     * @see GmpMathInterface::pow()
77
     */
78
    public function pow(\GMP $base, int $exponent): \GMP
79
    {
80
        return gmp_pow($base, $exponent);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_pow($base, $exponent) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
81
    }
82
83
    /**
84
     * {@inheritDoc}
85
     * @see GmpMathInterface::bitwiseAnd()
86
     */
87
    public function bitwiseAnd(\GMP $first, \GMP $other): \GMP
88
    {
89
        return gmp_and($first, $other);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_and($first, $other) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
90
    }
91
92
    /**
93
     * {@inheritDoc}
94
     * @see GmpMathInterface::rightShift()
95
     */
96
    public function rightShift(\GMP $number, int $positions): \GMP
97
    {
98
        // Shift 1 right = div / 2
99
        return gmp_div($number, gmp_pow(gmp_init(2, 10), $positions));
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_div($number, ...it(2, 10), $positions)) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     * @see GmpMathInterface::bitwiseXor()
105
     */
106
    public function bitwiseXor(\GMP $first, \GMP $other): \GMP
107
    {
108
        return gmp_xor($first, $other);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_xor($first, $other) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     * @see GmpMathInterface::leftShift()
114
     */
115
    public function leftShift(\GMP $number, int $positions): \GMP
116
    {
117
        // Shift 1 left = mul by 2
118
        return gmp_mul($number, gmp_pow(2, $positions));
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_mul($number, gmp_pow(2, $positions)) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     * @see GmpMathInterface::toString()
124
     */
125
    public function toString(\GMP $value): string
126
    {
127
        return gmp_strval($value);
128
    }
129
130
    /**
131
     * {@inheritDoc}
132
     * @see GmpMathInterface::hexDec()
133
     */
134
    public function hexDec(string $hex): string
135
    {
136
        return gmp_strval(gmp_init($hex, 16), 10);
137
    }
138
139
    /**
140
     * {@inheritDoc}
141
     * @see GmpMathInterface::decHex()
142
     */
143
    public function decHex(string $dec): string
144
    {
145
        $dec = gmp_init($dec, 10);
146
147
        if (gmp_cmp($dec, 0) < 0) {
148
            throw new \InvalidArgumentException('Unable to convert negative integer to string');
149
        }
150
151
        $hex = gmp_strval($dec, 16);
152
153
        if (BinaryString::length($hex) % 2 != 0) {
154
            $hex = '0'.$hex;
155
        }
156
157
        return $hex;
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     * @see GmpMathInterface::powmod()
163
     */
164
    public function powmod(\GMP $base, \GMP $exponent, \GMP $modulus): \GMP
165
    {
166
        if ($this->cmp($exponent, gmp_init(0, 10)) < 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(0, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

166
        if ($this->cmp($exponent, /** @scrutinizer ignore-type */ gmp_init(0, 10)) < 0) {
Loading history...
167
            throw new \InvalidArgumentException("Negative exponents (" . $this->toString($exponent) . ") not allowed.");
168
        }
169
170
        return gmp_powm($base, $exponent, $modulus);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_powm($base, $exponent, $modulus) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
171
    }
172
173
    /**
174
     * {@inheritDoc}
175
     * @see GmpMathInterface::isPrime()
176
     */
177
    public function isPrime(\GMP $n): bool
178
    {
179
        $prob = gmp_prob_prime($n);
180
181
        if ($prob > 0) {
182
            return true;
183
        }
184
185
        return false;
186
    }
187
188
    /**
189
     * {@inheritDoc}
190
     * @see GmpMathInterface::nextPrime()
191
     */
192
    public function nextPrime(\GMP $starting_value): \GMP
193
    {
194
        return gmp_nextprime($starting_value);
195
    }
196
197
    /**
198
     * {@inheritDoc}
199
     * @see GmpMathInterface::inverseMod()
200
     */
201
    public function inverseMod(\GMP $a, \GMP $m): \GMP
202
    {
203
        return gmp_invert($a, $m);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_invert($a, $m) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
204
    }
205
206
    /**
207
     * {@inheritDoc}
208
     * @see GmpMathInterface::jacobi()
209
     */
210
    public function jacobi(\GMP $a, \GMP $n): int
211
    {
212
        return gmp_jacobi($a, $n);
213
    }
214
215
    /**
216
     * @param \GMP $x
217
     * @param int $byteSize
218
     * @return string
219
     */
220
    public function intToFixedSizeString(\GMP $x, int $byteSize): string
221
    {
222
        if ($byteSize < 0) {
223
            throw new \RuntimeException("Byte size cannot be negative");
224
        }
225
226
        if (gmp_cmp($x, 0) < 0) {
227
            throw new \RuntimeException("x was negative - not yet supported");
228
        }
229
230
        $two = gmp_init(2);
231
        $range = gmp_pow($two, $byteSize * 8);
232
        if (NumberSize::bnNumBits($this, $x) >= NumberSize::bnNumBits($this, $range)) {
0 ignored issues
show
Bug introduced by
It seems like $range can also be of type resource; however, parameter $x of Mdanter\Ecc\Util\NumberSize::bnNumBits() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

232
        if (NumberSize::bnNumBits($this, $x) >= NumberSize::bnNumBits($this, /** @scrutinizer ignore-type */ $range)) {
Loading history...
233
            throw new \RuntimeException("Number overflows byte size");
234
        }
235
236
        $maskShift = gmp_pow($two, 8);
237
        $mask = gmp_mul(gmp_init(255), $range);
238
239
        $binary = '';
240
        for ($i = $byteSize - 1; $i >= 0; $i--) {
241
            $mask = gmp_div($mask, $maskShift);
242
            $binary .= pack('C', gmp_strval(gmp_div(gmp_and($x, $mask), gmp_pow($two, $i * 8)), 10));
243
        }
244
245
        return $binary;
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     * @see GmpMathInterface::intToString()
251
     */
252
    public function intToString(\GMP $x): string
253
    {
254
        if (gmp_cmp($x, 0) < 0) {
255
            throw new \InvalidArgumentException('Unable to convert negative integer to string');
256
        }
257
258
        $hex = gmp_strval($x, 16);
259
260
        if (BinaryString::length($hex) % 2 != 0) {
261
            $hex = '0'.$hex;
262
        }
263
264
        return pack('H*', $hex);
265
    }
266
267
    /**
268
     * {@inheritDoc}
269
     * @see GmpMathInterface::stringToInt()
270
     */
271
    public function stringToInt(string $s): \GMP
272
    {
273
        $result = gmp_init(0, 10);
274
        $sLen = BinaryString::length($s);
275
276
        for ($c = 0; $c < $sLen; $c ++) {
277
            $result = gmp_add(gmp_mul(256, $result), gmp_init(ord($s[$c]), 10));
278
        }
279
280
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     * @see GmpMathInterface::digestInteger()
286
     */
287
    public function digestInteger(\GMP $m): \GMP
288
    {
289
        return $this->stringToInt(hash('sha1', $this->intToString($m), true));
290
    }
291
292
    /**
293
     * {@inheritDoc}
294
     * @see GmpMathInterface::gcd2()
295
     */
296
    public function gcd2(\GMP $a, \GMP $b): \GMP
297
    {
298
        while ($this->cmp($a, gmp_init(0)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(0) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

298
        while ($this->cmp($a, /** @scrutinizer ignore-type */ gmp_init(0)) > 0) {
Loading history...
299
            $temp = $a;
300
            $a = $this->mod($b, $a);
301
            $b = $temp;
302
        }
303
304
        return $b;
305
    }
306
307
    /**
308
     * {@inheritDoc}
309
     * @see GmpMathInterface::baseConvert()
310
     */
311
    public function baseConvert(string $number, int $from, int $to): string
312
    {
313
        return gmp_strval(gmp_init($number, $from), $to);
314
    }
315
316
    /**
317
     * {@inheritDoc}
318
     * @see GmpMathInterface::getNumberTheory()
319
     */
320
    public function getNumberTheory(): NumberTheory
321
    {
322
        return new NumberTheory($this);
323
    }
324
325
    /**
326
     * @param \GMP $modulus
327
     * @return ModularArithmetic
328
     */
329
    public function getModularArithmetic(\GMP $modulus): ModularArithmetic
330
    {
331
        return new ModularArithmetic($this, $modulus);
332
    }
333
}
334