Passed
Pull Request — master (#140)
by Бабичев
04:55
created

Math::bcfloor()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 4
eloc 7
c 1
b 0
f 1
nc 4
nop 1
dl 0
loc 12
rs 10
1
<?php
2
3
namespace Bavix\Wallet\Simple;
4
5
use Bavix\Wallet\Interfaces\Mathable;
6
7
/**
8
 * Class MathService
9
 * @package Bavix\Wallet\Services
10
 * @codeCoverageIgnore
11
 */
12
class Math implements Mathable
13
{
14
15
    /**
16
     * @var int
17
     */
18
    protected $scale;
19
20
    /**
21
     * @param string|int|float $first
22
     * @param string|int|float $second
23
     * @param null|int $scale
24
     * @return string
25
     */
26
    public function add($first, $second, ?int $scale = null): string
27
    {
28
        if (config('wallet.math.enabled')) {
29
            return bcadd($first, $second, $this->scale($scale));
30
        }
31
32
        return $this->round($first + $second, $this->scale($scale));
33
    }
34
35
    /**
36
     * @param string|int|float $first
37
     * @param string|int|float $second
38
     * @param null|int $scale
39
     * @return string
40
     */
41
    public function sub($first, $second, ?int $scale = null): string
42
    {
43
        if (config('wallet.math.enabled')) {
44
            return bcsub($first, $second, $this->scale($scale));
45
        }
46
47
        return $this->round($first - $second, $this->scale($scale));
48
    }
49
50
    /**
51
     * @param string|int|float $first
52
     * @param string|int|float $second
53
     * @param null|int $scale
54
     * @return float|int|string|null
55
     */
56
    public function div($first, $second, ?int $scale = null): string
57
    {
58
        if (config('wallet.math.enabled')) {
59
            return bcdiv($first, $second, $this->scale($scale));
60
        }
61
62
        return $this->round($first / $second, $this->scale($scale));
63
    }
64
65
    /**
66
     * @param string|int|float $first
67
     * @param string|int|float $second
68
     * @param null|int $scale
69
     * @return float|int|string
70
     */
71
    public function mul($first, $second, ?int $scale = null): string
72
    {
73
        if (config('wallet.math.enabled')) {
74
            return bcmul($first, $second, $this->scale($scale));
75
        }
76
77
        return $this->round($first * $second, $this->scale($scale));
78
    }
79
80
    /**
81
     * @param string|int|float $first
82
     * @param string|int|float $second
83
     * @param null|int $scale
84
     * @return string
85
     */
86
    public function pow($first, $second, ?int $scale = null): string
87
    {
88
        if (config('wallet.math.enabled')) {
89
            return bcpow($first, $second, $this->scale($scale));
90
        }
91
92
        return $this->round($first ** $second, $this->scale($scale));
93
    }
94
95
    /**
96
     * @param string|int|float $number
97
     * @return string
98
     */
99
    public function ceil($number): string
100
    {
101
        if (config('wallet.math.enabled')) {
102
            return $this->bcceil($number);
103
        }
104
105
        return ceil($number);
0 ignored issues
show
Bug introduced by
It seems like $number can also be of type string; however, parameter $value of ceil() does only seem to accept double, 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

105
        return ceil(/** @scrutinizer ignore-type */ $number);
Loading history...
106
    }
107
108
    /**
109
     * @param string|int|float $number
110
     * @return string
111
     */
112
    public function floor($number): string
113
    {
114
        if (config('wallet.math.enabled')) {
115
            return $this->bcfloor($number);
116
        }
117
118
        return floor($number);
0 ignored issues
show
Bug introduced by
It seems like $number can also be of type string; however, parameter $value of floor() does only seem to accept double, 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

118
        return floor(/** @scrutinizer ignore-type */ $number);
Loading history...
119
    }
120
121
    /**
122
     * @param string|int|float $number
123
     * @param int $precision
124
     * @return string
125
     */
126
    public function round($number, int $precision = 0): string
127
    {
128
        if (config('wallet.math.enabled')) {
129
            return $this->bcround($number, $precision);
130
        }
131
132
        return round($number, $precision);
0 ignored issues
show
Bug introduced by
It seems like $number can also be of type string; however, parameter $val of round() does only seem to accept double, 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

132
        return round(/** @scrutinizer ignore-type */ $number, $precision);
Loading history...
133
    }
134
135
    /**
136
     * @param $first
137
     * @param $second
138
     * @return int
139
     */
140
    public function compare($first, $second): int
141
    {
142
        if (config('wallet.math.enabled')) {
143
            return bccomp($first, $second, $this->scale());
144
        }
145
146
        return $first <=> $second;
147
    }
148
149
    /**
150
     * @param string|int|float $number
151
     * @return string|void
152
     */
153
    protected function bcceil($number)
154
    {
155
        if (strpos($number, '.') !== false) {
156
            if (preg_match("~\.[0]+$~", $number)) {
157
                return $this->bcround($number, 0);
158
            }
159
            if ($number[0] !== '-') {
160
                return bcadd($number, 1, 0);
161
            }
162
            return bcsub($number, 0, 0);
163
        }
164
        return $number;
165
    }
166
167
    /**
168
     * @param string|int|float $number
169
     * @return string
170
     */
171
    protected function bcfloor($number)
172
    {
173
        if (strpos($number, '.') !== false) {
174
            if (preg_match("~\.[0]+$~", $number)) {
175
                return $this->bcround($number, 0);
176
            }
177
            if ($number[0] !== '-') {
178
                return bcadd($number, 0, 0);
179
            }
180
            return bcsub($number, 1, 0);
181
        }
182
        return $number;
183
    }
184
185
    /**
186
     * @param string|int|float $number
187
     * @param int $precision
188
     * @return string
189
     */
190
    protected function bcround($number, $precision)
191
    {
192
        if (strpos($number, '.') !== false) {
193
            if ($number[0] !== '-') {
194
                return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
195
            }
196
            return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
197
        }
198
        return $number;
199
    }
200
201
    /**
202
     * @param int $scale
203
     * @return int
204
     */
205
    protected function scale(?int $scale = null): int
206
    {
207
        if ($scale !== null) {
208
            return $scale;
209
        }
210
211
        if ($this->scale === null) {
212
            $this->scale = (int)config('wallet.math.scale', 64);
213
        }
214
215
        return $this->scale;
216
    }
217
218
}
219