Failed Conditions
Push — master ( 21f79c...ebcdaf )
by Florent
04:37
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 resource
22
     */
23
    private $value;
24
25
    /**
26
     * Converts base-10 and binary strings (base-256) to BigIntegers.
27
     *
28
     * @param \GMP|string $value
29
     * @param int         $base
30
     */
31
    private function __construct($value, $base)
32
    {
33
        if ($value instanceof \GMP) {
34
            $this->value = $value;
35
36
            return;
37
        }
38
39
        $this->value = gmp_init($value, $base);
40
    }
41
42
    /**
43
     * @param resource $value
44
     *
45
     * @return BigInteger
46
     */
47
    public static function createFromGMPResource($value)
48
    {
49
        Assertion::isInstanceOf($value, \GMP::class);
50
51
        return new self($value, 0);
52
    }
53
54
    /**
55
     * @param string $value
56
     *
57
     * @return BigInteger
58
     */
59
    public static function createFromBinaryString($value)
60
    {
61
        Assertion::string($value);
62
        $value = '0x'.bin2hex($value);
63
64
        return new self($value, 16);
65
    }
66
67
    /**
68
     * @param string $value
69
     *
70
     * @return BigInteger
71
     */
72
    public static function createFromDecimalString($value)
73
    {
74
        Assertion::string($value);
75
76
        return new self($value, 10);
77
    }
78
79
    /**
80
     * @param int $value
81
     *
82
     * @return BigInteger
83
     */
84
    public static function createFromDecimal($value)
85
    {
86
        Assertion::integer($value);
87
88
        return new self($value, 10);
89
    }
90
91
    /**
92
     * Converts a BigInteger to a binary string.
93
     *
94
     * @return string
95
     */
96
    public function toBytes()
97
    {
98
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
99
            return '';
100
        }
101
102
        $temp = gmp_strval(gmp_abs($this->value), 16);
103
        $temp = mb_strlen($temp, '8bit') & 1 ? '0'.$temp : $temp;
104
        $temp = hex2bin($temp);
105
106
        return ltrim($temp, chr(0));
107
    }
108
109
    /**
110
     * Converts a BigInteger to a binary string.
111
     *
112
     * @return int
113
     */
114
    public function toInteger()
115
    {
116
        if (gmp_cmp($this->value, gmp_init(0)) === 0) {
117
            return '';
118
        }
119
120
        $temp = gmp_strval(gmp_abs($this->value), 10);
121
122
        return (int) $temp;
123
    }
124
125
    /**
126
     * Adds two BigIntegers.
127
     *
128
     *  @param BigInteger $y
129
     *
130
     *  @return BigInteger
131
     */
132
    public function add(BigInteger $y)
133
    {
134
        $value = gmp_add($this->value, $y->value);
135
136
        return self::createFromGMPResource($value);
137
    }
138
139
    /**
140
     * Subtracts two BigIntegers.
141
     *
142
     *  @param BigInteger $y
143
     *
144
     *  @return BigInteger
145
     */
146
    public function subtract(BigInteger $y)
147
    {
148
        $value = gmp_sub($this->value, $y->value);
149
150
        return self::createFromGMPResource($value);
151
    }
152
153
    /**
154
     * Multiplies two BigIntegers.
155
     *
156
     * @param BigInteger $x
157
     *
158
     *  @return BigInteger
159
     */
160
    public function multiply(BigInteger $x)
161
    {
162
        $value = gmp_mul($this->value, $x->value);
163
164
        return self::createFromGMPResource($value);
165
    }
166
167
    /**
168
     * Divides two BigIntegers.
169
     *
170
     * @param BigInteger $x
171
     *
172
     *  @return BigInteger
173
     */
174
    public function divide(BigInteger $x)
175
    {
176
        $value = gmp_div($this->value, $x->value);
177
178
        return self::createFromGMPResource($value);
179
    }
180
181
    /**
182
     * Performs modular exponentiation.
183
     *
184
     * @param BigInteger $e
185
     * @param BigInteger $n
186
     *
187
     * @return BigInteger
188
     */
189
    public function modPow(BigInteger $e, BigInteger $n)
190
    {
191
        $value = gmp_powm($this->value, $e->value, $n->value);
192
193
        return self::createFromGMPResource($value);
194
    }
195
196
    /**
197
     * Performs modular exponentiation.
198
     *
199
     * @param BigInteger $d
200
     *
201
     * @return BigInteger
202
     */
203
    public function mod(BigInteger $d)
204
    {
205
        $value = gmp_mod($this->value, $d->value);
206
207
        return self::createFromGMPResource($value);
208
    }
209
210
    /**
211
     * Calculates modular inverses.
212
     *
213
     * @param BigInteger $n
214
     *
215
     * @return BigInteger
216
     */
217
    public function modInverse(BigInteger $n)
218
    {
219
        $value = gmp_invert($this->value, $n->value);
220
        Assertion::isInstanceOf($value, \GMP::class);
221
222
        return self::createFromGMPResource($value);
223
    }
224
225
    /**
226
     * Compares two numbers.
227
     *
228
     * @param BigInteger $y
229
     *
230
     * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
231
     */
232
    public function compare(BigInteger $y)
233
    {
234
        return gmp_cmp($this->value, $y->value);
235
    }
236
237
    /**
238
     * @param BigInteger $y
239
     *
240
     * @return bool
241
     */
242
    public function equals(BigInteger $y)
243
    {
244
        return 0 === $this->compare($y);
245
    }
246
247
    /**
248
     * @param BigInteger $y
249
     *
250
     * @return BigInteger
251
     */
252
    public static function random(BigInteger $y)
253
    {
254
        $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...
255
256
        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...
257
    }
258
259
    /**
260
     * @param BigInteger $y
261
     *
262
     * @return BigInteger
263
     */
264
    public function gcd(BigInteger $y)
265
    {
266
        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...
267
    }
268
269
    /**
270
     * @param BigInteger $y
271
     *
272
     * @return bool
273
     */
274
    public function lowerThan(BigInteger $y)
275
    {
276
        return 0 > $this->compare($y);
277
    }
278
279
    /**
280
     * @param BigInteger $y
281
     *
282
     * @return bool
283
     */
284
    public function lowerOrEqualThan(BigInteger $y)
285
    {
286
        return 0 >= $this->compare($y);
287
    }
288
289
    /**
290
     * @param BigInteger $y
291
     *
292
     * @return bool
293
     */
294
    public function greaterThan(BigInteger $y)
295
    {
296
        return 0 < $this->compare($y);
297
    }
298
299
    /**
300
     * @param BigInteger $y
301
     *
302
     * @return bool
303
     */
304
    public function greaterOrEqualThan(BigInteger $y)
305
    {
306
        return 0 <= $this->compare($y);
307
    }
308
309
    /**
310
     * @return bool
311
     */
312
    public function isEven()
313
    {
314
        $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...
315
        $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...
316
317
        return $this->mod($two)->equals($zero);
318
    }
319
320
    /**
321
     * @return bool
322
     */
323
    public function isOdd()
324
    {
325
        return !$this->isEven();
326
    }
327
}
328