Passed
Pull Request — master (#28)
by kacper
02:15
created

BC::bin2dec()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 1
nop 2
dl 0
loc 13
ccs 10
cts 10
cp 1
crap 2
rs 9.9666
c 0
b 0
f 0
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
    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
    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
    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((float)$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
    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
    public static function max()
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((string)$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
    public static function min()
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((string)$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
    public static function roundDown($number, $precision = 0)
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
    public static function floor($number)
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
    public static function roundUp($number, $precision = 0)
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
    public static function ceil($number)
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|int $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 string $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((int)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
        $isNegative = false;
639 30
        $result = '';
640 30
        if (self::BIT_OPERATOR_AND === $operator) {
641 10
            $result = $leftOperand & $rightOperand;
642 10
            $isNegative = ($leftOperandNegative and $rightOperandNegative);
643 20
        } elseif (self::BIT_OPERATOR_OR === $operator) {
644 12
            $result = $leftOperand | $rightOperand;
645 12
            $isNegative = ($leftOperandNegative or $rightOperandNegative);
646 8
        } elseif (self::BIT_OPERATOR_XOR === $operator) {
647 8
            $result = $leftOperand ^ $rightOperand;
648 8
            $isNegative = ($leftOperandNegative xor $rightOperandNegative);
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 36
    public static function dec2bin($number, $base = self::MAX_BASE)
666
    {
667 36
        return self::decBaseHelper(
668 36
            $base, function ($base) use ($number) {
669 35
            $value = '';
670 35
            if ('0' === $number) {
671 30
                return chr((int)$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);
677 33
                $value = chr((int)$rest) . $value;
678
            }
679
680 33
            return $value;
681 36
        }
682
        );
683
    }
684
685
    /**
686
     * @param int $base
687
     * @param \Closure $closure
688
     * @return string
689
     */
690 37
    private static function decBaseHelper($base, \Closure $closure)
691
    {
692 37
        if ($base < 2 || $base > self::MAX_BASE) {
693 2
            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 366
    public static function setScale($scale)
709
    {
710 366
        bcscale($scale);
711 366
    }
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
        }
753
754 11
        return $number;
755
    }
756
757
    /**
758
     * @param string $binary
759
     * @param int $base
760
     * @return string
761
     */
762 36
    public static function bin2dec($binary, $base = self::MAX_BASE)
763
    {
764 36
        return self::decBaseHelper(
765 36
            $base, function ($base) use ($binary) {
766 35
            $size = strlen($binary);
767 35
            $return = '0';
768 35
            for ($i = 0; $i < $size; ++$i) {
769 35
                $element = ord($binary[$i]);
770 35
                $power = BC::pow($base, $size - $i - 1);
771 35
                $return = BC::add($return, BC::mul($element, $power));
772
            }
773
774 35
            return $return;
775 36
        }
776
        );
777
    }
778
779
    /**
780
     * @param string $leftOperand
781
     * @param string $rightOperand
782
     * @return string
783
     */
784 14
    public static function bitOr($leftOperand, $rightOperand)
785
    {
786 14
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_OR);
787
    }
788
789
    /**
790
     * @param string $leftOperand
791
     * @param string $rightOperand
792
     * @return string
793
     */
794 10
    public static function bitXor($leftOperand, $rightOperand)
795
    {
796 10
        return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_XOR);
797
    }
798
}
799