Failed Conditions
Push — v7 ( 3f7b5a...d48fb3 )
by Florent
08:51 queued 04:13
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
final class BigInteger
15
{
16
    /**
17
     * Holds the BigInteger's value.
18
     *
19
     * @var \GMP
20
     */
21
    private $value;
22
23
    /**
24
     * BigInteger constructor.
25
     *
26
     * @param \GMP $value
27
     */
28
    private function __construct(\GMP $value)
29
    {
30
        $this->value = $value;
31
    }
32
33
    /**
34
     * @param \GMP $value
35
     *
36
     * @return BigInteger
37
     */
38
    public static function createFromGMPResource(\GMP $value): BigInteger
39
    {
40
        return new self($value);
41
    }
42
43
    /**
44
     * @param string $value
45
     *
46
     * @return BigInteger
47
     */
48
    public static function createFromBinaryString(string $value): BigInteger
49
    {
50
        $value = gmp_init('0x'.bin2hex($value), 16);
51
52
        return new self($value);
53
    }
54
55
    /**
56
     * @param string $value
57
     *
58
     * @return BigInteger
59
     */
60
    public static function createFromDecimalString(string $value): BigInteger
61
    {
62
        $value = gmp_init($value, 10);
63
64
        return new self($value);
65
    }
66
67
    /**
68
     * @param int $value
69
     *
70
     * @return BigInteger
71
     */
72
    public static function createFromDecimal(int $value): BigInteger
73
    {
74
        $value = gmp_init($value, 10);
75
76
        return new self($value);
77
    }
78
79
    /**
80
     * Converts a BigInteger to a binary string.
81
     *
82
     * @return string
83
     */
84
    public function toBytes(): string
85
    {
86
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
87
            return '';
88
        }
89
90
        $temp = gmp_strval(gmp_abs($this->value), 16);
91
        $temp = mb_strlen($temp, '8bit') & 1 ? '0'.$temp : $temp;
92
        $temp = hex2bin($temp);
93
94
        return ltrim($temp, chr(0));
95
    }
96
97
    /**
98
     * Converts a BigInteger to a binary string.
99
     *
100
     * @return int
101
     */
102
    public function toInteger(): int
103
    {
104
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
105
            return '';
106
        }
107
108
        $temp = gmp_strval(gmp_abs($this->value), 10);
109
110
        return (int) $temp;
111
    }
112
113
    /**
114
     * Adds two BigIntegers.
115
     *
116
     *  @param BigInteger $y
117
     *
118
     *  @return BigInteger
119
     */
120
    public function add(BigInteger $y): BigInteger
121
    {
122
        $value = gmp_add($this->value, $y->value);
123
124
        return self::createFromGMPResource($value);
125
    }
126
127
    /**
128
     * Subtracts two BigIntegers.
129
     *
130
     *  @param BigInteger $y
131
     *
132
     *  @return BigInteger
133
     */
134
    public function subtract(BigInteger $y): BigInteger
135
    {
136
        $value = gmp_sub($this->value, $y->value);
137
138
        return self::createFromGMPResource($value);
139
    }
140
141
    /**
142
     * Multiplies two BigIntegers.
143
     *
144
     * @param BigInteger $x
145
     *
146
     *  @return BigInteger
147
     */
148
    public function multiply(BigInteger $x): BigInteger
149
    {
150
        $value = gmp_mul($this->value, $x->value);
151
152
        return self::createFromGMPResource($value);
153
    }
154
155
    /**
156
     * Divides two BigIntegers.
157
     *
158
     * @param BigInteger $x
159
     *
160
     *  @return BigInteger
161
     */
162
    public function divide(BigInteger $x): BigInteger
163
    {
164
        $value = gmp_div($this->value, $x->value);
165
166
        return self::createFromGMPResource($value);
167
    }
168
169
    /**
170
     * Performs modular exponentiation.
171
     *
172
     * @param BigInteger $e
173
     * @param BigInteger $n
174
     *
175
     * @return BigInteger
176
     */
177
    public function modPow(BigInteger $e, BigInteger $n): BigInteger
178
    {
179
        $value = gmp_powm($this->value, $e->value, $n->value);
180
181
        return self::createFromGMPResource($value);
182
    }
183
184
    /**
185
     * Performs modular exponentiation.
186
     *
187
     * @param BigInteger $d
188
     *
189
     * @return BigInteger
190
     */
191
    public function mod(BigInteger $d): BigInteger
192
    {
193
        $value = gmp_mod($this->value, $d->value);
194
195
        return self::createFromGMPResource($value);
196
    }
197
198
    /**
199
     * Calculates modular inverses.
200
     *
201
     * @param BigInteger $n
202
     *
203
     * @return BigInteger
204
     */
205
    public function modInverse(BigInteger $n): BigInteger
206
    {
207
        $value = gmp_invert($this->value, $n->value);
208
        if (!$value instanceof \GMP) {
209
            throw new \InvalidArgumentException();
210
        }
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