Complex classes like BigInteger often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BigInteger, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class BigInteger |
||
15 | { |
||
16 | const MONTGOMERY = 0; |
||
17 | |||
18 | const BARRETT = 1; |
||
19 | |||
20 | const POWEROF2 = 2; |
||
21 | |||
22 | const CLASSIC = 3; |
||
23 | |||
24 | const NONE = 4; |
||
25 | |||
26 | /**#@+ |
||
27 | * Array constants |
||
28 | * |
||
29 | * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and |
||
30 | * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them. |
||
31 | * |
||
32 | */ |
||
33 | /** |
||
34 | * $result[self::VALUE] contains the value. |
||
35 | */ |
||
36 | const VALUE = 0; |
||
37 | /** |
||
38 | * $result[self::SIGN] contains the sign. |
||
39 | */ |
||
40 | const SIGN = 1; |
||
41 | /**#@-*/ |
||
42 | |||
43 | /**#@+ |
||
44 | */ |
||
45 | /** |
||
46 | * Cache constants. |
||
47 | * |
||
48 | * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. |
||
49 | */ |
||
50 | const VARIABLE = 0; |
||
51 | /** |
||
52 | * $cache[self::DATA] contains the cached data. |
||
53 | */ |
||
54 | const DATA = 1; |
||
55 | /**#@-*/ |
||
56 | |||
57 | /** |
||
58 | * Karatsuba Cutoff. |
||
59 | * |
||
60 | * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? |
||
61 | */ |
||
62 | const KARATSUBA_CUTOFF = 25; |
||
63 | |||
64 | /**#@+ |
||
65 | * Static properties used by the pure-PHP implementation. |
||
66 | * |
||
67 | * @see __construct() |
||
68 | */ |
||
69 | protected static $base; |
||
70 | protected static $baseFull; |
||
71 | protected static $maxDigit; |
||
72 | protected static $msb; |
||
73 | |||
74 | /** |
||
75 | * $max10 in greatest $max10Len satisfying |
||
76 | * $max10 = 10**$max10Len <= 2**$base. |
||
77 | */ |
||
78 | protected static $max10; |
||
79 | |||
80 | /** |
||
81 | * $max10Len in greatest $max10Len satisfying |
||
82 | * $max10 = 10**$max10Len <= 2**$base. |
||
83 | */ |
||
84 | protected static $max10Len; |
||
85 | protected static $maxDigit2; |
||
86 | /**#@-*/ |
||
87 | |||
88 | /** |
||
89 | * Holds the BigInteger's value. |
||
90 | * |
||
91 | * @var resource |
||
92 | */ |
||
93 | private $value; |
||
94 | |||
95 | /** |
||
96 | * Holds the BigInteger's magnitude. |
||
97 | * |
||
98 | * @var bool |
||
99 | */ |
||
100 | private $is_negative = false; |
||
101 | |||
102 | /** |
||
103 | * Precision. |
||
104 | */ |
||
105 | private $precision = -1; |
||
106 | |||
107 | /** |
||
108 | * Precision Bitmask. |
||
109 | */ |
||
110 | private $bitmask = false; |
||
111 | |||
112 | /** |
||
113 | * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers. |
||
114 | * |
||
115 | * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using |
||
116 | * two's compliment. The sole exception to this is -10, which is treated the same as 10 is. |
||
117 | * |
||
118 | * Here's an example: |
||
119 | * <code> |
||
120 | * <?php |
||
121 | * $a = new \Jose\Util\in base-16 |
||
122 | * |
||
123 | * echo $a->toString(); // outputs 50 |
||
124 | * ?> |
||
125 | * </code> |
||
126 | * |
||
127 | * @param $x base-10 number or base-$base number if $base set. |
||
128 | * @param int $base |
||
129 | */ |
||
130 | public function __construct($x = 0, $base = 10) |
||
227 | |||
228 | /** |
||
229 | * Converts a BigInteger to a byte string (eg. base-256). |
||
230 | * |
||
231 | * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're |
||
232 | * saved as two's compliment. |
||
233 | * |
||
234 | * Here's an example: |
||
235 | * <code> |
||
236 | * <?php |
||
237 | * $a = new \Jose\Util\ger('65'); |
||
238 | * |
||
239 | * echo $a->toBytes(); // outputs chr(65) |
||
240 | * ?> |
||
241 | * </code> |
||
242 | * |
||
243 | * @param bool $twos_compliment |
||
244 | * |
||
245 | * @return string |
||
246 | * |
||
247 | */ |
||
248 | public function toBytes($twos_compliment = false) |
||
282 | |||
283 | /** |
||
284 | * Adds two BigIntegers. |
||
285 | * |
||
286 | * Here's an example: |
||
287 | * <code> |
||
288 | * <?php |
||
289 | * $a = new \Jose\Util\ger('10'); |
||
290 | * $b = new \Jose\Util\ger('20'); |
||
291 | * |
||
292 | * $c = $a->add($b); |
||
293 | * |
||
294 | * echo $c->toString(); // outputs 30 |
||
295 | * ?> |
||
296 | * </code> |
||
297 | * |
||
298 | * @param \Jose\Util\Integer $y |
||
299 | * |
||
300 | * @return \Jose\Util\BigInteger |
||
301 | * |
||
302 | */ |
||
303 | public function add(BigInteger $y) |
||
310 | |||
311 | /** |
||
312 | * Subtracts two BigIntegers. |
||
313 | * |
||
314 | * Here's an example: |
||
315 | * <code> |
||
316 | * <?php |
||
317 | * $a = new \Jose\Util\ger('10'); |
||
318 | * $b = new \Jose\Util\ger('20'); |
||
319 | * |
||
320 | * $c = $a->subtract($b); |
||
321 | * |
||
322 | * echo $c->toString(); // outputs -10 |
||
323 | * ?> |
||
324 | * </code> |
||
325 | * |
||
326 | * @param \Jose\Util\Integer $y |
||
327 | * |
||
328 | * @return \Jose\Util\BigInteger |
||
329 | * |
||
330 | */ |
||
331 | public function subtract(BigInteger $y) |
||
338 | |||
339 | /** |
||
340 | * Multiplies two BigIntegers. |
||
341 | * |
||
342 | * Here's an example: |
||
343 | * <code> |
||
344 | * <?php |
||
345 | * $a = new \Jose\Util\ger('10'); |
||
346 | * $b = new \Jose\Util\ger('20'); |
||
347 | * |
||
348 | * $c = $a->multiply($b); |
||
349 | * |
||
350 | * echo $c->toString(); // outputs 200 |
||
351 | * ?> |
||
352 | * </code> |
||
353 | * |
||
354 | * @param \Jose\Util\Integer $x |
||
355 | * |
||
356 | * @return \Jose\Util\BigInteger |
||
357 | */ |
||
358 | public function multiply(BigInteger $x) |
||
365 | |||
366 | /** |
||
367 | * Divides two BigIntegers. |
||
368 | * |
||
369 | * Returns an array whose first element contains the quotient and whose second element contains the |
||
370 | * "common residue". If the remainder would be positive, the "common residue" and the remainder are the |
||
371 | * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder |
||
372 | * and the divisor (basically, the "common residue" is the first positive modulo). |
||
373 | * |
||
374 | * Here's an example: |
||
375 | * <code> |
||
376 | * <?php |
||
377 | * $a = new \Jose\Util\ger('10'); |
||
378 | * $b = new \Jose\Util\ger('20'); |
||
379 | * |
||
380 | * list($quotient, $remainder) = $a->divide($b); |
||
381 | * |
||
382 | * echo $quotient->toString(); // outputs 0 |
||
383 | * echo "\r\n"; |
||
384 | * echo $remainder->toString(); // outputs 10 |
||
385 | * ?> |
||
386 | * </code> |
||
387 | * |
||
388 | * @param \Jose\Util\Integer $y |
||
389 | * |
||
390 | * @return array |
||
391 | * |
||
392 | */ |
||
393 | public function divide(BigInteger $y) |
||
406 | |||
407 | /** |
||
408 | * Performs modular exponentiation. |
||
409 | * |
||
410 | * Here's an example: |
||
411 | * <code> |
||
412 | * <?php |
||
413 | * $a = new \Jose\Util\ger('10'); |
||
414 | * $b = new \Jose\Util\ger('20'); |
||
415 | * $c = new \Jose\Util\ger('30'); |
||
416 | * |
||
417 | * $c = $a->modPow($b, $c); |
||
418 | * |
||
419 | * echo $c->toString(); // outputs 10 |
||
420 | * ?> |
||
421 | * </code> |
||
422 | * |
||
423 | * @param \Jose\Util\Integer $e |
||
424 | * @param \Jose\Util\Integer $n |
||
425 | * |
||
426 | * @return \Jose\Util\BigInteger |
||
427 | * |
||
428 | * and although the approach involving repeated squaring does vastly better, it, too, is impractical |
||
429 | * for our purposes. The reason being that division - by far the most complicated and time-consuming |
||
430 | * of the basic operations (eg. +,-,*,/) - occurs multiple times within it. |
||
431 | * |
||
432 | * Modular reductions resolve this issue. Although an individual modular reduction takes more time |
||
433 | * then an individual division, when performed in succession (with the same modulo), they're a lot faster. |
||
434 | * |
||
435 | * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction, |
||
436 | * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the |
||
437 | * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because |
||
438 | * the product of two odd numbers is odd), but what about when RSA isn't used? |
||
439 | * |
||
440 | * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a |
||
441 | * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the |
||
442 | * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however, |
||
443 | * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and |
||
444 | * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. |
||
445 | * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. |
||
446 | */ |
||
447 | public function modPow(BigInteger $e, BigInteger $n) |
||
467 | |||
468 | /** |
||
469 | * Calculates modular inverses. |
||
470 | * |
||
471 | * Say you have (30 mod 17 * x mod 17) mod 17 == 1. x can be found using modular inverses. |
||
472 | * |
||
473 | * Here's an example: |
||
474 | * <code> |
||
475 | * <?php |
||
476 | * $a = new \Jose\Util\teger(30); |
||
477 | * $b = new \Jose\Util\teger(17); |
||
478 | * |
||
479 | * $c = $a->modInverse($b); |
||
480 | * echo $c->toString(); // outputs 4 |
||
481 | * |
||
482 | * echo "\r\n"; |
||
483 | * |
||
484 | * $d = $a->multiply($c); |
||
485 | * list(, $d) = $d->divide($b); |
||
486 | * echo $d; // outputs 1 (as per the definition of modular inverse) |
||
487 | * ?> |
||
488 | * </code> |
||
489 | * |
||
490 | * @param \Jose\Util\Integer $n |
||
491 | * |
||
492 | * @return \Jose\Util\eger|false |
||
493 | * |
||
494 | */ |
||
495 | public function modInverse(BigInteger $n) |
||
502 | |||
503 | /** |
||
504 | * Absolute value. |
||
505 | * |
||
506 | * @return \Jose\Util\BigInteger |
||
507 | */ |
||
508 | public function abs() |
||
516 | |||
517 | /** |
||
518 | * Compares two numbers. |
||
519 | * |
||
520 | * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite. The reason for this is |
||
521 | * demonstrated thusly: |
||
522 | * |
||
523 | * $x > $y: $x->compare($y) > 0 |
||
524 | * $x < $y: $x->compare($y) < 0 |
||
525 | * $x == $y: $x->compare($y) == 0 |
||
526 | * |
||
527 | * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). |
||
528 | * |
||
529 | * @param \Jose\Util\Integer $y |
||
530 | * |
||
531 | * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. |
||
532 | * |
||
533 | */ |
||
534 | public function compare(BigInteger $y) |
||
538 | |||
539 | /** |
||
540 | * Logical Left Shift. |
||
541 | * |
||
542 | * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. |
||
543 | * |
||
544 | * @param int $shift |
||
545 | * |
||
546 | * @return \Jose\Util\BigInteger |
||
547 | * |
||
548 | */ |
||
549 | public function bitwise_leftShift($shift) |
||
563 | |||
564 | /** |
||
565 | * Generates a random BigInteger. |
||
566 | * |
||
567 | * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not. |
||
568 | * |
||
569 | * @param int $size |
||
570 | * |
||
571 | * @return \Jose\Util\BigInteger |
||
572 | */ |
||
573 | private static function _random_number_helper($size) |
||
577 | |||
578 | /** |
||
579 | * Generate a random number. |
||
580 | * |
||
581 | * Returns a random number between $min and $max where $min and $max |
||
582 | * can be defined using one of the two methods: |
||
583 | * |
||
584 | * BigInteger::random($min, $max) |
||
585 | * BigInteger::random($max, $min) |
||
586 | * |
||
587 | * @param \Jose\Util\BigInteger $min |
||
588 | * @param \Jose\Util\BigInteger $max |
||
589 | * |
||
590 | * @return \Jose\Util\BigInteger |
||
591 | */ |
||
592 | public static function random(BigInteger $min, BigInteger $max) |
||
647 | |||
648 | /** |
||
649 | * Normalize. |
||
650 | * |
||
651 | * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision |
||
652 | * |
||
653 | * @param \Jose\Util\BigInteger |
||
654 | * |
||
655 | * @return \Jose\Util\BigInteger |
||
656 | */ |
||
657 | private function _normalize($result) |
||
668 | } |
||
669 |
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 thecomposer.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
orrequire-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 you have not tested against this specific condition, such errors might go unnoticed.