Math::isEven()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BitWasp\Bitcoin\Math;
6
7
use Mdanter\Ecc\Math\GmpMath;
8
use Mdanter\Ecc\Util\NumberSize;
9
10
class Math extends GmpMath
11
{
12
13
    /**
14
     * @param \GMP $integer
15
     * @return bool
16
     */
17 54
    public function isEven(\GMP $integer): bool
18
    {
19 54
        return $this->cmp($this->mod($integer, gmp_init(2)), gmp_init(0)) === 0;
0 ignored issues
show
Bug introduced by
It seems like gmp_init(2) can also be of type resource; however, parameter $modulus of Mdanter\Ecc\Math\GmpMath::mod() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

19
        return $this->cmp($this->mod($integer, /** @scrutinizer ignore-type */ gmp_init(2)), gmp_init(0)) === 0;
Loading history...
Bug introduced by
It seems like gmp_init(0) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

19
        return $this->cmp($this->mod($integer, gmp_init(2)), /** @scrutinizer ignore-type */ gmp_init(0)) === 0;
Loading history...
20
    }
21
22
    /**
23
     * @param \GMP $int
24
     * @param \GMP $otherInt
25
     * @return \GMP
26
     */
27 1695
    public function bitwiseOr(\GMP $int, \GMP $otherInt): \GMP
28
    {
29 1695
        return gmp_or($int, $otherInt);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_or($int, $otherInt) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
30
    }
31
32
    /**
33
     * Similar to gmp_div_qr, return a tuple containing the
34
     * result and the remainder
35
     *
36
     * @param \GMP $dividend
37
     * @param \GMP $divisor
38
     * @return array
39
     */
40
    public function divQr(\GMP $dividend, \GMP $divisor): array
41
    {
42
        // $div = n / q
43
        $div = $this->div($dividend, $divisor);
44
        // $remainder = n - (n / q) * q
45
        $remainder = $this->sub($dividend, $this->mul($div, $divisor));
46
        return [$div, $remainder];
47
    }
48
49
    /**
50
     * @param int $compact
51
     * @param bool|false $isNegative
52
     * @param bool|false $isOverflow
53
     * @return \GMP
54
     */
55 210
    public function decodeCompact($compact, &$isNegative, &$isOverflow): \GMP
56
    {
57 210
        if ($compact < 0 || $compact > pow(2, 32) - 1) {
58
            throw new \RuntimeException('Compact integer must be 32bit');
59
        }
60
61 210
        $compact = gmp_init($compact, 10);
62 210
        $size = $this->rightShift($compact, 24);
0 ignored issues
show
Bug introduced by
It seems like $compact can also be of type resource; however, parameter $number of Mdanter\Ecc\Math\GmpMath::rightShift() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
        $size = $this->rightShift(/** @scrutinizer ignore-type */ $compact, 24);
Loading history...
63 210
        $word = $this->bitwiseAnd($compact, gmp_init(0x007fffff, 10));
0 ignored issues
show
Bug introduced by
It seems like $compact can also be of type resource; however, parameter $first of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $word = $this->bitwiseAnd(/** @scrutinizer ignore-type */ $compact, gmp_init(0x007fffff, 10));
Loading history...
Bug introduced by
It seems like gmp_init(8388607, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
        $word = $this->bitwiseAnd($compact, /** @scrutinizer ignore-type */ gmp_init(0x007fffff, 10));
Loading history...
64 210
        if ($this->cmp($size, gmp_init(3)) <= 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(3) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

64
        if ($this->cmp($size, /** @scrutinizer ignore-type */ gmp_init(3)) <= 0) {
Loading history...
65 13
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub(gmp_init(3, 10), $size)));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(8, 10) can also be of type resource; however, parameter $multiplier of Mdanter\Ecc\Math\GmpMath::mul() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            $positions = (int) $this->toString($this->mul(/** @scrutinizer ignore-type */ gmp_init(8, 10), $this->sub(gmp_init(3, 10), $size)));
Loading history...
Bug introduced by
It seems like gmp_init(3, 10) can also be of type resource; however, parameter $minuend of Mdanter\Ecc\Math\GmpMath::sub() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub(/** @scrutinizer ignore-type */ gmp_init(3, 10), $size)));
Loading history...
66 13
            $word = $this->rightShift($word, $positions);
67
        } else {
68 197
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub($size, gmp_init(3, 10))));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(3, 10) can also be of type resource; however, parameter $subtrahend of Mdanter\Ecc\Math\GmpMath::sub() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
            $positions = (int) $this->toString($this->mul(gmp_init(8, 10), $this->sub($size, /** @scrutinizer ignore-type */ gmp_init(3, 10))));
Loading history...
69 197
            $word = $this->leftShift($word, $positions);
70
        }
71
72
        // isNegative: $word !== 0 && $uint32 & 0x00800000 !== 0
73
        // isOverflow: $word !== 0 && (($size > 34) || ($word > 0xff && $size > 33) || ($word > 0xffff && $size > 32))
74 210
        $zero = gmp_init(0);
75 210
        $isNegative = ($this->cmp($word, $zero) !== 0) && ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000)), $zero) === 1);
76 210
        $isOverflow = $this->cmp($word, $zero) !== 0 && (
77 199
                ($this->cmp($size, gmp_init(34, 10)) > 0)
78 198
                || ($this->cmp($word, gmp_init(0xff, 10)) > 0 && $this->cmp($size, gmp_init(33, 10)) > 0)
79 210
                || ($this->cmp($word, gmp_init(0xffff, 10)) > 0 && $this->cmp($size, gmp_init(32, 10)) > 0)
80
            );
81
82 210
        return $word;
83
    }
84
85
    /**
86
     * @param \GMP $integer
87
     * @return \GMP
88
     */
89 18
    public function getLow64(\GMP $integer): \GMP
90
    {
91 18
        $bits = gmp_strval($integer, 2);
92 18
        $bits = substr($bits, 0, 64);
93 18
        $bits = str_pad($bits, 64, '0', STR_PAD_LEFT);
94 18
        return gmp_init($bits, 2);
0 ignored issues
show
Bug Best Practice introduced by
The expression return gmp_init($bits, 2) could return the type resource which is incompatible with the type-hinted return GMP. Consider adding an additional type-check to rule them out.
Loading history...
95
    }
96
97
    /**
98
     * @param \GMP $int
99
     * @param int $byteSize
100
     * @return string
101
     */
102
    public function fixedSizeInt(\GMP $int, int $byteSize): string
103
    {
104
        $two = gmp_init(2);
105
        $maskShift = gmp_pow($two, 8);
106
        $mask = gmp_mul(gmp_init(255), gmp_pow($two, 256));
107
108
        $x = '';
109
        for ($i = $byteSize - 1; $i >= 0; $i--) {
110
            $mask = gmp_div($mask, $maskShift);
111
            $x .= pack('C', gmp_strval(gmp_div(gmp_and($int, $mask), gmp_pow($two, $i * 8)), 10));
112
        }
113
114
        return $x;
115
    }
116
117
    /**
118
     * @param \GMP $integer
119
     * @param bool $fNegative
120
     * @return \GMP
121
     */
122 18
    public function encodeCompact(\GMP $integer, bool $fNegative): \GMP
123
    {
124 18
        if (!is_bool($fNegative)) {
0 ignored issues
show
introduced by
The condition is_bool($fNegative) is always true.
Loading history...
125
            throw new \InvalidArgumentException('CompactInteger::read() - flag must be boolean!');
126
        }
127
128 18
        $size = (int) NumberSize::bnNumBytes($this, $integer);
129 18
        if ($size <= 3) {
130 14
            $compact = $this->leftShift($this->getLow64($integer), (8 * (3 - $size)));
131
        } else {
132 4
            $compact = $this->rightShift($integer, 8 * ($size - 3));
133 4
            $compact = $this->getLow64($compact);
134
        }
135
136 18
        if ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000, 10)), gmp_init(0, 10)) > 0) {
0 ignored issues
show
Bug introduced by
It seems like gmp_init(0, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::cmp() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        if ($this->cmp($this->bitwiseAnd($compact, gmp_init(0x00800000, 10)), /** @scrutinizer ignore-type */ gmp_init(0, 10)) > 0) {
Loading history...
Bug introduced by
It seems like gmp_init(8388608, 10) can also be of type resource; however, parameter $other of Mdanter\Ecc\Math\GmpMath::bitwiseAnd() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
        if ($this->cmp($this->bitwiseAnd($compact, /** @scrutinizer ignore-type */ gmp_init(0x00800000, 10)), gmp_init(0, 10)) > 0) {
Loading history...
137 1
            $compact = $this->rightShift($compact, 8);
138 1
            $size = $size + 1;
139
        }
140
141 18
        $compact = $this->bitwiseOr($compact, $this->leftShift(gmp_init($size, 10), 24));
0 ignored issues
show
Bug introduced by
It seems like gmp_init($size, 10) can also be of type resource; however, parameter $number of Mdanter\Ecc\Math\GmpMath::leftShift() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

141
        $compact = $this->bitwiseOr($compact, $this->leftShift(/** @scrutinizer ignore-type */ gmp_init($size, 10), 24));
Loading history...
142 18
        if ($fNegative && $this->cmp($this->bitwiseAnd($compact, gmp_init(0x007fffff, 10)), gmp_init(0, 10)) > 0) { /// ?
143 2
            $compact = $this->bitwiseOr($compact, gmp_init(0x00800000, 10));
0 ignored issues
show
Bug introduced by
It seems like gmp_init(8388608, 10) can also be of type resource; however, parameter $otherInt of BitWasp\Bitcoin\Math\Math::bitwiseOr() does only seem to accept GMP, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

143
            $compact = $this->bitwiseOr($compact, /** @scrutinizer ignore-type */ gmp_init(0x00800000, 10));
Loading history...
144
        }
145
146 18
        return $compact;
147
    }
148
}
149