Failed Conditions
Push — v7 ( 3f7b5a...d48fb3 )
by Florent
08:51 queued 04:13
created

BigInteger   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 304
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 28
lcom 1
cbo 0
dl 0
loc 304
rs 10
c 1
b 0
f 1

24 Methods

Rating   Name   Duplication   Size   Complexity  
A toBytes() 0 12 3
A compare() 0 4 1
A equals() 0 4 1
A random() 0 6 1
A gcd() 0 4 1
A lowerThan() 0 4 1
A lowerOrEqualThan() 0 4 1
A greaterThan() 0 4 1
A greaterOrEqualThan() 0 4 1
A isEven() 0 7 1
A isOdd() 0 4 1
A __construct() 0 4 1
A createFromGMPResource() 0 4 1
A createFromBinaryString() 0 6 1
A createFromDecimalString() 0 6 1
A createFromDecimal() 0 6 1
A toInteger() 0 10 2
A add() 0 6 1
A subtract() 0 6 1
A multiply() 0 6 1
A divide() 0 6 1
A modPow() 0 6 1
A mod() 0 6 1
A modInverse() 0 9 2
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) {
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...
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
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...
245
246
        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...
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
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 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
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...
305
        $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...
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