1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the Cubiche package. |
5
|
|
|
* |
6
|
|
|
* Copyright (c) Cubiche |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Cubiche\Domain\System; |
13
|
|
|
|
14
|
|
|
use Cubiche\Domain\System\Exception\NotImplementedException; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Decimal Infinite Class. |
18
|
|
|
* |
19
|
|
|
* @author Karel Osorio Ramírez <[email protected]> |
20
|
|
|
*/ |
21
|
|
|
class DecimalInfinite extends Decimal |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* @var DecimalInfinite |
25
|
|
|
*/ |
26
|
|
|
protected static $infPositive = null; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @var DecimalInfinite |
30
|
|
|
*/ |
31
|
|
|
protected static $infNegative = null; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @param float $value |
35
|
|
|
* |
36
|
|
|
* @return \Cubiche\Domain\System\DecimalInfinite |
37
|
|
|
*/ |
38
|
|
|
public static function fromNative($value) |
39
|
|
|
{ |
40
|
|
|
if ($value === INF) { |
41
|
|
|
return self::infPositive(); |
42
|
|
|
} elseif ($value === -INF) { |
43
|
|
|
return self::infNegative(); |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
return new self($value); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* @return \Cubiche\Domain\System\DecimalInfinite |
51
|
|
|
*/ |
52
|
|
|
public static function infPositive() |
53
|
|
|
{ |
54
|
|
|
if (self::$infPositive === null) { |
55
|
|
|
self::$infPositive = new self(INF); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
return self::$infPositive; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @return \Cubiche\Domain\System\DecimalInfinite |
63
|
|
|
*/ |
64
|
|
|
public static function infNegative() |
65
|
|
|
{ |
66
|
|
|
if (self::$infNegative === null) { |
67
|
|
|
self::$infNegative = new self(-INF); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
return self::$infNegative; |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* @param string $value |
75
|
|
|
*/ |
76
|
|
|
protected function __construct($value) |
77
|
|
|
{ |
78
|
|
|
if (\is_infinite($value)) { |
79
|
|
|
$this->value = $value; |
80
|
|
|
} else { |
81
|
|
|
throw new \InvalidArgumentException(sprintf( |
82
|
|
|
'Argument "%s" is invalid. Allowed types for argument are "INF" or "-INF".', |
83
|
|
|
$value |
84
|
|
|
)); |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* {@inheritdoc} |
90
|
|
|
*/ |
91
|
|
View Code Duplication |
public function add(Number $x) |
|
|
|
|
92
|
|
|
{ |
93
|
|
|
if (!$x->isInfinite() || |
94
|
|
|
($this->isPositive() && $x->isPositive()) || |
95
|
|
|
($this->isNegative() && $x->isNegative())) { |
96
|
|
|
return $this; |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
throw new \DomainException('The add operation is not defined between "INF" and "-INF"'); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* {@inheritdoc} |
104
|
|
|
*/ |
105
|
|
|
public function addInteger(Integer $x) |
106
|
|
|
{ |
107
|
|
|
return $this->add($x); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* {@inheritdoc} |
112
|
|
|
*/ |
113
|
|
|
public function addReal(Real $x) |
114
|
|
|
{ |
115
|
|
|
return $this->add($x); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* {@inheritdoc} |
120
|
|
|
*/ |
121
|
|
|
public function addDecimal(Decimal $x, $scale = null) |
122
|
|
|
{ |
123
|
|
|
return $this->add($x); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* {@inheritdoc} |
128
|
|
|
*/ |
129
|
|
View Code Duplication |
public function sub(Number $x) |
|
|
|
|
130
|
|
|
{ |
131
|
|
|
if (!$x->isInfinite() || |
132
|
|
|
($this->isPositive() && $x->isNegative()) || |
133
|
|
|
($this->isNegative() && $x->isPositive())) { |
134
|
|
|
return $this; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
throw new \DomainException('The sub operation is not defined between "INF" and "INF"'); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* {@inheritdoc} |
142
|
|
|
*/ |
143
|
|
|
public function subInteger(Integer $x) |
144
|
|
|
{ |
145
|
|
|
return $this->sub($x); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* {@inheritdoc} |
150
|
|
|
*/ |
151
|
|
|
public function subReal(Real $x) |
152
|
|
|
{ |
153
|
|
|
return $this->sub($x); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* {@inheritdoc} |
158
|
|
|
*/ |
159
|
|
|
public function subDecimal(Decimal $x, $scale = null) |
160
|
|
|
{ |
161
|
|
|
return $this->sub($x); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
/** |
165
|
|
|
* {@inheritdoc} |
166
|
|
|
*/ |
167
|
|
|
public function mult(Number $x) |
168
|
|
|
{ |
169
|
|
|
if ($x->isZero()) { |
170
|
|
|
throw new \DomainException('The mult operation is not defined between "INF" and zero'); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
if ($this->isPositive() === $x->isPositive()) { |
174
|
|
|
return self::infPositive(); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return self::infNegative(); |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* {@inheritdoc} |
182
|
|
|
*/ |
183
|
|
|
public function multInteger(Integer $x) |
184
|
|
|
{ |
185
|
|
|
return $this->mult($x); |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* {@inheritdoc} |
190
|
|
|
*/ |
191
|
|
|
public function multReal(Real $x) |
192
|
|
|
{ |
193
|
|
|
return $this->mult($x); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* {@inheritdoc} |
198
|
|
|
*/ |
199
|
|
|
public function multDecimal(Decimal $x, $scale = null) |
200
|
|
|
{ |
201
|
|
|
return $this->mult($x); |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
protected function divSpecialCases(Number $x) |
205
|
|
|
{ |
206
|
|
|
if ($x->isInfinite()) { |
207
|
|
|
throw new \DomainException('The div operation is not defined between "INF" and "INF"'); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
return parent::divSpecialCases($x); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* {@inheritdoc} |
215
|
|
|
*/ |
216
|
|
|
public function div(Number $x) |
217
|
|
|
{ |
218
|
|
|
$this->divSpecialCases($x); |
219
|
|
|
|
220
|
|
|
if ($this->isPositive() === $x->isPositive()) { |
221
|
|
|
return self::infPositive(); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
return self::infNegative(); |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/** |
228
|
|
|
* {@inheritdoc} |
229
|
|
|
*/ |
230
|
|
|
public function divInteger(Integer $x) |
231
|
|
|
{ |
232
|
|
|
return $this->div($x); |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
/** |
236
|
|
|
* {@inheritdoc} |
237
|
|
|
*/ |
238
|
|
|
public function divReal(Real $x) |
239
|
|
|
{ |
240
|
|
|
return $this->div($x); |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
/** |
244
|
|
|
* {@inheritdoc} |
245
|
|
|
*/ |
246
|
|
|
public function divDecimal(Decimal $x, $scale = null) |
247
|
|
|
{ |
248
|
|
|
return $this->div($x); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @param Number $x |
253
|
|
|
* |
254
|
|
|
* @throws \DomainException |
255
|
|
|
* |
256
|
|
|
* @return \Cubiche\Domain\System\DecimalInfinite |
257
|
|
|
*/ |
258
|
|
View Code Duplication |
protected function powSpecialCases(Number $x) |
|
|
|
|
259
|
|
|
{ |
260
|
|
|
if ($x->isPositive()) { |
261
|
|
|
if ($this->isPositive()) { |
262
|
|
|
return $this; |
263
|
|
|
} |
264
|
|
|
|
265
|
|
|
if ($x->isInfinite()) { |
266
|
|
|
throw new \DomainException('The pow operation is not defined between "-INF" and "INF"'); |
267
|
|
|
} |
268
|
|
|
} elseif ($x->isNegative()) { |
269
|
|
|
return Decimal::fromNative(0); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
return; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* {@inheritdoc} |
277
|
|
|
*/ |
278
|
|
|
public function powInteger(Integer $x) |
279
|
|
|
{ |
280
|
|
|
$value = $this->powSpecialCases($x); |
281
|
|
|
if ($value !== null) { |
282
|
|
|
return $value; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
if ($x->isEven()) { |
286
|
|
|
return self::infPositive(); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
return self::infNegative(); |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* {@inheritdoc} |
294
|
|
|
*/ |
295
|
|
|
public function powReal(Real $x) |
296
|
|
|
{ |
297
|
|
|
$value = $this->powSpecialCases($x); |
298
|
|
|
if ($value !== null) { |
299
|
|
|
return $value; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
throw new NotImplementedException(self::class, 'powReal'); |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* {@inheritdoc} |
307
|
|
|
*/ |
308
|
|
|
public function powDecimal(Decimal $x, $scale = null) |
309
|
|
|
{ |
310
|
|
|
$value = $this->powSpecialCases($x); |
311
|
|
|
if ($value !== null) { |
312
|
|
|
return $value; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
throw new NotImplementedException(self::class, 'powDecimal'); |
316
|
|
|
} |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* {@inheritdoc} |
320
|
|
|
*/ |
321
|
|
|
public function sqrt($scale = null) |
322
|
|
|
{ |
323
|
|
|
throw new NotImplementedException(self::class, 'sqrt'); |
324
|
|
|
} |
325
|
|
|
} |
326
|
|
|
|
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.