Passed
Pull Request — master (#28)
by kacper
01:38
created

BC::bitAnd()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
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 364
    public static function convertScientificNotationToString($number)
47
    {
48
        // check if number is in scientific notation, first use stripos as is faster then preg_match
49 364
        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 364
        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 146
    public static function pow($leftOperand, $rightOperand, $scale = null)
88
    {
89 146
        $leftOperand = self::convertScientificNotationToString($leftOperand);
90 146
        $rightOperand = self::convertScientificNotationToString($rightOperand);
91
92 146
        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 146
        if (null === $scale) {
101 74
            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 262
    private static function checkIsFloat($number)
112
    {
113 262
        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 40
    public static function getScale()
148
    {
149 40
        $sqrt = self::sqrt('2');
150
151 40
        return strlen(substr($sqrt, strpos($sqrt, '.') + 1));
152
    }
153
154
    /**
155
     * @param string $operand
156
     * @param null|int $scale
157
     * @return string
158
     */
159 45
    public static function sqrt($operand, $scale = null)
160
    {
161 45
        $operand = self::convertScientificNotationToString($operand);
162
163 45
        if (null === $scale) {
164 41
            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 364
    private static function checkNumber($number)
175
    {
176 364
        $number = str_replace('+', '', filter_var($number, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
177 364
        if ('-0' === $number || !is_numeric($number)) {
178 28
            return '0';
179
        }
180
181 361
        return $number;
182
    }
183
184
    /**
185
     * @param string $leftOperand
186
     * @param string $rightOperand
187
     * @param null|int $scale
188
     * @return string
189
     */
190 166 View Code Duplication
    public static function mul($leftOperand, $rightOperand, $scale = null)
191
    {
192 166
        $leftOperand = self::convertScientificNotationToString($leftOperand);
193 166
        $rightOperand = self::convertScientificNotationToString($rightOperand);
194
195 166
        if (null === $scale) {
196 60
            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 160 View Code Duplication
    public static function add($leftOperand, $rightOperand, $scale = null)
224
    {
225 160
        $leftOperand = self::convertScientificNotationToString($leftOperand);
226 160
        $rightOperand = self::convertScientificNotationToString($rightOperand);
227
228 160
        if (null === $scale) {
229 41
            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 130 View Code Duplication
    public static function div($leftOperand, $rightOperand, $scale = null)
242
    {
243 130
        $leftOperand = self::convertScientificNotationToString($leftOperand);
244 130
        $rightOperand = self::convertScientificNotationToString($rightOperand);
245
246 130
        if (null === $scale) {
247 45
            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 64
    public static function comp($leftOperand, $rightOperand, $scale = null)
293
    {
294 64
        $leftOperand = self::convertScientificNotationToString($leftOperand);
295 64
        $rightOperand = self::convertScientificNotationToString($rightOperand);
296
297 64
        if (null === $scale) {
298 53
            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 78 View Code Duplication
    public static function sub($leftOperand, $rightOperand, $scale = null)
315
    {
316 78
        $leftOperand = self::convertScientificNotationToString($leftOperand);
317 78
        $rightOperand = self::convertScientificNotationToString($rightOperand);
318
319 78
        if (null === $scale) {
320 47
            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 98 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 98
        $number = self::convertScientificNotationToString($number);
427 98
        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 98
        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 56
    public static function mod($leftOperand, $modulus, $scale = null)
520
    {
521 56
        $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 56
        if (null === $scale) {
528 44
            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 35
    public static function dec2bin($number, $base = self::MAX_BASE)
666
    {
667 35
        return self::decBaseHelper(
668 35
            $base, function ($base) use ($number) {
669 35
            $value = '';
670 35
            if ('0' === $number) {
671 30
                return chr($number);
672
            }
673
674 33
            while (BC::comp($number, '0') !== BC::COMPARE_EQUAL) {
675 33
                $rest = BC::mod($number, $base);
676 33
                $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...
677 33
                $value = chr((int)$rest) . $value;
678
            }
679
680 33
            return $value;
681 35
        }
682
        );
683
    }
684
685
    /**
686
     * @param int $base
687
     * @param \Closure $closure
688
     * @return string
689
     */
690 35
    private static function decBaseHelper($base, \Closure $closure)
691
    {
692 35
        if ($base < 2 || $base > self::MAX_BASE) {
693
            throw new \InvalidArgumentException('Invalid Base: ' . $base);
694
        }
695 35
        $orgScale = self::getScale();
696 35
        self::setScale(0);
697
698 35
        $value = $closure($base);
699
700 35
        self::setScale($orgScale);
701
702 35
        return $value;
703
    }
704
705
    /**
706
     * @param null|int $scale
707
     */
708 364
    public static function setScale($scale)
709
    {
710 364
        bcscale($scale);
711 364
    }
712
713
    /**
714
     * @param int|string $number
715
     * @return string
716
     */
717 45
    public static function abs($number)
718
    {
719 45
        $number = self::convertScientificNotationToString($number);
720
721 45
        if (self::isNegative($number)) {
722 19
            $number = (string)substr($number, 1);
723
        }
724
725 45
        return self::checkNumber($number);
726
    }
727
728
    /**
729
     * @param string $string
730
     * @param int $length
731
     * @return string
732
     */
733 30
    private static function alignBinLength($string, $length)
734
    {
735 30
        return str_pad($string, $length, self::dec2bin('0'), STR_PAD_LEFT);
736
    }
737
738
    /**
739
     * @param string $number
740
     * @return string
741
     */
742 11
    private static function recalculateNegative($number)
743
    {
744 11
        $xor = str_repeat(self::dec2bin(self::MAX_BASE - 1), strlen($number));
745 11
        $number ^= $xor;
746 11
        for ($i = strlen($number) - 1; $i >= 0; $i--) {
747 11
            $byte = ord($number[$i]);
748 11
            if (++$byte !== self::MAX_BASE) {
749 11
                $number[$i] = chr($byte);
750 11
                break;
751
            }
752
            $number[$i] = chr(0);
753
        }
754
755 11
        return $number;
756
    }
757
758
    /**
759
     * @param string $binary
760
     * @param int $base
761
     * @return string
762
     */
763 35
    public static function bin2dec($binary, $base = self::MAX_BASE)
764
    {
765 35
        return self::decBaseHelper(
766 35
            $base, function ($base) use ($binary) {
767 35
            $size = strlen($binary);
768 35
            $return = '0';
769 35
            for ($i = 0; $i < $size; ++$i) {
770 35
                $element = ord($binary[$i]);
771 35
                $power = BC::pow($base, $size - $i - 1);
772 35
                $return = BC::add($return, BC::mul($element, $power));
773
            }
774
775 35
            return $return;
776 35
        }
777
        );
778
    }
779
780
    /**
781
     * @param string $leftOperand
782
     * @param string $rightOperand
783
     * @return string
784
     */
785 14
    public static function bitOr($leftOperand, $rightOperand)
786
    {
787 14
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_OR);
788
    }
789
790
    /**
791
     * @param string $leftOperand
792
     * @param string $rightOperand
793
     * @return string
794
     */
795 10
    public static function bitXor($leftOperand, $rightOperand)
796
    {
797 10
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_XOR);
798
    }
799
}
800