Failed Conditions
Push — Documentation ( 72cdad...085e34 )
by Florent
02:30
created

BigInteger::mod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
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) {
0 ignored issues
show
Bug introduced by
The class GMP does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
34
            $this->value = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
35
36
            return;
37
        }
38
39
        $this->value = gmp_init($value, $base);
0 ignored issues
show
Documentation Bug introduced by
It seems like gmp_init($value, $base) of type object<GMP> is incompatible with the declared type resource of property $value.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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);
0 ignored issues
show
Documentation introduced by
$value is of type resource, but the function expects a object<GMP>|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
Coding Style introduced by
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
Coding Style introduced by
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
Coding Style introduced by
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
Coding Style introduced by
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
Coding Style introduced by
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