BinaryMath::compare()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 2
nc 4
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace IPLib\Service;
4
5
/**
6
 * Helper class to work with unsigned binary integers.
7
 *
8
 * @internal
9
 */
10
class BinaryMath
11
{
12
    /**
13
     * Trim the leading zeroes from a non-negative integer represented in binary form.
14
     *
15
     * @param string $value
16
     *
17
     * @return string
18
     */
19 1027
    public function reduce($value)
20
    {
21 1027
        $value = ltrim($value, '0');
22
23 1027
        return $value === '' ? '0' : $value;
24
    }
25
26
    /**
27
     * Compare two non-negative integers represented in binary form.
28
     *
29
     * @param string $a
30
     * @param string $b
31
     *
32
     * @return int 1 if $a is greater than $b, -1 if $b is greater than $b, 0 if they are the same
33
     */
34 16
    public function compare($a, $b)
35
    {
36 16
        list($a, $b) = $this->toSameLength($a, $b);
37
38 16
        return $a < $b ? -1 : ($a > $b ? 1 : 0);
39
    }
40
41
    /**
42
     * Add 1 to a non-negative integer represented in binary form.
43
     *
44
     * @param string $value
45
     *
46
     * @return string
47
     */
48 155
    public function increment($value)
49
    {
50 155
        $lastZeroIndex = strrpos($value, '0');
51 155
        if ($lastZeroIndex === false) {
52 13
            return '1' . str_repeat('0', strlen($value));
53
        }
54
55 143
        return ltrim(substr($value, 0, $lastZeroIndex), '0') . '1' . str_repeat('0', strlen($value) - $lastZeroIndex - 1);
56
    }
57
58
    /**
59
     * Calculate the bitwise AND of two non-negative integers represented in binary form.
60
     *
61
     * @param string $operand1
62
     * @param string $operand2
63
     *
64
     * @return string
65
     */
66 516
    public function andX($operand1, $operand2)
67
    {
68 516
        $operand1 = $this->reduce($operand1);
69 516
        $operand2 = $this->reduce($operand2);
70 516
        $numBits = min(strlen($operand1), strlen($operand2));
71 516
        $operand1 = substr(str_pad($operand1, $numBits, '0', STR_PAD_LEFT), -$numBits);
72 516
        $operand2 = substr(str_pad($operand2, $numBits, '0', STR_PAD_LEFT), -$numBits);
73 516
        $result = '';
74 516
        for ($index = 0; $index < $numBits; $index++) {
75 516
            $result .= $operand1[$index] === '1' && $operand2[$index] === '1' ? '1' : '0';
76
        }
77
78 516
        return $this->reduce($result);
79
    }
80
81
    /**
82
     * Calculate the bitwise OR of two non-negative integers represented in binary form.
83
     *
84
     * @param string $operand1
85
     * @param string $operand2
86
     *
87
     * @return string
88
     */
89 501
    public function orX($operand1, $operand2)
90
    {
91 501
        list($operand1, $operand2, $numBits) = $this->toSameLength($operand1, $operand2);
92 501
        $result = '';
93 501
        for ($index = 0; $index < $numBits; $index++) {
94 501
            $result .= $operand1[$index] === '1' || $operand2[$index] === '1' ? '1' : '0';
95
        }
96
97 501
        return $result;
98
    }
99
100
    /**
101
     * Zero-padding of two non-negative integers represented in binary form, so that they have the same length.
102
     *
103
     * @param string $num1
104
     * @param string $num2
105
     *
106
     * @return string[],int[] The first array element is $num1 (padded), the first array element is $num2 (padded), the third array element is the number of bits
107
     */
108 517
    private function toSameLength($num1, $num2)
109
    {
110 517
        $num1 = $this->reduce($num1);
111 517
        $num2 = $this->reduce($num2);
112 517
        $numBits = max(strlen($num1), strlen($num2));
113
114
        return array(
115 517
            str_pad($num1, $numBits, '0', STR_PAD_LEFT),
116 517
            str_pad($num2, $numBits, '0', STR_PAD_LEFT),
117 517
            $numBits,
118
        );
119
    }
120
}
121