Passed
Pull Request — master (#139)
by Jordan
06:15
created

ArithmeticProvider::pow()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 3
dl 0
loc 18
ccs 13
cts 13
cp 1
crap 2
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
namespace Samsara\Fermat\Provider;
4
5
use Decimal\Decimal;
6
use Samsara\Exceptions\UsageError\IntegrityConstraint;
7
8
/**
9
 *
10
 */
11
class ArithmeticProvider
12
{
13
14
    /**
15
     * @param string $number1
16
     * @param string $number2
17
     * @param $scale
18
     * @return string
19
     */
20 586
    public static function add(string $number1, string $number2, $scale = 100)
21
    {
22 586
        if (extension_loaded('decimal')) {
23 34
            $intDigits1 = self::integerDigits($number1);
24 34
            $intDigits2 = self::integerDigits($number2);
25 34
            $decimalScale = max($intDigits1, $intDigits2);
26 34
            $decimalScale = $decimalScale+$scale+1;
27 34
            $decimalScale = max($decimalScale, strlen($number1)+1, strlen($number2)+1);
28 34
            $number1 = new Decimal($number1, $decimalScale);
29 34
            $number2 = new Decimal($number2, $decimalScale);
30
31 34
            $result = $number1->add($number2);
32
33 34
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
34
        } else {
35 552
            $result = \bcadd($number1, $number2, $scale);
36
        }
37 586
        return $result;
38
    }
39
40
    /**
41
     * @param string $left
42
     * @param string $right
43
     * @param $scale
44
     * @return string
45
     */
46 707
    public static function subtract(string $left, string $right, $scale = 100)
47
    {
48 707
        if (extension_loaded('decimal')) {
49 34
            $intDigits1 = self::integerDigits($left);
50 34
            $intDigits2 = self::integerDigits($right);
51 34
            $decimalScale = max($intDigits1, $intDigits2);
52 34
            $decimalScale = $decimalScale+$scale+1;
53 34
            $decimalScale = max($decimalScale, strlen($left)+1, strlen($right)+1);
54 34
            $number1 = new Decimal($left, $decimalScale);
55 34
            $number2 = new Decimal($right, $decimalScale);
56
57 34
            $result = $number1->sub($number2);
58
59 34
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
60
        } else {
61 673
            $result = \bcsub($left, $right, $scale);
62
        }
63 707
        return $result;
64
    }
65
66
    /**
67
     * @param string $number1
68
     * @param string $number2
69
     * @param $scale
70
     * @return string
71
     */
72 802
    public static function multiply(string $number1, string $number2, $scale = 100)
73
    {
74 802
        if (extension_loaded('decimal')) {
75 63
            $intDigits1 = self::integerDigits($number1);
76 63
            $intDigits2 = self::integerDigits($number2);
77 63
            $decimalScale = max($intDigits1, $intDigits2);
78 63
            $decimalScale = $decimalScale+$scale+1;
79 63
            $decimalScale = max($decimalScale, strlen($number1)+1, strlen($number2)+1);
80 63
            $number1 = new Decimal($number1, $decimalScale);
81 63
            $number2 = new Decimal($number2, $decimalScale);
82
83 63
            $result = $number1->mul($number2);
84
85 63
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
86
        } else {
87 739
            $result = \bcmul($number1, $number2, $scale);
88
        }
89 802
        return $result;
90
    }
91
92
    /**
93
     * @param string $numerator
94
     * @param string $denominator
95
     * @param $scale
96
     * @return string
97
     */
98 931
    public static function divide(string $numerator, string $denominator, $scale = 100)
99
    {
100 931
        if (extension_loaded('decimal')) {
101 72
            $intDigits1 = self::integerDigits($numerator);
102 72
            $intDigits2 = self::integerDigits($denominator);
103 72
            $decimalScale = max($intDigits1, $intDigits2);
104 72
            $decimalScale = $decimalScale+$scale+1;
105 72
            $decimalScale = max($decimalScale, strlen($numerator)+1, strlen($denominator)+1);
106 72
            $number1 = new Decimal($numerator, $decimalScale);
107 72
            $number2 = new Decimal($denominator, $decimalScale);
108
109 72
            $result = $number1->div($number2);
110
111 72
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
112
        } else {
113 859
            $result = \bcdiv($numerator, $denominator, $scale);
114
        }
115 931
        return $result;
116
    }
117
118
    /**
119
     * @param string $base
120
     * @param string $exponent
121
     * @param $scale
122
     * @return string
123
     */
124 508
    public static function pow(string $base, string $exponent, $scale = 100)
125
    {
126 508
        if (extension_loaded('decimal')) {
127 18
            $intDigits1 = self::integerDigits($base);
128 18
            $intDigits2 = self::integerDigits($exponent);
129 18
            $decimalScale = max($intDigits1, $intDigits2);
130 18
            $decimalScale = $decimalScale+$scale+1;
131 18
            $decimalScale = max($decimalScale, strlen($base)+1, strlen($exponent)+1);
132 18
            $number1 = new Decimal($base, $decimalScale);
133 18
            $number2 = new Decimal($exponent, $decimalScale);
134
135 18
            $result = $number1->pow($number2);
136
137 18
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
138
        } else {
139 490
            $result = \bcpow($base, $exponent, $scale);
140
        }
141 508
        return $result;
142
    }
143
144
    /**
145
     * @param string $number
146
     * @param $scale
147
     * @return string
148
     */
149 74
    public static function squareRoot(string $number, $scale = 100)
150
    {
151 74
        if (extension_loaded('decimal')) {
152
            $intDigits1 = self::integerDigits($number);
153
            $decimalScale = $intDigits1+$scale+1;
154
            $decimalScale = max($decimalScale, strlen($number)+1);
155
            $number = new Decimal($number, $decimalScale);
156
157
            $result = $number->sqrt();
158
159
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
160
        } else {
161 74
            $result = \bcsqrt($number, $scale);
162
        }
163 74
        return $result;
164
    }
165
166
    /**
167
     * @param string $number
168
     * @param $modulo
169
     * @return string
170
     */
171
    public static function modulo(string $number, $modulo)
172
    {
173
        if (extension_loaded('decimal')) {
174
            $decimalScale = (max(strlen($modulo)*2, strlen($number)*2));
175
            $number1 = new Decimal($number, $decimalScale);
176
            $number2 = new Decimal($modulo, $decimalScale);
177
178
            $result = $number1->mod($number2);
179
180
            $result = $result->toString();
181
        } else {
182
            $result = \bcmod($number, $modulo);
183
        }
184
        return $result;
185
    }
186
187
    /**
188
     * @param string $left
189
     * @param string $right
190
     * @param $scale
191
     * @return int
192
     */
193 1903
    public static function compare(string $left, string $right, $scale = 100)
194
    {
195 1903
        if (extension_loaded('decimal')) {
196 166
            $intDigits1 = self::integerDigits($left);
197 166
            $intDigits2 = self::integerDigits($right);
198 166
            $decimalScale = max($intDigits1, $intDigits2);
199 166
            $decimalScale = $decimalScale+$scale+1;
200 166
            $decimalScale = max($decimalScale, strlen($left)+1, strlen($right)+1);
201 166
            $number1 = new Decimal($left, $decimalScale);
202 166
            $number2 = new Decimal($right, $decimalScale);
203
204 166
            $result = $number1->compareTo($number2);
205
        } else {
206 1737
            $result = \bccomp($left, $right, $scale);
207
        }
208 1903
        return $result;
209
    }
210
211
    /**
212
     * @param string $left
213
     * @param string $right
214
     * @param string $modulus
215
     * @param $scale
216
     * @return string
217
     */
218
    public static function powmod(string $left, string $right, string $modulus, $scale = 100)
219
    {
220
        if (extension_loaded('decimal')) {
221
            $number1 = new Decimal($left, $scale+2);
222
            $number2 = new Decimal($right, $scale+2);
223
            $number3 = new Decimal($modulus, $scale+2);
224
225
            $result = $number1->pow($number2)->mod($number3);
226
227
            $result = $result->toFixed($scale+2);
228
        } else {
229
            $result = \bcpowmod($left, $right, $modulus, $scale);
230
        }
231
        return $result;
232
    }
233
234 174
    private static function integerDigits(string $number): int
235
    {
236 174
        return strlen($number);
237
    }
238
239
}