Passed
Pull Request — master (#28)
by kacper
03:15 queued 01:15
created

BC::checkNumber()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 9.9666
c 0
b 0
f 0
cc 3
nc 2
nop 1
crap 3
1
<?php
2
3
namespace BCMathExtended;
4
5
/**
6
 * Class BC
7
 * @package BCMathExtended
8
 */
9
class BC
10
{
11
    const COMPARE_EQUAL = 0;
12
    const COMPARE_LEFT_GRATER = 1;
13
    const COMPARE_RIGHT_GRATER = -1;
14
15
    const DEFAULT_SCALE = 100;
16
17
    const MAX_BASE = 256;
18
19
    const BIT_OPERATOR_AND = 'and';
20
    const BIT_OPERATOR_OR = 'or';
21
    const BIT_OPERATOR_XOR = 'xor';
22
23
    /**
24
     * @param int|string $number
25
     * @param int $precision
26
     * @return string
27
     */
28 47
    public static function round($number, $precision = 0)
29
    {
30 47
        $number = self::convertScientificNotationToString($number);
31 47
        if (self::checkIsFloat($number)) {
32 36
            if (self::isNegative($number)) {
33 4
                return self::sub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
34
            }
35
36 32
            return self::add($number, '0.' . str_repeat('0', $precision) . '5', $precision);
37
        }
38
39 11
        return self::checkNumber($number);
40
    }
41
42
    /**
43
     * @param int|string|float $number
44
     * @return string
45
     */
46 359
    public static function convertScientificNotationToString($number)
47
    {
48
        // check if number is in scientific notation, first use stripos as is faster then preg_match
49 359
        if (false !== stripos($number, 'E') && preg_match('/(-?(\d+\.)?\d+)E([+-]?)(\d+)/i', $number, $regs)) {
50
            // calculate final scale of number
51 59
            $scale = $regs[4] + self::getDecimalsLengthFromNumber($regs[1]);
52 59
            $pow = self::pow(10, $regs[4], $scale);
53 59
            if ('-' === $regs[3]) {
54 25
                $number = self::div($regs[1], $pow, $scale);
55
            } else {
56 34
                $number = self::mul($pow, $regs[1], $scale);
57
            }
58
            // remove unnecessary 0 from 0.000 is a 0
59 59
            $number = rtrim($number, '0');
60
            // if you remove 0 you must clean dot
61 59
            $number = rtrim($number, '.');
62
        }
63
64 359
        return self::checkNumber($number);
65
    }
66
67
    /**
68
     * @param int|string|float $number
69
     * @return int
70
     */
71 91
    public static function getDecimalsLengthFromNumber($number)
72
    {
73 91
        $check = explode('.', $number);
74 91
        if (!empty($check[1])) {
75 62
            return strlen($check[1]);
76
        }
77
78 29
        return 0;
79
    }
80
81
    /**
82
     * @param string $leftOperand
83
     * @param string $rightOperand
84
     * @param null|int $scale
85
     * @return string
86
     */
87 141
    public static function pow($leftOperand, $rightOperand, $scale = null)
88
    {
89 141
        $leftOperand = self::convertScientificNotationToString($leftOperand);
90 141
        $rightOperand = self::convertScientificNotationToString($rightOperand);
91
92 141
        if (self::checkIsFloat($rightOperand)) {
93 7
            if (null === $scale) {
94 2
                return self::powFractional($leftOperand, $rightOperand);
95
            }
96
97 5
            return self::powFractional($leftOperand, $rightOperand, $scale);
98
        }
99
100 141
        if (null === $scale) {
101 69
            return bcpow($leftOperand, $rightOperand);
102
        }
103
104 75
        return bcpow($leftOperand, $rightOperand, $scale);
105
    }
106
107
    /**
108
     * @param int|string $number
109
     * @return bool
110
     */
111 257
    private static function checkIsFloat($number)
112
    {
113 257
        return false !== strpos($number, '.');
114
    }
115
116
    /**
117
     * @param string $leftOperand
118
     * @param string $rightOperand
119
     * @param null|int $scale
120
     * @return string
121
     */
122 7
    private static function powFractional($leftOperand, $rightOperand, $scale = null)
123
    {
124
        // we need to increased scale to get correct results and avoid rounding error
125 7
        $increasedScale = null === $scale ? self::getScale() : $scale;
126 7
        $increasedScale *= 2;
127 7
        $decimals = explode('.', $rightOperand);
128
129 7
        return self::checkNumber(
130 7
            self::mul(
131 7
                self::exp(
132 7
                    self::mul(
133 7
                        self::log($leftOperand),
134 7
                        '0.' . $decimals[1],
135 7
                        $increasedScale
136
                    )
137
                ),
138 7
                self::pow($leftOperand, $decimals[0], $increasedScale),
139 7
                $scale
140
            )
141
        );
142
    }
143
144
    /**
145
     * @return int
146
     */
147 35
    public static function getScale()
148
    {
149 35
        $sqrt = self::sqrt('2');
150
151 35
        return strlen(substr($sqrt, strpos($sqrt, '.') + 1));
152
    }
153
154
    /**
155
     * @param string $operand
156
     * @param null|int $scale
157
     * @return string
158
     */
159 40
    public static function sqrt($operand, $scale = null)
160
    {
161 40
        $operand = self::convertScientificNotationToString($operand);
162
163 40
        if (null === $scale) {
164 36
            return bcsqrt($operand);
165
        }
166
167 5
        return bcsqrt($operand, $scale);
168
    }
169
170
    /**
171
     * @param int|string $number
172
     * @return int|string
173
     */
174 359
    private static function checkNumber($number)
175
    {
176 359
        $number = str_replace('+', '', filter_var($number, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
177 359
        if ('-0' === $number || !is_numeric($number)) {
178 28
            return '0';
179
        }
180
181 356
        return $number;
182
    }
183
184
    /**
185
     * @param string $leftOperand
186
     * @param string $rightOperand
187
     * @param null|int $scale
188
     * @return string
189
     */
190 161 View Code Duplication
    public static function mul($leftOperand, $rightOperand, $scale = null)
191
    {
192 161
        $leftOperand = self::convertScientificNotationToString($leftOperand);
193 161
        $rightOperand = self::convertScientificNotationToString($rightOperand);
194
195 161
        if (null === $scale) {
196 55
            return bcmul($leftOperand, $rightOperand);
197
        }
198
199 108
        return bcmul($leftOperand, $rightOperand, $scale);
200
    }
201
202
    /**
203
     * @param string $arg
204
     * @return string
205
     */
206 15
    public static function exp($arg)
207
    {
208 15
        $scale = self::DEFAULT_SCALE;
209 15
        $result = '1';
210 15
        for ($i = 299; $i > 0; $i--) {
211 15
            $result = self::add(self::mul(self::div($result, $i, $scale), $arg, $scale), 1, $scale);
212
        }
213
214 15
        return $result;
215
    }
216
217
    /**
218
     * @param string $leftOperand
219
     * @param string $rightOperand
220
     * @param null|int $scale
221
     * @return string
222
     */
223 155 View Code Duplication
    public static function add($leftOperand, $rightOperand, $scale = null)
224
    {
225 155
        $leftOperand = self::convertScientificNotationToString($leftOperand);
226 155
        $rightOperand = self::convertScientificNotationToString($rightOperand);
227
228 155
        if (null === $scale) {
229 36
            return bcadd($leftOperand, $rightOperand);
230
        }
231
232 122
        return bcadd($leftOperand, $rightOperand, $scale);
233
    }
234
235
    /**
236
     * @param string $leftOperand
237
     * @param string $rightOperand
238
     * @param null|int $scale
239
     * @return string
240
     */
241 125 View Code Duplication
    public static function div($leftOperand, $rightOperand, $scale = null)
242
    {
243 125
        $leftOperand = self::convertScientificNotationToString($leftOperand);
244 125
        $rightOperand = self::convertScientificNotationToString($rightOperand);
245
246 125
        if (null === $scale) {
247 40
            return bcdiv($leftOperand, $rightOperand);
248
        }
249
250 93
        return bcdiv($leftOperand, $rightOperand, $scale);
251
    }
252
253
    /**
254
     * @param string $arg
255
     * @return string
256
     */
257 12
    public static function log($arg)
258
    {
259 12
        $arg = self::convertScientificNotationToString($arg);
260 12
        if ($arg === '0') {
261 1
            return '-INF';
262
        }
263 11
        if (self::COMPARE_RIGHT_GRATER === self::comp($arg, '0')) {
264 1
            return 'NAN';
265
        }
266 10
        $scale = self::DEFAULT_SCALE;
267 10
        $m = (string)log($arg);
268 10
        $x = self::sub(self::div($arg, self::exp($m), $scale), '1', $scale);
269 10
        $res = '0';
270 10
        $pow = '1';
271 10
        $i = 1;
272
        do {
273 10
            $pow = self::mul($pow, $x, $scale);
274 10
            $sum = self::div($pow, $i, $scale);
275 10
            if ($i % 2 === 1) {
276 10
                $res = self::add($res, $sum, $scale);
277
            } else {
278 9
                $res = self::sub($res, $sum, $scale);
279
            }
280 10
            $i++;
281 10
        } while (self::comp($sum, '0', $scale));
282
283 10
        return self::add($res, $m, $scale);
284
    }
285
286
    /**
287
     * @param string $leftOperand
288
     * @param string $rightOperand
289
     * @param null|int $scale
290
     * @return int
291
     */
292 59
    public static function comp($leftOperand, $rightOperand, $scale = null)
293
    {
294 59
        $leftOperand = self::convertScientificNotationToString($leftOperand);
295 59
        $rightOperand = self::convertScientificNotationToString($rightOperand);
296
297 59
        if (null === $scale) {
298 48
            return bccomp($leftOperand, $rightOperand, max(strlen($leftOperand), strlen($rightOperand)));
299
        }
300
301 21
        return bccomp(
302 21
            $leftOperand,
303 21
            $rightOperand,
304 21
            $scale
305
        );
306
    }
307
308
    /**
309
     * @param string $leftOperand
310
     * @param string $rightOperand
311
     * @param null|int $scale
312
     * @return string
313
     */
314 73 View Code Duplication
    public static function sub($leftOperand, $rightOperand, $scale = null)
315
    {
316 73
        $leftOperand = self::convertScientificNotationToString($leftOperand);
317 73
        $rightOperand = self::convertScientificNotationToString($rightOperand);
318
319 73
        if (null === $scale) {
320 42
            return bcsub($leftOperand, $rightOperand);
321
        }
322
323 33
        return bcsub($leftOperand, $rightOperand, $scale);
324
    }
325
326
    /**
327
     * @param $number
328
     * @return bool
329
     */
330 148
    private static function isNegative($number)
331
    {
332 148
        return 0 === strncmp('-', $number, 1);
333
    }
334
335
    /**
336
     * @param int|string $min
337
     * @param int|string $max
338
     * @return string
339
     */
340 2
    public static function rand($min, $max)
341
    {
342 2
        $max = self::convertScientificNotationToString($max);
343 2
        $min = self::convertScientificNotationToString($min);
344
345 2
        $difference = self::add(self::sub($max, $min), 1);
346 2
        $randPercent = self::div(mt_rand(), mt_getrandmax(), 8);
347
348 2
        return self::add($min, self::mul($difference, $randPercent, 8), 0);
349
    }
350
351
    /**
352
     * @param array|int|string,...
353
     * @return null|string
354
     */
355 1 View Code Duplication
    public static function max()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
356
    {
357 1
        $max = null;
358 1
        $args = func_get_args();
359 1
        if (is_array($args[0])) {
360 1
            $args = $args[0];
361
        }
362 1
        foreach ($args as $number) {
363 1
            $number = self::convertScientificNotationToString($number);
364 1
            if (null === $max) {
365 1
                $max = $number;
366 1
            } elseif (self::comp($max, $number) === self::COMPARE_RIGHT_GRATER) {
367 1
                $max = $number;
368
            }
369
        }
370
371 1
        return $max;
372
    }
373
374
    /**
375
     * @param array|int|string,...
376
     * @return null|string
377
     */
378 1 View Code Duplication
    public static function min()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
379
    {
380 1
        $min = null;
381 1
        $args = func_get_args();
382 1
        if (is_array($args[0])) {
383 1
            $args = $args[0];
384
        }
385 1
        foreach ($args as $number) {
386 1
            $number = self::convertScientificNotationToString($number);
387 1
            if (null === $min) {
388 1
                $min = $number;
389 1
            } elseif (self::comp($min, $number) === self::COMPARE_LEFT_GRATER) {
390 1
                $min = $number;
391
            }
392
        }
393
394 1
        return $min;
395
    }
396
397
    /**
398
     * @param int|string $number
399
     * @param int $precision
400
     * @return string
401
     */
402 17 View Code Duplication
    public static function roundDown($number, $precision = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
403
    {
404 17
        $number = self::convertScientificNotationToString($number);
405 17
        $multiply = self::pow(10, (string)abs($precision));
406
407 17
        return $precision < 0
408
            ?
409 4
            self::mul(
410 4
                self::floor(self::div($number, $multiply, self::getDecimalsLengthFromNumber($number))), $multiply,
411 4
                $precision
412
            )
413
            :
414 13
            self::div(
415 13
                self::floor(self::mul($number, $multiply, self::getDecimalsLengthFromNumber($number))), $multiply,
416 17
                $precision
417
            );
418
    }
419
420
    /**
421
     * @param int|string $number
422
     * @return string
423
     */
424 93 View Code Duplication
    public static function floor($number)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
425
    {
426 93
        $number = self::convertScientificNotationToString($number);
427 93
        if (self::checkIsFloat($number) && self::checkIsFloatCleanZeros($number)) {
428 38
            $result = 0;
429 38
            if (self::isNegative($number)) {
430 7
                --$result;
431
            }
432 38
            $number = self::add($number, $result, 0);
433
        }
434
435 93
        return self::checkNumber($number);
436
    }
437
438
    /**
439
     * @param int|string $number
440
     * @return bool
441
     */
442 68
    private static function checkIsFloatCleanZeros(&$number)
443
    {
444 68
        return false !== strpos($number = rtrim(rtrim($number, '0'), '.'), '.');
445
    }
446
447
    /**
448
     * @param int|string $number
449
     * @param int $precision
450
     * @return string
451
     */
452 17 View Code Duplication
    public static function roundUp($number, $precision = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
453
    {
454 17
        $number = self::convertScientificNotationToString($number);
455 17
        $multiply = self::pow(10, (string)abs($precision));
456
457 17
        return $precision < 0
458
            ?
459 4
            self::mul(
460 4
                self::ceil(self::div($number, $multiply, self::getDecimalsLengthFromNumber($number))), $multiply,
461 4
                $precision
462
            )
463
            :
464 13
            self::div(
465 13
                self::ceil(self::mul($number, $multiply, self::getDecimalsLengthFromNumber($number))), $multiply,
466 17
                $precision
467
            );
468
    }
469
470
    /**
471
     * @param int|string $number
472
     * @return string
473
     */
474 41 View Code Duplication
    public static function ceil($number)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
475
    {
476 41
        $number = self::convertScientificNotationToString($number);
477 41
        if (self::checkIsFloat($number) && self::checkIsFloatCleanZeros($number)) {
478 22
            $result = 1;
479 22
            if (self::isNegative($number)) {
480 5
                --$result;
481
            }
482 22
            $number = self::add($number, $result, 0);
483
        }
484
485 41
        return self::checkNumber($number);
486
    }
487
488
    /**
489
     * @param string $leftOperand
490
     * @param string $rightOperand
491
     * @param string $modulus
492
     * @param null|int $scale
493
     * @return string
494
     */
495 10
    public static function powMod($leftOperand, $rightOperand, $modulus, $scale = null)
496
    {
497 10
        $leftOperand = self::convertScientificNotationToString($leftOperand);
498 10
        $rightOperand = self::convertScientificNotationToString($rightOperand);
499
500
        // bcpowmod in 5.6 have don't calculate correct results if scale is empty
501 10
        if (null === $scale) {
502 4
            return self::mod(self::pow($leftOperand, $rightOperand), $modulus);
503
        }
504
505
        // cant use bcpowmod here as it don't support floats
506 6
        if (self::checkIsFloat($leftOperand) || self::checkIsFloat($rightOperand) || self::checkIsFloat($modulus)) {
507 2
            return self::mod(self::pow($leftOperand, $rightOperand, $scale), $modulus, $scale);
508
        }
509
510 4
        return bcpowmod($leftOperand, $rightOperand, $modulus, $scale);
511
    }
512
513
    /**
514
     * @param string $leftOperand
515
     * @param string $modulus
516
     * @param null $scale
517
     * @return string
518
     */
519 51
    public static function mod($leftOperand, $modulus, $scale = null)
520
    {
521 51
        $leftOperand = self::convertScientificNotationToString($leftOperand);
522
523
        // bcmod in 7.2 is not working properly - for example bcmod(9.9999E-10, -0.00056, 9) should return '-0.000559999' but returns 0.0000000
524
525
        // bcmod in php 5.6< don't support scale and floats
526
        // let use this $x - floor($x/$y) * $y;
527 51
        if (null === $scale) {
528 39
            return self::sub($leftOperand, self::mul(self::floor(self::div($leftOperand, $modulus)), $modulus));
529
        }
530
531 12
        return self::sub(
532 12
            $leftOperand, self::mul(self::floor(self::div($leftOperand, $modulus, $scale)), $modulus, $scale), $scale
533
        );
534
    }
535
536
    /**
537
     * @param string $arg
538
     * @return string
539
     * @throws \InvalidArgumentException
540
     */
541 8
    public static function fact($arg)
542
    {
543 8
        $arg = self::convertScientificNotationToString($arg);
544
545 8
        if (self::checkIsFloat($arg)) {
546 1
            throw new \InvalidArgumentException('Number has to be an integer');
547
        }
548 7
        if (self::isNegative($arg)) {
549 1
            throw new \InvalidArgumentException('Number has to be greater than or equal to 0');
550
        }
551
552 6
        $return = '1';
553 6
        for ($i = 2; $i <= $arg; ++$i) {
554 5
            $return = self::mul($return, $i);
555
        }
556
557 6
        return $return;
558
    }
559
560
    /**
561
     * @param string $hex
562
     * @return string
563
     */
564 5
    public static function hexdec($hex)
565
    {
566 5
        $remainingDigits = substr($hex, 0, -1);
567 5
        $lastDigitToDecimal = \hexdec(substr($hex, -1));
568
569 5
        if ('' === $remainingDigits) {
570 5
            return $lastDigitToDecimal;
571
        }
572
573 5
        return self::add(self::mul(16, self::hexdec($remainingDigits)), $lastDigitToDecimal, 0);
574
    }
575
576
    /**
577
     * @param int $decimal
578
     * @return string
579
     */
580 6
    public static function dechex($decimal)
581
    {
582 6
        $quotient = self::div($decimal, 16, 0);
583 6
        $remainderToHex = \dechex(self::mod($decimal, 16));
584
585 6
        if (self::comp($quotient, 0) === 0) {
586 6
            return $remainderToHex;
587
        }
588
589 6
        return self::dechex($quotient) . $remainderToHex;
590
    }
591
592
    /**
593
     * @param string $leftOperand
594
     * @param string $rightOperand
595
     * @return string
596
     */
597 12
    public static function bitAnd($leftOperand, $rightOperand)
598
    {
599 12
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_AND);
600
    }
601
602
    /**
603
     * @param string $leftOperand
604
     * @param string $rightOperand
605
     * @param string $operator
606
     * @return string
607
     */
608 36
    private static function bitOperatorHelper($leftOperand, $rightOperand, $operator)
609
    {
610 36
        $leftOperand = self::convertScientificNotationToString($leftOperand);
611 36
        $rightOperand = self::convertScientificNotationToString($rightOperand);
612
613 36
        if (self::checkIsFloat($leftOperand)) {
614 3
            throw new \InvalidArgumentException('Left operator has to be an integer');
615
        }
616 33
        if (self::checkIsFloat($rightOperand)) {
617 3
            throw new \InvalidArgumentException('Right operator has to be an integer');
618
        }
619
620 30
        $leftOperandNegative = self::isNegative($leftOperand);
621 30
        $rightOperandNegative = self::isNegative($rightOperand);
622
623 30
        $leftOperand = self::dec2bin(self::abs($leftOperand));
624 30
        $rightOperand = self::dec2bin(self::abs($rightOperand));
625
626 30
        $maxLength = max(strlen($leftOperand), strlen($rightOperand));
627
628 30
        $leftOperand = self::alignBinLength($leftOperand, $maxLength);
629 30
        $rightOperand = self::alignBinLength($rightOperand, $maxLength);
630
631 30
        if ($leftOperandNegative) {
632 7
            $leftOperand = self::recalculateNegative($leftOperand);
633
        }
634 30
        if ($rightOperandNegative) {
635 7
            $rightOperand = self::recalculateNegative($rightOperand);
636
        }
637
638 30
        if (self::BIT_OPERATOR_AND === $operator) {
639 10
            $result = $leftOperand & $rightOperand;
640 10
            $isNegative = ($leftOperandNegative and $rightOperandNegative);
641 20
        } elseif (self::BIT_OPERATOR_OR === $operator) {
642 12
            $result = $leftOperand | $rightOperand;
643 12
            $isNegative = ($leftOperandNegative or $rightOperandNegative);
644 8
        } elseif (self::BIT_OPERATOR_XOR === $operator) {
645 8
            $result = $leftOperand ^ $rightOperand;
646 8
            $isNegative = ($leftOperandNegative xor $rightOperandNegative);
647
        } else {
648
            throw new \InvalidArgumentException('Unknown operator');
649
        }
650
651 30
        if ($isNegative) {
652 8
            $result = self::recalculateNegative($result);
653
        }
654
655 30
        $result = self::bin2dec($result);
656
657 30
        return $isNegative ? '-' . $result : $result;
658
    }
659
660
    /**
661
     * @param string $number
662
     * @param int $base
663
     * @return string
664
     */
665
    public static function dec2bin($number, $base = self::MAX_BASE)
666
    {
667 30
        return self::decBaseHelper($base, function ($base) use ($number) {
668 30
            $value = '';
669 30
            if ('0' === $number) {
670 30
                return chr($number);
671
            }
672
673 28
            while (BC::comp($number, '0') !== BC::COMPARE_EQUAL) {
674 28
                $rest = BC::mod($number, $base);
675 28
                $number = BC::div($number, $base);
0 ignored issues
show
Bug introduced by
Consider using a different name than the imported variable $number, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
676 28
                $value = chr((int)$rest) . $value;
677
            }
678
679 28
            return $value;
680 30
        });
681
    }
682
683
    /**
684
     * @param int $base
685
     * @param \Closure $closure
686
     * @return string
687
     */
688 30
    private static function decBaseHelper($base, \Closure $closure)
689
    {
690 30
        if ($base < 2 || $base > self::MAX_BASE) {
691
            throw new \InvalidArgumentException('Invalid Base: ' . $base);
692
        }
693 30
        $orgScale = self::getScale();
694 30
        self::setScale(0);
695
696 30
        $value = $closure($base);
697
698 30
        self::setScale($orgScale);
699
700 30
        return $value;
701
    }
702
703
    /**
704
     * @param null|int $scale
705
     */
706 359
    public static function setScale($scale)
707
    {
708 359
        bcscale($scale);
709 359
    }
710
711
    /**
712
     * @param int|string $number
713
     * @return string
714
     */
715 45
    public static function abs($number)
716
    {
717 45
        $number = self::convertScientificNotationToString($number);
718
719 45
        if (self::isNegative($number)) {
720 19
            $number = (string)substr($number, 1);
721
        }
722
723 45
        return self::checkNumber($number);
724
    }
725
726
    /**
727
     * @param string $string
728
     * @param int $length
729
     * @return string
730
     */
731 30
    private static function alignBinLength($string, $length)
732
    {
733 30
        return str_pad($string, $length, self::dec2bin('0'), STR_PAD_LEFT);
734
    }
735
736
    /**
737
     * @param string $number
738
     * @return string
739
     */
740 11
    private static function recalculateNegative($number)
741
    {
742 11
        $xor = str_repeat(self::dec2bin(self::MAX_BASE - 1), strlen($number));
743 11
        $number ^= $xor;
744 11
        for ($i = strlen($number) - 1; $i >= 0; $i--) {
745 11
            $byte = ord($number[$i]);
746 11
            if (++$byte !== self::MAX_BASE) {
747 11
                $number[$i] = chr($byte);
748 11
                break;
749
            }
750
            $number[$i] = chr(0);
751
        }
752
753 11
        return $number;
754
    }
755
756
    /**
757
     * @param string $value
758
     * @param int $base
759
     * @return string
760
     */
761
    public static function bin2dec($value, $base = self::MAX_BASE)
762
    {
763 30
        return self::decBaseHelper($base, function ($base) use ($value) {
764 30
            $size = strlen($value);
765 30
            $return = '0';
766 30
            for ($i = 0; $i < $size; ++$i) {
767 30
                $element = ord($value[$i]);
768 30
                $power = BC::pow($base, $size - $i - 1);
769 30
                $return = BC::add($return, BC::mul($element, $power));
770
            }
771
772 30
            return $return;
773 30
        });
774
    }
775
776
    /**
777
     * @param string $leftOperand
778
     * @param string $rightOperand
779
     * @return string
780
     */
781 14
    public static function bitOr($leftOperand, $rightOperand)
782
    {
783 14
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_OR);
784
    }
785
786
    /**
787
     * @param string $leftOperand
788
     * @param string $rightOperand
789
     * @return string
790
     */
791 10
    public static function bitXor($leftOperand, $rightOperand)
792
    {
793 10
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_XOR);
794
    }
795
}
796