Test Failed
Pull Request — master (#132)
by Jordan
03:33
created

ArithmeticTests::testPower()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 5
dl 0
loc 10
rs 10
1
<?php
2
3
namespace Samsara\Fermat\Values;
4
5
use PHPUnit\Framework\TestCase;
6
use Samsara\Exceptions\SystemError\PlatformError\MissingPackage;
7
use Samsara\Exceptions\UsageError\IntegrityConstraint;
8
use Samsara\Fermat\Enums\CalcMode;
9
use Samsara\Fermat\Enums\NumberBase;
10
use Samsara\Fermat\Types\Base\Number;
11
12
class ArithmeticTests extends TestCase
13
{
14
15
16
    /*
17
     * ADDITION
18
     */
19
20
    public function additionImmutableDecimalProvider(): array
21
    {
22
23
        $five = (new ImmutableDecimal(5))->setMode(CalcMode::Precision);
24
        $fiveBaseFive = (new ImmutableDecimal(5, null, NumberBase::Five))->setMode(CalcMode::Precision);
25
        $ten = (new ImmutableDecimal(10))->setMode(CalcMode::Precision);
26
        $oneQuarter = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
27
        $sixTenths = (new ImmutableDecimal('0.6'))->setMode(CalcMode::Precision);
28
        $fourTenths = (new ImmutableDecimal('0.4'))->setMode(CalcMode::Precision);
29
        $oneTenth = (new ImmutableDecimal('0.1'))->setMode(CalcMode::Precision);
30
        $twoTenths = (new ImmutableDecimal('0.2'))->setMode(CalcMode::Precision);
31
        $tenScale = (new ImmutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
32
        $elevenScale = (new ImmutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
33
        $tenPowThirty = (new ImmutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
34
        $negFour = (new ImmutableDecimal('-4'))->setMode(CalcMode::Precision);
35
        $fiveI = (new ImmutableDecimal('5i'))->setMode(CalcMode::Precision);
36
        $tenI = (new ImmutableDecimal('10i'))->setMode(CalcMode::Precision);
37
38
        return [
39
            'IDecimal 5+10' => [$five, $ten, '15', NumberBase::Ten, 10],
40
            'IDecimal 5+10 base 5' => [$fiveBaseFive, $ten, '30', NumberBase::Five, 10],
41
            'IDecimal 5+1/4' => [$five, $oneQuarter, '5.25', NumberBase::Ten, 10],
42
            'IDecimal 1/4+5' => [$oneQuarter, $five, '21/4', NumberBase::Ten, 10],
43
            'IDecimal 0.6+0.4' => [$sixTenths, $fourTenths, '1', NumberBase::Ten, 10],
44
            'IDecimal 0.1+0.2' => [$oneTenth, $twoTenths, '0.3', NumberBase::Ten, 10],
45
            'IDecimal 0.1+0.0000000001' => [$oneTenth, $tenScale, '0.1000000001', NumberBase::Ten, 10],
46
            'IDecimal 0.1+0.00000000001' => [$oneTenth, $elevenScale, '0.1', NumberBase::Ten, 10],
47
            'IDecimal 1000000000000000000000000000000+5' => [$tenPowThirty, $five, '1000000000000000000000000000005', NumberBase::Ten, 10],
48
            'IDecimal 1000000000000000000000000000000+0.00000000001' => [$tenPowThirty, $elevenScale, '1000000000000000000000000000000', NumberBase::Ten, 10],
49
            'IDecimal 0.00000000001+1000000000000000000000000000000' => [$elevenScale, $tenPowThirty, '1000000000000000000000000000000.00000000001', NumberBase::Ten, 11],
50
            'IDecimal -4+0.1' => [$negFour, $oneTenth, '-3.9', NumberBase::Ten, 10],
51
            'IDecimal 5+5i' => [$five, $fiveI, MissingPackage::class, NumberBase::Ten, 10],
52
            'IDecimal 5i+10i' => [$fiveI, $tenI, '15i', NumberBase::Ten, 10],
53
        ];
54
55
    }
56
57
    public function additionMutableDecimalProvider(): array
58
    {
59
60
        $five = (new MutableDecimal(5))->setMode(CalcMode::Precision);
61
        $fiveBaseFive = (new MutableDecimal(5, null, NumberBase::Five))->setMode(CalcMode::Precision);
62
        $ten = (new MutableDecimal(10))->setMode(CalcMode::Precision);
63
        $oneQuarter = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
64
        $sixTenths = (new MutableDecimal('0.6'))->setMode(CalcMode::Precision);
65
        $fourTenths = (new MutableDecimal('0.4'))->setMode(CalcMode::Precision);
66
        $oneTenth = (new MutableDecimal('0.1'))->setMode(CalcMode::Precision);
67
        $twoTenths = (new MutableDecimal('0.2'))->setMode(CalcMode::Precision);
68
        $tenScale = (new MutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
69
        $elevenScale = (new MutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
70
        $tenPowThirty = (new MutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
71
        $negFour = (new MutableDecimal('-4'))->setMode(CalcMode::Precision);
72
        $fiveI = (new MutableDecimal('5i'))->setMode(CalcMode::Precision);
73
        $tenI = (new MutableDecimal('10i'))->setMode(CalcMode::Precision);
74
75
        return [
76
            'MDecimal 5+10' => [$five, $ten, '15', NumberBase::Ten, 10],
77
            'MDecimal 5+10 base 5' => [$fiveBaseFive, $ten, '30', NumberBase::Five, 10],
78
            'MDecimal 5+1/4' => [$five, $oneQuarter, '5.25', NumberBase::Ten, 10],
79
            'MDecimal 1/4+5' => [$oneQuarter, $five, '21/4', NumberBase::Ten, 10],
80
            'MDecimal 0.6+0.4' => [$sixTenths, $fourTenths, '1', NumberBase::Ten, 10],
81
            'MDecimal 0.1+0.2' => [$oneTenth, $twoTenths, '0.3', NumberBase::Ten, 10],
82
            'MDecimal 0.1+0.0000000001' => [$oneTenth, $tenScale, '0.1000000001', NumberBase::Ten, 10],
83
            'MDecimal 0.1+0.00000000001' => [$oneTenth, $elevenScale, '0.1', NumberBase::Ten, 10],
84
            'MDecimal 1000000000000000000000000000000+5' => [$tenPowThirty, $five, '1000000000000000000000000000005', NumberBase::Ten, 10],
85
            'MDecimal 1000000000000000000000000000000+0.00000000001' => [$tenPowThirty, $elevenScale, '1000000000000000000000000000000', NumberBase::Ten, 10],
86
            'MDecimal 0.00000000001+1000000000000000000000000000000' => [$elevenScale, $tenPowThirty, '1000000000000000000000000000000.00000000001', NumberBase::Ten, 11],
87
            'MDecimal -4+0.1' => [$negFour, $oneTenth, '-3.9', NumberBase::Ten, 10],
88
            'MDecimal 5+5i' => [$five, $fiveI, MissingPackage::class, NumberBase::Ten, 10],
89
            'MDecimal 5i+10i' => [$fiveI, $tenI, '15i', NumberBase::Ten, 10],
90
        ];
91
92
    }
93
94
    public function additionImmutableFractionProvider(): array
95
    {
96
        $a = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
97
        $b = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
98
        $c = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
99
        $d = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
100
        $e = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(8))->setMode(CalcMode::Precision));
101
        $f = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal('10000000000000000000000000'))->setMode(CalcMode::Precision));
102
103
        return [
104
            'IFraction 1/4+1/5' => [$a, $b, '9/20', NumberBase::Ten, 10],
105
            'IFraction 1/4+3/4' => [$a, $c, '1/1', NumberBase::Ten, 10],
106
            'IFraction 1/5+4/5' => [$b, $d, '1/1', NumberBase::Ten, 10],
107
            'IFraction 1/5+3/4' => [$b, $c, '19/20', NumberBase::Ten, 10],
108
            'IFraction 1/4+4/5' => [$a, $d, '21/20', NumberBase::Ten, 10],
109
            'IFraction 1/4+4/8' => [$a, $e, '3/4', NumberBase::Ten, 10],
110
            'IFraction 4/8+1/4' => [$e, $a, '3/4', NumberBase::Ten, 10],
111
            'IFraction 1/4+3/10000000000000000000000000' => [$a, $f, '2500000000000000000000003/10000000000000000000000000', NumberBase::Ten, 10]
112
        ];
113
    }
114
115
    /**
116
     * @dataProvider additionImmutableDecimalProvider
117
     * @dataProvider additionMutableDecimalProvider
118
     * @dataProvider additionImmutableFractionProvider
119
     */
120
    public function testAddition(Number $a, Number $b, string $expected, NumberBase $base, int $scale)
121
    {
122
        if (str_contains($expected, 'Exception')) {
123
            $this->expectException($expected);
124
            $a->add($b);
125
        } else {
126
            $answer = $a->add($b);
127
            $this->assertEquals($expected, $answer->getValue());
128
            $this->assertEquals($base, $answer->getBase());
0 ignored issues
show
Bug introduced by
The method getBase() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Samsara\Fermat\Types\Bas...s\SimpleNumberInterface or Samsara\Fermat\Types\Bas...mbers\FractionInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

128
            $this->assertEquals($base, $answer->/** @scrutinizer ignore-call */ getBase());
Loading history...
Bug introduced by
The method getBase() does not exist on Samsara\Fermat\Types\Bas...mbers\FractionInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Samsara\Fermat\Types\Bas...mbers\FractionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

128
            $this->assertEquals($base, $answer->/** @scrutinizer ignore-call */ getBase());
Loading history...
129
            $this->assertEquals($scale, $answer->getScale());
130
        }
131
    }
132
133
    /*
134
     * SUBTRACTION
135
     */
136
137
    public function subtractionMutableDecimalProvider(): array
138
    {
139
140
        $five = (new MutableDecimal(5))->setMode(CalcMode::Precision);
141
        $fiveBaseFive = (new MutableDecimal(5, null, NumberBase::Five))->setMode(CalcMode::Precision);
142
        $ten = (new MutableDecimal(10))->setMode(CalcMode::Precision);
143
        $oneQuarter = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
144
        $sixTenths = (new MutableDecimal('0.6'))->setMode(CalcMode::Precision);
145
        $fourTenths = (new MutableDecimal('0.4'))->setMode(CalcMode::Precision);
146
        $oneTenth = (new MutableDecimal('0.1'))->setMode(CalcMode::Precision);
147
        $twoTenths = (new MutableDecimal('0.2'))->setMode(CalcMode::Precision);
148
        $tenScale = (new MutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
149
        $elevenScale = (new MutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
150
        $tenPowThirty = (new MutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
151
        $negFour = (new MutableDecimal('-4'))->setMode(CalcMode::Precision);
152
        $fiveI = (new MutableDecimal('5i'))->setMode(CalcMode::Precision);
153
        $tenI = (new MutableDecimal('10i'))->setMode(CalcMode::Precision);
154
155
        return [
156
            'IDecimal 5-10' => [$five, $ten, '-5', NumberBase::Ten, 10],
157
            'IDecimal 5-10 base 5' => [$fiveBaseFive, $ten, '-10', NumberBase::Five, 10],
158
            'IDecimal 5-1/4' => [$five, $oneQuarter, '4.75', NumberBase::Ten, 10],
159
            'IDecimal 1/4-5' => [$oneQuarter, $five, '-19/4', NumberBase::Ten, 10],
160
            'IDecimal 0.6-0.4' => [$sixTenths, $fourTenths, '0.2', NumberBase::Ten, 10],
161
            'IDecimal 0.1-0.2' => [$oneTenth, $twoTenths, '-0.1', NumberBase::Ten, 10],
162
            'IDecimal 0.1-0.0000000001' => [$oneTenth, $tenScale, '0.0999999999', NumberBase::Ten, 10],
163
            'IDecimal 0.1-0.00000000001' => [$oneTenth, $elevenScale, '0.1', NumberBase::Ten, 10],
164
            'IDecimal 1000000000000000000000000000000-5' => [$tenPowThirty, $five, '999999999999999999999999999995', NumberBase::Ten, 10],
165
            'IDecimal 1000000000000000000000000000000-0.00000000001' => [$tenPowThirty, $elevenScale, '1000000000000000000000000000000', NumberBase::Ten, 10],
166
            'IDecimal 0.00000000001-1000000000000000000000000000000' => [$elevenScale, $tenPowThirty, '-999999999999999999999999999999.99999999999', NumberBase::Ten, 11],
167
            'IDecimal -4-0.1' => [$negFour, $oneTenth, '-4.1', NumberBase::Ten, 10],
168
            'IDecimal 5-5i' => [$five, $fiveI, MissingPackage::class, NumberBase::Ten, 10],
169
            'IDecimal 5i-10i' => [$fiveI, $tenI, '-5i', NumberBase::Ten, 10],
170
        ];
171
172
    }
173
174
    public function subtractionImmutableDecimalProvider(): array
175
    {
176
177
        $five = (new ImmutableDecimal(5))->setMode(CalcMode::Precision);
178
        $fiveBaseFive = (new ImmutableDecimal(5, null, NumberBase::Five))->setMode(CalcMode::Precision);
179
        $ten = (new ImmutableDecimal(10))->setMode(CalcMode::Precision);
180
        $oneQuarter = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
181
        $sixTenths = (new ImmutableDecimal('0.6'))->setMode(CalcMode::Precision);
182
        $fourTenths = (new ImmutableDecimal('0.4'))->setMode(CalcMode::Precision);
183
        $oneTenth = (new ImmutableDecimal('0.1'))->setMode(CalcMode::Precision);
184
        $twoTenths = (new ImmutableDecimal('0.2'))->setMode(CalcMode::Precision);
185
        $tenScale = (new ImmutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
186
        $elevenScale = (new ImmutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
187
        $tenPowThirty = (new ImmutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
188
        $negFour = (new ImmutableDecimal('-4'))->setMode(CalcMode::Precision);
189
        $fiveI = (new ImmutableDecimal('5i'))->setMode(CalcMode::Precision);
190
        $tenI = (new ImmutableDecimal('10i'))->setMode(CalcMode::Precision);
191
192
        return [
193
            'MDecimal 5-10' => [$five, $ten, '-5', NumberBase::Ten, 10],
194
            'MDecimal 5-10 base 5' => [$fiveBaseFive, $ten, '-10', NumberBase::Five, 10],
195
            'MDecimal 5-1/4' => [$five, $oneQuarter, '4.75', NumberBase::Ten, 10],
196
            'MDecimal 1/4-5' => [$oneQuarter, $five, '-19/4', NumberBase::Ten, 10],
197
            'MDecimal 0.6-0.4' => [$sixTenths, $fourTenths, '0.2', NumberBase::Ten, 10],
198
            'MDecimal 0.1-0.2' => [$oneTenth, $twoTenths, '-0.1', NumberBase::Ten, 10],
199
            'MDecimal 0.1-0.0000000001' => [$oneTenth, $tenScale, '0.0999999999', NumberBase::Ten, 10],
200
            'MDecimal 0.1-0.00000000001' => [$oneTenth, $elevenScale, '0.1', NumberBase::Ten, 10],
201
            'MDecimal 1000000000000000000000000000000-5' => [$tenPowThirty, $five, '999999999999999999999999999995', NumberBase::Ten, 10],
202
            'MDecimal 1000000000000000000000000000000-0.00000000001' => [$tenPowThirty, $elevenScale, '1000000000000000000000000000000', NumberBase::Ten, 10],
203
            'IDecimal 0.00000000001-1000000000000000000000000000000' => [$elevenScale, $tenPowThirty, '-999999999999999999999999999999.99999999999', NumberBase::Ten, 11],
204
            'MDecimal -4-0.1' => [$negFour, $oneTenth, '-4.1', NumberBase::Ten, 10],
205
            'MDecimal 5-5i' => [$five, $fiveI, MissingPackage::class, NumberBase::Ten, 10],
206
            'MDecimal 5i-10i' => [$fiveI, $tenI, '-5i', NumberBase::Ten, 10],
207
        ];
208
209
    }
210
211
    public function subtractionImmutableFractionProvider(): array
212
    {
213
        $a = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
214
        $b = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
215
        $c = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
216
        $d = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
217
        $e = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(8))->setMode(CalcMode::Precision));
218
        $f = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal('10000000000000000000000000'))->setMode(CalcMode::Precision));
219
220
        return [
221
            'IFraction 1/4-1/5' =>[$a, $b, '1/20', NumberBase::Ten, 10],
222
            'IFraction 1/4-3/4' =>[$a, $c, '-1/2', NumberBase::Ten, 10],
223
            'IFraction 1/5-4/5' =>[$b, $d, '-3/5', NumberBase::Ten, 10],
224
            'IFraction 1/5-3/4' =>[$b, $c, '-11/20', NumberBase::Ten, 10],
225
            'IFraction 1/4-4/5' =>[$a, $d, '-11/20', NumberBase::Ten, 10],
226
            'IFraction 1/4-4/8' =>[$a, $e, '-1/4', NumberBase::Ten, 10],
227
            'IFraction 4/8-1/4' =>[$e, $a, '1/4', NumberBase::Ten, 10],
228
            'IFraction 1/4-3/10000000000000000000000000' =>[$a, $f, '2499999999999999999999997/10000000000000000000000000', NumberBase::Ten, 10]
229
        ];
230
    }
231
232
    /**
233
     * @dataProvider subtractionImmutableDecimalProvider
234
     * @dataProvider subtractionMutableDecimalProvider
235
     * @dataProvider subtractionImmutableFractionProvider
236
     */
237
    public function testSubtraction(Number $a, Number $b, string $expected, NumberBase $base, int $scale)
238
    {
239
        if (str_contains($expected, 'Exception')) {
240
            $this->expectException($expected);
241
            $a->subtract($b);
242
        } else {
243
            $answer = $a->subtract($b);
244
            $this->assertEquals($expected, $answer->getValue());
245
            $this->assertEquals($base, $answer->getBase());
246
            $this->assertEquals($scale, $answer->getScale());
247
        }
248
    }
249
250
    /*
251
     * MULTIPLICATION
252
     */
253
254
    public function multiplicationImmutableDecimalProvider(): array
255
    {
256
        $a = (new ImmutableDecimal('2'))->setMode(CalcMode::Precision);
257
        $a2 = (new ImmutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
258
        $b = (new ImmutableDecimal('3'))->setMode(CalcMode::Precision);
259
        $c = (new ImmutableDecimal('-2'))->setMode(CalcMode::Precision);
260
        $d = (new ImmutableDecimal('-3'))->setMode(CalcMode::Precision);
261
        $e = (new ImmutableDecimal('0.5'))->setMode(CalcMode::Precision);
262
        $f = (new ImmutableDecimal('-0.5'))->setMode(CalcMode::Precision);
263
        $g = (new ImmutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
264
        $h = (new ImmutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
265
        $i = (new ImmutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
266
        $j = (new ImmutableDecimal('2i'))->setMode(CalcMode::Precision);
267
        $k = (new ImmutableDecimal('3i'))->setMode(CalcMode::Precision);
268
269
        return [
270
            'IDecimal 2*3' => [$a, $b, '6', NumberBase::Ten, 10],
271
            'IDecimal 2*3 base 5' => [$a2, $b, '11', NumberBase::Five, 10],
272
            'IDecimal 2*-2' => [$a, $c, '-4', NumberBase::Ten, 10],
273
            'IDecimal 3*-2' => [$b, $c, '-6', NumberBase::Ten, 10],
274
            'IDecimal -2*-3' => [$c, $d, '6', NumberBase::Ten, 10],
275
            'IDecimal 2*0.5' => [$a, $e, '1', NumberBase::Ten, 10],
276
            'IDecimal 3*0.5' => [$b, $e, '1.5', NumberBase::Ten, 10],
277
            'IDecimal 2*-0.5' => [$a, $f, '-1', NumberBase::Ten, 10],
278
            'IDecimal 3*-0.5' => [$b, $f, '-1.5', NumberBase::Ten, 10],
279
            'IDecimal 2*0.0000000001' => [$a, $g, '0.0000000002', NumberBase::Ten, 10],
280
            'IDecimal 2*0.00000000001' => [$a, $h, '0', NumberBase::Ten, 10],
281
            'IDecimal 2*1000000000000000000000000000000' => [$a, $i, '2000000000000000000000000000000', NumberBase::Ten, 10],
282
            'IDecimal 0.0000000001*1000000000000000000000000000000' => [$g, $i, '100000000000000000000', NumberBase::Ten, 10],
283
            'IDecimal 2*2i' => [$a, $j, '4i', NumberBase::Ten, 10],
284
            'IDecimal 2i*3i' => [$j, $k, '-6', NumberBase::Ten, 10],
285
        ];
286
    }
287
288
    public function multiplicationMutableDecimalProvider(): array
289
    {
290
        $a = (new MutableDecimal('2'))->setMode(CalcMode::Precision);
291
        $a2 = (new MutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
292
        $b = (new MutableDecimal('3'))->setMode(CalcMode::Precision);
293
        $c = (new MutableDecimal('-2'))->setMode(CalcMode::Precision);
294
        $d = (new MutableDecimal('-3'))->setMode(CalcMode::Precision);
295
        $e = (new MutableDecimal('0.5'))->setMode(CalcMode::Precision);
296
        $f = (new MutableDecimal('-0.5'))->setMode(CalcMode::Precision);
297
        $g = (new MutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
298
        $h = (new MutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
299
        $i = (new MutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
300
        $j = (new MutableDecimal('2i'))->setMode(CalcMode::Precision);
301
        $k = (new MutableDecimal('3i'))->setMode(CalcMode::Precision);
302
303
        return [
304
            'MDecimal 2*3' => [$a, $b, '6', NumberBase::Ten, 10],
305
            'MDecimal 2*3 base 5' => [$a2, $b, '11', NumberBase::Five, 10],
306
            'MDecimal 2*-2' => [$a, $c, '-4', NumberBase::Ten, 10],
307
            'MDecimal 3*-2' => [$b, $c, '-6', NumberBase::Ten, 10],
308
            'MDecimal -2*-3' => [$c, $d, '6', NumberBase::Ten, 10],
309
            'MDecimal 2*0.5' => [$a, $e, '1', NumberBase::Ten, 10],
310
            'MDecimal 3*0.5' => [$b, $e, '1.5', NumberBase::Ten, 10],
311
            'MDecimal 2*-0.5' => [$a, $f, '-1', NumberBase::Ten, 10],
312
            'MDecimal 3*-0.5' => [$b, $f, '-1.5', NumberBase::Ten, 10],
313
            'MDecimal 2*0.0000000001' => [$a, $g, '0.0000000002', NumberBase::Ten, 10],
314
            'MDecimal 2*0.00000000001' => [$a, $h, '0', NumberBase::Ten, 10],
315
            'MDecimal 2*1000000000000000000000000000000' => [$a, $i, '2000000000000000000000000000000', NumberBase::Ten, 10],
316
            'MDecimal 0.0000000001*1000000000000000000000000000000' => [$g, $i, '100000000000000000000', NumberBase::Ten, 10],
317
            'MDecimal 2*2i' => [$a, $j, '4i', NumberBase::Ten, 10],
318
            'MDecimal 2i*3i' => [$j, $k, '-6', NumberBase::Ten, 10],
319
        ];
320
    }
321
322
    public function multiplicationImmutableFractionProvider(): array
323
    {
324
        $a = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
325
        $b = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
326
        $c = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
327
        $d = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
328
        $e = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(8))->setMode(CalcMode::Precision));
329
        $f = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal('10000000000000000000000000'))->setMode(CalcMode::Precision));
330
331
        return [
332
            'IFraction 1/4*1/5' => [$a, $b, '1/20', NumberBase::Ten, 10],
333
            'IFraction 1/4*3/4' => [$a, $c, '3/16', NumberBase::Ten, 10],
334
            'IFraction 1/5*4/5' => [$b, $d, '4/25', NumberBase::Ten, 10],
335
            'IFraction 1/5*3/4' => [$b, $c, '3/20', NumberBase::Ten, 10],
336
            'IFraction 1/4*4/5' => [$a, $d, '1/5', NumberBase::Ten, 10],
337
            'IFraction 1/4*4/8' => [$a, $e, '1/8', NumberBase::Ten, 10],
338
            'IFraction 4/8*1/4' => [$e, $a, '1/8', NumberBase::Ten, 10],
339
            'IFraction 1/4*3/10000000000000000000000000' => [$a, $f, '3/40000000000000000000000000', NumberBase::Ten, 10]
340
        ];
341
    }
342
343
    /**
344
     * @dataProvider multiplicationImmutableDecimalProvider
345
     * @dataProvider multiplicationMutableDecimalProvider
346
     * @dataProvider multiplicationImmutableFractionProvider
347
     */
348
    public function testMultiplication(Number $a, Number $b, string $expected, NumberBase $base, int $scale)
349
    {
350
        $answer = $a->multiply($b);
351
        $this->assertEquals($expected, $answer->getValue());
352
        $this->assertEquals($base, $answer->getBase());
353
        $this->assertEquals($scale, $answer->getScale());
354
    }
355
356
    /*
357
     * DIVISION
358
     */
359
360
    public function divisionImmutableDecimalProvider(): array
361
    {
362
        $a = (new ImmutableDecimal('2'))->setMode(CalcMode::Precision);
363
        $a2 = (new ImmutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
364
        $b = (new ImmutableDecimal('3'))->setMode(CalcMode::Precision);
365
        $c = (new ImmutableDecimal('-2'))->setMode(CalcMode::Precision);
366
        $d = (new ImmutableDecimal('-3'))->setMode(CalcMode::Precision);
367
        $e = (new ImmutableDecimal('0.5'))->setMode(CalcMode::Precision);
368
        $f = (new ImmutableDecimal('-0.5'))->setMode(CalcMode::Precision);
369
        $g = (new ImmutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
370
        $h = (new ImmutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
371
        $i = (new ImmutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
372
        $j = (new ImmutableDecimal('5i'))->setMode(CalcMode::Precision);
373
        $k = (new ImmutableDecimal('10i'))->setMode(CalcMode::Precision);
374
        $l = (new ImmutableDecimal('0'))->setMode(CalcMode::Precision);
375
376
        return [
377
            'IDecimal 2 / 3' => [$a, $b, '0.6666666667', NumberBase::Ten, 10],
378
            'IDecimal 2 / 3 base 5' => [$a2, $b, '0.131313131002111', NumberBase::Five, 10],
379
            'IDecimal 2 / -2' => [$a, $c, '-1', NumberBase::Ten, 10],
380
            'IDecimal 3 / -2' => [$b, $c, '-1.5', NumberBase::Ten, 10],
381
            'IDecimal -2 / -3' => [$c, $d, '0.6666666667', NumberBase::Ten, 10],
382
            'IDecimal 2 / 0.5' => [$a, $e, '4', NumberBase::Ten, 10],
383
            'IDecimal 3 / 0.5' => [$b, $e, '6', NumberBase::Ten, 10],
384
            'IDecimal 2 / -0.5' => [$a, $f, '-4', NumberBase::Ten, 10],
385
            'IDecimal 3 / -0.5' => [$b, $f, '-6', NumberBase::Ten, 10],
386
            'IDecimal 2 / 0.0000000001' => [$a, $g, '20000000000', NumberBase::Ten, 10],
387
            'IDecimal 2 / 0.00000000001' => [$a, $h, '200000000000', NumberBase::Ten, 10],
388
            'IDecimal 2 / 1000000000000000000000000000000' => [$a, $i, '0', NumberBase::Ten, 10],
389
            'IDecimal 1000000000000000000000000000000 / 2' => [$i, $a, '500000000000000000000000000000', NumberBase::Ten, 10],
390
            'IDecimal 0.0000000001 / 1000000000000000000000000000000' => [$g, $i, '0', NumberBase::Ten, 10],
391
            'IDecimal 2 / 5i' => [$a, $j, '-0.4i', NumberBase::Ten, 10],
392
            'IDecimal 5i / 2' => [$j, $a, '2.5i', NumberBase::Ten, 10],
393
            'IDecimal 5i / 10i' => [$j, $k, '0.5', NumberBase::Ten, 10],
394
            'IDecimal 2 / 0' => [$a, $l, IntegrityConstraint::class, NumberBase::Ten, 10]
395
        ];
396
    }
397
398
    public function divisionMutableDecimalProvider(): array
399
    {
400
        $a = (new MutableDecimal('2'))->setMode(CalcMode::Precision);
401
        $a2 = (new MutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
402
        $b = (new MutableDecimal('3'))->setMode(CalcMode::Precision);
403
        $c = (new MutableDecimal('-2'))->setMode(CalcMode::Precision);
404
        $d = (new MutableDecimal('-3'))->setMode(CalcMode::Precision);
405
        $e = (new MutableDecimal('0.5'))->setMode(CalcMode::Precision);
406
        $f = (new MutableDecimal('-0.5'))->setMode(CalcMode::Precision);
407
        $g = (new MutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
408
        $h = (new MutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
409
        $i = (new MutableDecimal('1000000000000000000000000000000'))->setMode(CalcMode::Precision);
410
        $j = (new MutableDecimal('5i'))->setMode(CalcMode::Precision);
411
        $k = (new MutableDecimal('10i'))->setMode(CalcMode::Precision);
412
        $l = (new MutableDecimal('0'))->setMode(CalcMode::Precision);
413
414
415
        return [
416
            'MDecimal 2 / 3' => [$a, $b, '0.6666666667', NumberBase::Ten, 10],
417
            'MDecimal 2 / 3 base 5' => [$a2, $b, '0.131313131002111', NumberBase::Five, 10],
418
            'MDecimal 2 / -2' => [$a, $c, '-1', NumberBase::Ten, 10],
419
            'MDecimal 3 / -2' => [$b, $c, '-1.5', NumberBase::Ten, 10],
420
            'MDecimal -2 / -3' => [$c, $d, '0.6666666667', NumberBase::Ten, 10],
421
            'MDecimal 2 / 0.5' => [$a, $e, '4', NumberBase::Ten, 10],
422
            'MDecimal 3 / 0.5' => [$b, $e, '6', NumberBase::Ten, 10],
423
            'MDecimal 2 / -0.5' => [$a, $f, '-4', NumberBase::Ten, 10],
424
            'MDecimal 3 / -0.5' => [$b, $f, '-6', NumberBase::Ten, 10],
425
            'MDecimal 2 / 0.0000000001' => [$a, $g, '20000000000', NumberBase::Ten, 10],
426
            'MDecimal 2 / 0.00000000001' => [$a, $h, '200000000000', NumberBase::Ten, 10],
427
            'MDecimal 2 / 1000000000000000000000000000000' => [$a, $i, '0', NumberBase::Ten, 10],
428
            'MDecimal 1000000000000000000000000000000 / 2' => [$i, $a, '500000000000000000000000000000', NumberBase::Ten, 10],
429
            'MDecimal 0.0000000001 / 1000000000000000000000000000000' => [$g, $i, '0', NumberBase::Ten, 10],
430
            'MDecimal 2 / 5i' => [$a, $j, '-0.4i', NumberBase::Ten, 10],
431
            'MDecimal 5i / 2' => [$j, $a, '2.5i', NumberBase::Ten, 10],
432
            'MDecimal 5i / 10i' => [$j, $k, '0.5', NumberBase::Ten, 10],
433
            'MDecimal 2 / 0' => [$a, $l, IntegrityConstraint::class, NumberBase::Ten, 10]
434
        ];
435
    }
436
437
    public function divisionImmutableFractionProvider(): array
438
    {
439
        $a = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
440
        $b = new ImmutableFraction((new ImmutableDecimal(1))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
441
        $c = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal(4))->setMode(CalcMode::Precision));
442
        $d = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(5))->setMode(CalcMode::Precision));
443
        $e = new ImmutableFraction((new ImmutableDecimal(4))->setMode(CalcMode::Precision), (new ImmutableDecimal(8))->setMode(CalcMode::Precision));
444
        $f = new ImmutableFraction((new ImmutableDecimal(3))->setMode(CalcMode::Precision), (new ImmutableDecimal('10000000000000000000000000'))->setMode(CalcMode::Precision));
445
446
        return [
447
            'IFraction 1/4 / 1/5' => [$a, $b, '5/4', NumberBase::Ten, 10],
448
            'IFraction 1/4 / 3/4' => [$a, $c, '1/3', NumberBase::Ten, 10],
449
            'IFraction 1/5 / 4/5' => [$b, $d, '1/4', NumberBase::Ten, 10],
450
            'IFraction 1/5 / 3/4' => [$b, $c, '4/15', NumberBase::Ten, 10],
451
            'IFraction 1/4 / 4/5' => [$a, $d, '5/16', NumberBase::Ten, 10],
452
            'IFraction 1/4 / 4/8' => [$a, $e, '1/2', NumberBase::Ten, 10],
453
            'IFraction 4/8 / 1/4' => [$e, $a, '2/1', NumberBase::Ten, 10],
454
            'IFraction 1/4 / 3/10000000000000000000000000' => [$a, $f, '2500000000000000000000000/3', NumberBase::Ten, 10]
455
        ];
456
    }
457
458
    /**
459
     * @dataProvider divisionImmutableDecimalProvider
460
     * @dataProvider divisionMutableDecimalProvider
461
     * @dataProvider divisionImmutableFractionProvider
462
     */
463
    public function testDivision(Number $a, Number $b, string $expected, NumberBase $base, int $scale)
464
    {
465
        if (str_contains($expected, 'Exception')) {
466
            $this->expectException($expected);
467
            $a->divide($b);
468
        } else {
469
            $answer = $a->divide($b);
470
            $this->assertEquals($expected, $answer->getValue());
471
            $this->assertEquals($base, $answer->getBase());
472
            $this->assertEquals($scale, $answer->getScale());
473
        }
474
    }
475
476
    /*
477
     * POW
478
     */
479
480
    public function powerImmutableDecimalProvider(): array
481
    {
482
        $a = (new ImmutableDecimal('2'))->setMode(CalcMode::Precision);
483
        $a2 = (new ImmutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
484
        $b = (new ImmutableDecimal('3'))->setMode(CalcMode::Precision);
485
        $c = (new ImmutableDecimal('-2'))->setMode(CalcMode::Precision);
486
        $d = (new ImmutableDecimal('-3'))->setMode(CalcMode::Precision);
487
        $e = (new ImmutableDecimal('0.5'))->setMode(CalcMode::Precision);
488
        $f = (new ImmutableDecimal('-0.5'))->setMode(CalcMode::Precision);
489
        $g = (new ImmutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
490
        $h = (new ImmutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
491
492
493
        return [
494
            'IDecimal 2^3' => [$a, $b, '8', NumberBase::Ten, 10],
495
            'IDecimal 2^3 base 5' => [$a2, $b, '13', NumberBase::Five, 10],
496
            'IDecimal 2^-2' => [$a, $c, '0.25', NumberBase::Ten, 10],
497
            'IDecimal 3^-2' => [$b, $c, '0.1111111111', NumberBase::Ten, 10],
498
            'IDecimal -2^-3' => [$c, $d, '-0.125', NumberBase::Ten, 10],
499
            'IDecimal 2^0.5' => [$a, $e, '1.4142135624', NumberBase::Ten, 10],
500
            'IDecimal -2^0.5' => [$c, $e, MissingPackage::class, NumberBase::Ten, 10],
501
            'IDecimal 3^0.5' => [$b, $e, '1.7320508076', NumberBase::Ten, 10],
502
            'IDecimal 2^-0.5' => [$a, $f, '0.7071067812', NumberBase::Ten, 10],
503
            'IDecimal 3^-0.5' => [$b, $f, '0.5773502692', NumberBase::Ten, 10],
504
            'IDecimal 2^0.0000000001' => [$a, $g, '1.0000000001', NumberBase::Ten, 10],
505
            'IDecimal 2^0.00000000001' => [$a, $h, '1', NumberBase::Ten, 10],
506
        ];
507
    }
508
509
    public function powerMutableDecimalProvider(): array
510
    {
511
        $a = (new MutableDecimal('2'))->setMode(CalcMode::Precision);
512
        $a2 = (new MutableDecimal('2', null, NumberBase::Five))->setMode(CalcMode::Precision);
513
        $b = (new MutableDecimal('3'))->setMode(CalcMode::Precision);
514
        $c = (new MutableDecimal('-2'))->setMode(CalcMode::Precision);
515
        $d = (new MutableDecimal('-3'))->setMode(CalcMode::Precision);
516
        $e = (new MutableDecimal('0.5'))->setMode(CalcMode::Precision);
517
        $f = (new MutableDecimal('-0.5'))->setMode(CalcMode::Precision);
518
        $g = (new MutableDecimal('0.0000000001'))->setMode(CalcMode::Precision);
519
        $h = (new MutableDecimal('0.00000000001'))->setMode(CalcMode::Precision);
520
521
522
        return [
523
            'MDecimal 2^3' => [$a, $b, '8', NumberBase::Ten, 10],
524
            'MDecimal 2^3 base 5' => [$a2, $b, '13', NumberBase::Five, 10],
525
            'MDecimal 2^-2' => [$a, $c, '0.25', NumberBase::Ten, 10],
526
            'MDecimal 3^-2' => [$b, $c, '0.1111111111', NumberBase::Ten, 10],
527
            'MDecimal -2^-3' => [$c, $d, '-0.125', NumberBase::Ten, 10],
528
            'MDecimal 2^0.5' => [$a, $e, '1.4142135624', NumberBase::Ten, 10],
529
            'MDecimal -2^0.5' => [$c, $e, MissingPackage::class, NumberBase::Ten, 10],
530
            'MDecimal 3^0.5' => [$b, $e, '1.7320508076', NumberBase::Ten, 10],
531
            'MDecimal 2^-0.5' => [$a, $f, '0.7071067812', NumberBase::Ten, 10],
532
            'MDecimal 3^-0.5' => [$b, $f, '0.5773502692', NumberBase::Ten, 10],
533
            'MDecimal 2^0.0000000001' => [$a, $g, '1.0000000001', NumberBase::Ten, 10],
534
            'MDecimal 2^0.00000000001' => [$a, $h, '1', NumberBase::Ten, 10],
535
        ];
536
    }
537
538
    /**
539
     * @dataProvider powerImmutableDecimalProvider
540
     * @dataProvider powerMutableDecimalProvider
541
     */
542
    public function testPower(Number $a, Number $b, string $expected, NumberBase $base, int $scale)
543
    {
544
        if (str_contains($expected, 'Exception')) {
545
            $this->expectException($expected);
546
            $a->pow($b);
547
        } else {
548
            $answer = $a->pow($b);
549
            $this->assertEquals($expected, $answer->getValue());
550
            $this->assertEquals($base, $answer->getBase());
551
            $this->assertEquals($scale, $answer->getScale());
552
        }
553
    }
554
555
}