Passed
Push — master ( 37e520...3d8e1d )
by kacper
01:39
created

BC::powMod()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 3
cts 4
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 4
crap 2.0625
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
    /**
16
     * @param int $scale
17
     */
18 9
    public static function setScale($scale)
19
    {
20 9
        bcscale($scale);
21 9
    }
22
23
    /**
24
     * @param int|string $number
25
     * @return string
26
     */
27 2 View Code Duplication
    public static function ceil($number)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
28
    {
29 2
        $number = (string)$number;
30
31 2
        if (self::checkIsFloat($number) && self::checkIsFloatCleanZeros($number)) {
32 2
            $result = 1;
33 2
            if (self::isNegative($number)) {
34 2
                --$result;
35
            }
36 2
            $number = self::add($number, $result, 0);
37
        }
38
39 2
        return self::checkNumber($number);
40
    }
41
42
    /**
43
     * @param int|string $number
44
     * @return bool
45
     */
46 6
    private static function checkIsFloat($number)
47
    {
48 6
        return false !== strpos($number, '.');
49
    }
50
51
    /**
52
     * @param int|string $number
53
     * @return bool
54
     */
55 5
    private static function checkIsFloatCleanZeros(&$number)
56
    {
57 5
        return false !== strpos($number = rtrim(rtrim($number, '0'), '.'), '.');
58
    }
59
60
    /**
61
     * @param $number
62
     * @return bool
63
     */
64 6
    private static function isNegative($number)
65
    {
66 6
        return 0 === strncmp('-', $number, 1);
67
    }
68
69
    /**
70
     * @param int|string $number
71
     * @return int|string
72
     */
73 7
    private static function checkNumber($number)
74
    {
75 7
        $number = str_replace('+', '', filter_var($number, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
76 7
        if ('-0' === $number || !is_numeric($number)) {
77 4
            return '0';
78
        }
79 7
        return $number;
80
    }
81
82
    /**
83
     * @param int|string $number
84
     * @param int $precision
85
     * @return string
86
     */
87 1
    public static function round($number, $precision = 0)
88
    {
89 1
        $number = (string)$number;
90
91 1
        if (self::checkIsFloat($number)) {
92 1
            if (self::isNegative($number)) {
93 1
                return self::sub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
94
            }
95
96 1
            return self::add($number, '0.' . str_repeat('0', $precision) . '5', $precision);
97
        }
98
99 1
        return self::checkNumber($number);
100
    }
101
102
    /**
103
     * @param int|string $number
104
     * @return string
105
     */
106 3 View Code Duplication
    public static function floor($number)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
    {
108 3
        $number = (string)$number;
109
110 3
        if (self::checkIsFloat($number) && self::checkIsFloatCleanZeros($number)) {
111 2
            $result = 0;
112 2
            if (self::isNegative($number)) {
113 2
                --$result;
114
            }
115 2
            $number = self::add($number, $result, 0);
116
        }
117
118 3
        return self::checkNumber($number);
119
    }
120
121
    /**
122
     * @param int|string $number
123
     * @return string
124
     */
125 1
    public static function abs($number)
126
    {
127 1
        $number = (string)$number;
128
129 1
        if (self::isNegative($number)) {
130 1
            $number = (string)substr($number, 1);
131
        }
132
133 1
        return self::checkNumber($number);
134
    }
135
136
    /**
137
     * @param int|string $min
138
     * @param int|string $max
139
     * @return string
140
     */
141 1
    public static function rand($min, $max)
142
    {
143 1
        $max = (string)$max;
144 1
        $min = (string)$min;
145
146 1
        $difference = self::add(self::sub($max, $min), 1);
147 1
        $randPercent = self::div(mt_rand(), mt_getrandmax(), 8);
148
149 1
        return self::add($min, self::mul($difference, $randPercent, 8), 0);
150
    }
151
152
    /**
153
     * @param array|int|string,...
154
     * @return null|int|string
155
     */
156 1 View Code Duplication
    public static function max()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
    {
158 1
        $max = null;
159 1
        $args = func_get_args();
160 1
        if (is_array($args[0])) {
161 1
            $args = $args[0];
162
        }
163 1
        foreach ($args as $value) {
164 1
            if (null === $max) {
165 1
                $max = $value;
166
            } else {
167 1
                if (self::comp($max, $value) < 0) {
168 1
                    $max = $value;
169
                }
170
            }
171
        }
172
173 1
        return $max;
174
    }
175
176
    /**
177
     * @param array|int|string,...
178
     * @return null|int|string
179
     */
180 1 View Code Duplication
    public static function min()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
181
    {
182 1
        $min = null;
183 1
        $args = func_get_args();
184 1
        if (is_array($args[0])) {
185 1
            $args = $args[0];
186
        }
187 1
        foreach ($args as $value) {
188 1
            if (null === $min) {
189 1
                $min = $value;
190
            } else {
191 1
                if (self::comp($min, $value) > 0) {
192 1
                    $min = $value;
193
                }
194
            }
195
        }
196
197 1
        return $min;
198
    }
199
200
    /**
201
     * @param int|string $number
202
     * @param int $precision
203
     * @return string
204
     */
205 1 View Code Duplication
    public static function roundDown($number, $precision = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
    {
207 1
        $multiply = self::pow(10, (string)abs($precision));
208 1
        return $precision < 0 ?
209 1
            self::mul(self::floor(self::div($number, $multiply)), $multiply, $precision) :
210 1
            self::div(self::floor(self::mul($number, $multiply)), $multiply, $precision);
211
    }
212
213
    /**
214
     * @param int|string $number
215
     * @param int $precision
216
     * @return string
217
     */
218 1 View Code Duplication
    public static function roundUp($number, $precision = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
    {
220 1
        $multiply = self::pow(10, (string)abs($precision));
221 1
        return $precision < 0 ?
222 1
            self::mul(self::ceil(self::div($number, $multiply)), $multiply, $precision) :
223 1
            self::div(self::ceil(self::mul($number, $multiply)), $multiply, $precision);
224
    }
225
226
    /**
227
     * @return int
228
     */
229 1
    public static function getScale()
230
    {
231 1
        $sqrt = bcsqrt('2');
232 1
        return strlen(substr($sqrt, strpos($sqrt, '.') + 1));
233
    }
234
235
    /**
236
     * @param string $leftOperand
237
     * @param string $rightOperand
238
     * @param int $scale
239
     * @return string
240
     */
241 7
    public static function add($leftOperand, $rightOperand, $scale = null)
242
    {
243 7
        if (null === $scale) {
244 2
            return bcadd($leftOperand, $rightOperand);
245
        }
246 7
        return bcadd($leftOperand, $rightOperand, $scale);
247
    }
248
249
    /**
250
     * @param string $leftOperand
251
     * @param string $rightOperand
252
     * @param int $scale
253
     * @return int
254
     */
255 3
    public static function comp($leftOperand, $rightOperand, $scale = null)
256
    {
257 3
        if (null === $scale) {
258 3
            return bccomp($leftOperand, $rightOperand);
259
        }
260 1
        return bccomp($leftOperand, $rightOperand, $scale);
261
    }
262
263
    /**
264
     * @param string $leftOperand
265
     * @param string $rightOperand
266
     * @param int $scale
267
     * @return string
268
     */
269 5
    public static function div($leftOperand, $rightOperand, $scale = null)
270
    {
271 5
        if (null === $scale) {
272 3
            return bcdiv($leftOperand, $rightOperand);
273
        }
274 5
        return bcdiv($leftOperand, $rightOperand, $scale);
275
    }
276
277
    /**
278
     * @param string $leftOperand
279
     * @param string $modulus
280
     * @return string
281
     */
282 1
    public static function mod($leftOperand, $modulus)
283
    {
284 1
        return bcmod($leftOperand, $modulus);
285
    }
286
287
    /**
288
     * @param string $leftOperand
289
     * @param string $modulus
290
     * @param int $scale
291
     * @return string
292
     */
293 1
    public static function fmod($leftOperand, $modulus, $scale = null)
294
    {
295
        // From PHP 7.2 on, bcmod can handle real numbers
296 1
        if (version_compare(PHP_VERSION, '7.2.0') >= 0) {
297
            return bcmod($leftOperand, $modulus);
298
        }
299
300
        // mod(a, b) = a - b * floor(a/b)
301 1
        return self::sub(
302 1
            $leftOperand,
303 1
            self::mul(
304 1
                $modulus,
305 1
                self::floor(self::div($leftOperand, $modulus, $scale)),
306 1
                $scale
307
            ),
308 1
            $scale
309
        );
310
    }
311
312
    /**
313
     * @param string $leftOperand
314
     * @param string $rightOperand
315
     * @param int $scale
316
     * @return string
317
     */
318 5
    public static function mul($leftOperand, $rightOperand, $scale = null)
319
    {
320 5
        if (null === $scale) {
321 3
            return bcmul($leftOperand, $rightOperand);
322
        }
323 5
        return bcmul($leftOperand, $rightOperand, $scale);
324
    }
325
326
    /**
327
     * @param string $leftOperand
328
     * @param string $rightOperand
329
     * @param int $scale
330
     * @return string
331
     */
332 3
    public static function pow($leftOperand, $rightOperand, $scale = null)
333
    {
334 3
        if (null === $scale) {
335 3
            return bcpow($leftOperand, $rightOperand);
336
        }
337 1
        return bcpow($leftOperand, $rightOperand, $scale);
338
    }
339
340
    /**
341
     * @param string $leftOperand
342
     * @param string $rightOperand
343
     * @param string $modulus
344
     * @param int $scale
345
     * @return string
346
     */
347 1
    public static function powMod($leftOperand, $rightOperand, $modulus, $scale = null)
348
    {
349 1
        if (null === $scale) {
350 1
            return bcpowmod($leftOperand, $rightOperand, $modulus);
351
        }
352
        return bcpowmod($leftOperand, $rightOperand, $modulus, $scale);
353
    }
354
355
    /**
356
     * @param string $operand
357
     * @param int $scale
358
     * @return string
359
     */
360 1
    public static function sqrt($operand, $scale = null)
361
    {
362 1
        if (null === $scale) {
363 1
            return bcsqrt($operand);
364
        }
365 1
        return bcsqrt($operand, $scale);
366
    }
367
368
    /**
369
     * @param string $leftOperand
370
     * @param string $rightOperand
371
     * @param int $scale
372
     * @return string
373
     */
374 4
    public static function sub($leftOperand, $rightOperand, $scale = null)
375
    {
376 4
        if (null === $scale) {
377 2
            return bcsub($leftOperand, $rightOperand);
378
        }
379 3
        return bcsub($leftOperand, $rightOperand, $scale);
380
    }
381
}
382