Passed
Push — master ( 621c3c...4216b1 )
by Jordan
23:02 queued 16:19
created

ArithmeticProvider::divide()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.3272

Importance

Changes 0
Metric Value
cc 2
eloc 13
nc 2
nop 3
dl 0
loc 18
ccs 4
cts 13
cp 0.3076
crap 3.3272
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 30
    public static function add(string $number1, string $number2, $scale = 100)
21
    {
22 30
        if (extension_loaded('decimal')) {
23
            $intDigits1 = self::integerDigits($number1);
24
            $intDigits2 = self::integerDigits($number2);
25
            $decimalScale = max($intDigits1, $intDigits2);
26
            $decimalScale = $decimalScale+$scale+1;
27
            $decimalScale = max($decimalScale, strlen($number1)+1, strlen($number2)+1);
28
            $number1 = new Decimal($number1, $decimalScale);
29
            $number2 = new Decimal($number2, $decimalScale);
30
31
            $result = $number1->add($number2);
32
33
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
34
        } else {
35 30
            $result = \bcadd($number1, $number2, $scale);
36
        }
37 30
        return $result;
38
    }
39
40
    /**
41
     * @param string $left
42
     * @param string $right
43
     * @param $scale
44
     * @return string
45
     */
46 29
    public static function subtract(string $left, string $right, $scale = 100)
47
    {
48 29
        if (extension_loaded('decimal')) {
49
            $intDigits1 = self::integerDigits($left);
50
            $intDigits2 = self::integerDigits($right);
51
            $decimalScale = max($intDigits1, $intDigits2);
52
            $decimalScale = $decimalScale+$scale+1;
53
            $decimalScale = max($decimalScale, strlen($left)+1, strlen($right)+1);
54
            $number1 = new Decimal($left, $decimalScale);
55
            $number2 = new Decimal($right, $decimalScale);
56
57
            $result = $number1->sub($number2);
58
59
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
60
        } else {
61 29
            $result = \bcsub($left, $right, $scale);
62
        }
63 29
        return $result;
64
    }
65
66
    /**
67
     * @param string $number1
68
     * @param string $number2
69
     * @param $scale
70
     * @return string
71
     */
72 33
    public static function multiply(string $number1, string $number2, $scale = 100)
73
    {
74 33
        if (extension_loaded('decimal')) {
75
            $intDigits1 = self::integerDigits($number1);
76
            $intDigits2 = self::integerDigits($number2);
77
            $decimalScale = max($intDigits1, $intDigits2);
78
            $decimalScale = $decimalScale+$scale+1;
79
            $decimalScale = max($decimalScale, strlen($number1)+1, strlen($number2)+1);
80
            $number1 = new Decimal($number1, $decimalScale);
81
            $number2 = new Decimal($number2, $decimalScale);
82
83
            $result = $number1->mul($number2);
84
85
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
86
        } else {
87 33
            $result = \bcmul($number1, $number2, $scale);
88
        }
89 33
        return $result;
90
    }
91
92
    /**
93
     * @param string $numerator
94
     * @param string $denominator
95
     * @param $scale
96
     * @return string
97
     */
98 43
    public static function divide(string $numerator, string $denominator, $scale = 100)
99
    {
100 43
        if (extension_loaded('decimal')) {
101
            $intDigits1 = self::integerDigits($numerator);
102
            $intDigits2 = self::integerDigits($denominator);
103
            $decimalScale = max($intDigits1, $intDigits2);
104
            $decimalScale = $decimalScale+$scale+1;
105
            $decimalScale = max($decimalScale, strlen($numerator)+1, strlen($denominator)+1);
106
            $number1 = new Decimal($numerator, $decimalScale);
107
            $number2 = new Decimal($denominator, $decimalScale);
108
109
            $result = $number1->div($number2);
110
111
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
112
        } else {
113 43
            $result = \bcdiv($numerator, $denominator, $scale);
114
        }
115 43
        return $result;
116
    }
117
118
    /**
119
     * @param string $base
120
     * @param string $exponent
121
     * @param $scale
122
     * @return string
123
     */
124 27
    public static function pow(string $base, string $exponent, $scale = 100)
125
    {
126 27
        if (extension_loaded('decimal')) {
127
            $intDigits1 = self::integerDigits($base);
128
            $intDigits2 = self::integerDigits($exponent);
129
            $decimalScale = max($intDigits1, $intDigits2);
130
            $decimalScale = $decimalScale+$scale+1;
131
            $decimalScale = max($decimalScale, strlen($base)+1, strlen($exponent)+1);
132
            $number1 = new Decimal($base, $decimalScale);
133
            $number2 = new Decimal($exponent, $decimalScale);
134
135
            $result = $number1->pow($number2);
136
137
            $result = $result->toFixed($scale, false, Decimal::ROUND_TRUNCATE);
138
        } else {
139 27
            $result = \bcpow($base, $exponent, $scale);
140
        }
141 27
        return $result;
142
    }
143
144
    /**
145
     * @param string $number
146
     * @param $scale
147
     * @return string
148
     */
149 12
    public static function squareRoot(string $number, $scale = 100)
150
    {
151 12
        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 12
            $result = \bcsqrt($number, $scale);
162
        }
163 12
        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 108
    public static function compare(string $left, string $right, $scale = 100)
194
    {
195 108
        if (extension_loaded('decimal')) {
196
            $intDigits1 = self::integerDigits($left);
197
            $intDigits2 = self::integerDigits($right);
198
            $decimalScale = max($intDigits1, $intDigits2);
199
            $decimalScale = $decimalScale+$scale+1;
200
            $decimalScale = max($decimalScale, strlen($left)+1, strlen($right)+1);
201
            $number1 = new Decimal($left, $decimalScale);
202
            $number2 = new Decimal($right, $decimalScale);
203
204
            $result = $number1->compareTo($number2);
205
        } else {
206 108
            $result = \bccomp($left, $right, $scale);
207
        }
208 108
        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
    private static function integerDigits(string $number): int
235
    {
236
        if (!str_contains($number, '.')) {
237
            return strlen($number);
238
        }
239
240
        return strpos($number, '.');
241
    }
242
243
}