Failed Conditions
Push — v7 ( 838dcb )
by Florent
04:30
created

src/Util/BigInteger.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose\Util;
13
14
use Assert\Assertion;
15
16
final class BigInteger
17
{
18
    /**
19
     * Holds the BigInteger's value.
20
     *
21
     * @var \GMP
22
     */
23
    private $value;
24
25
    /**
26
     * BigInteger constructor.
27
     *
28
     * @param \GMP $value
29
     */
30
    private function __construct(\GMP $value)
31
    {
32
        $this->value = $value;
33
    }
34
35
    /**
36
     * @param \GMP $value
37
     *
38
     * @return BigInteger
39
     */
40
    public static function createFromGMPResource(\GMP $value): BigInteger
41
    {
42
        return new self($value);
43
    }
44
45
    /**
46
     * @param string $value
47
     *
48
     * @return BigInteger
49
     */
50
    public static function createFromBinaryString(string $value): BigInteger
51
    {
52
        $value = gmp_init('0x'.bin2hex($value), 16);
53
54
        return new self($value);
55
    }
56
57
    /**
58
     * @param string $value
59
     *
60
     * @return BigInteger
61
     */
62
    public static function createFromDecimalString(string $value): BigInteger
63
    {
64
        $value = gmp_init($value, 10);
65
66
        return new self($value);
67
    }
68
69
    /**
70
     * @param int $value
71
     *
72
     * @return BigInteger
73
     */
74
    public static function createFromDecimal(int $value): BigInteger
75
    {
76
        $value = gmp_init($value, 10);
77
78
        return new self($value);
79
    }
80
81
    /**
82
     * Converts a BigInteger to a binary string.
83
     *
84
     * @return string
85
     */
86
    public function toBytes(): string
87
    {
88
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
89
            return '';
90
        }
91
92
        $temp = gmp_strval(gmp_abs($this->value), 16);
93
        $temp = mb_strlen($temp, '8bit') & 1 ? '0'.$temp : $temp;
94
        $temp = hex2bin($temp);
95
96
        return ltrim($temp, chr(0));
97
    }
98
99
    /**
100
     * Converts a BigInteger to a binary string.
101
     *
102
     * @return int
103
     */
104
    public function toInteger(): int
105
    {
106
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
107
            return '';
108
        }
109
110
        $temp = gmp_strval(gmp_abs($this->value), 10);
111
112
        return (int) $temp;
113
    }
114
115
    /**
116
     * Adds two BigIntegers.
117
     *
118
     *  @param BigInteger $y
119
     *
120
     *  @return BigInteger
121
     */
122
    public function add(BigInteger $y): BigInteger
123
    {
124
        $value = gmp_add($this->value, $y->value);
125
126
        return self::createFromGMPResource($value);
127
    }
128
129
    /**
130
     * Subtracts two BigIntegers.
131
     *
132
     *  @param BigInteger $y
133
     *
134
     *  @return BigInteger
135
     */
136
    public function subtract(BigInteger $y): BigInteger
137
    {
138
        $value = gmp_sub($this->value, $y->value);
139
140
        return self::createFromGMPResource($value);
141
    }
142
143
    /**
144
     * Multiplies two BigIntegers.
145
     *
146
     * @param BigInteger $x
147
     *
148
     *  @return BigInteger
149
     */
150
    public function multiply(BigInteger $x): BigInteger
151
    {
152
        $value = gmp_mul($this->value, $x->value);
153
154
        return self::createFromGMPResource($value);
155
    }
156
157
    /**
158
     * Divides two BigIntegers.
159
     *
160
     * @param BigInteger $x
161
     *
162
     *  @return BigInteger
163
     */
164
    public function divide(BigInteger $x): BigInteger
165
    {
166
        $value = gmp_div($this->value, $x->value);
167
168
        return self::createFromGMPResource($value);
169
    }
170
171
    /**
172
     * Performs modular exponentiation.
173
     *
174
     * @param BigInteger $e
175
     * @param BigInteger $n
176
     *
177
     * @return BigInteger
178
     */
179
    public function modPow(BigInteger $e, BigInteger $n): BigInteger
180
    {
181
        $value = gmp_powm($this->value, $e->value, $n->value);
182
183
        return self::createFromGMPResource($value);
184
    }
185
186
    /**
187
     * Performs modular exponentiation.
188
     *
189
     * @param BigInteger $d
190
     *
191
     * @return BigInteger
192
     */
193
    public function mod(BigInteger $d): BigInteger
194
    {
195
        $value = gmp_mod($this->value, $d->value);
196
197
        return self::createFromGMPResource($value);
198
    }
199
200
    /**
201
     * Calculates modular inverses.
202
     *
203
     * @param BigInteger $n
204
     *
205
     * @return BigInteger
206
     */
207
    public function modInverse(BigInteger $n): BigInteger
208
    {
209
        $value = gmp_invert($this->value, $n->value);
210
        Assertion::isInstanceOf($value, \GMP::class);
211
212
        return self::createFromGMPResource($value);
213
    }
214
215
    /**
216
     * Compares two numbers.
217
     *
218
     * @param BigInteger $y
219
     *
220
     * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
221
     */
222
    public function compare(BigInteger $y): int
223
    {
224
        return gmp_cmp($this->value, $y->value);
225
    }
226
227
    /**
228
     * @param BigInteger $y
229
     *
230
     * @return bool
231
     */
232
    public function equals(BigInteger $y): bool
233
    {
234
        return 0 === $this->compare($y);
235
    }
236
237
    /**
238
     * @param BigInteger $y
239
     *
240
     * @return BigInteger
241
     */
242
    public static function random(BigInteger $y): BigInteger
243
    {
244
        $zero = BigInteger::createFromDecimal(0);
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
245
246
        return BigInteger::createFromGMPResource(gmp_random_range($zero->value, $y->value));
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
247
    }
248
249
    /**
250
     * @param BigInteger $y
251
     *
252
     * @return BigInteger
253
     */
254
    public function gcd(BigInteger $y): BigInteger
255
    {
256
        return BigInteger::createFromGMPResource(gmp_gcd($this->value, $y->value));
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
257
    }
258
259
    /**
260
     * @param BigInteger $y
261
     *
262
     * @return bool
263
     */
264
    public function lowerThan(BigInteger $y): bool
265
    {
266
        return 0 > $this->compare($y);
267
    }
268
269
    /**
270
     * @param BigInteger $y
271
     *
272
     * @return bool
273
     */
274
    public function lowerOrEqualThan(BigInteger $y): bool
275
    {
276
        return 0 >= $this->compare($y);
277
    }
278
279
    /**
280
     * @param BigInteger $y
281
     *
282
     * @return bool
283
     */
284
    public function greaterThan(BigInteger $y): bool
285
    {
286
        return 0 < $this->compare($y);
287
    }
288
289
    /**
290
     * @param BigInteger $y
291
     *
292
     * @return bool
293
     */
294
    public function greaterOrEqualThan(BigInteger $y): bool
295
    {
296
        return 0 <= $this->compare($y);
297
    }
298
299
    /**
300
     * @return bool
301
     */
302
    public function isEven(): bool
303
    {
304
        $zero = BigInteger::createFromDecimal(0);
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
305
        $two  = BigInteger::createFromDecimal(2);
0 ignored issues
show
As per coding style, self should be used for accessing local static members.

This check looks for accesses to local static members using the fully qualified name instead of self::.

<?php

class Certificate {
    const TRIPLEDES_CBC = 'ASDFGHJKL';

    private $key;

    public function __construct()
    {
        $this->key = Certificate::TRIPLEDES_CBC;
    }
}

While this is perfectly valid, the fully qualified name of Certificate::TRIPLEDES_CBC could just as well be replaced by self::TRIPLEDES_CBC. Referencing local members with self:: assured the access will still work when the class is renamed, makes it perfectly clear that the member is in fact local and will usually be shorter.

Loading history...
306
307
        return $this->mod($two)->equals($zero);
308
    }
309
310
    /**
311
     * @return bool
312
     */
313
    public function isOdd(): bool
314
    {
315
        return !$this->isEven();
316
    }
317
}
318