DecimalMathTest   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 493
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 3
dl 0
loc 493
rs 10
c 0
b 0
f 0

26 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 5 2
A testBump() 0 5 1
A bumpProvider() 0 20 1
A testSlump() 0 5 1
A slumpProvider() 0 28 1
A testProduct() 0 9 1
A productProvider() 0 24 2
A testProductLargeFloat() 0 9 1
A productLargeFloatProvider() 0 14 2
A testProductWithBC() 0 9 1
A productWithBCProvider() 0 6 1
A testProductLengthOverrun() 0 6 1
A productLengthOverrunProvider() 0 12 1
A testSum() 0 9 1
A sumProvider() 0 15 1
A testMin() 0 9 1
A testMax() 0 9 1
A minMaxProvider() 0 10 1
A testRoundToDigit() 0 6 1
B roundToDigitProvider() 0 81 1
A testGetPositionForExponent() 0 6 1
A getPositionForExponentProvider() 0 12 1
A testRoundToExponent() 0 6 1
B roundToExponentProvider() 0 68 1
A testShift() 0 6 1
A shiftProvider() 0 36 1
1
<?php
2
3
namespace DataValues\Tests;
4
5
use DataValues\DecimalMath;
6
use DataValues\DecimalValue;
7
8
/**
9
 * @covers \DataValues\DecimalMath
10
 *
11
 * @group DataValue
12
 * @group DataValueExtensions
13
 *
14
 * @license GPL-2.0-or-later
15
 * @author Daniel Kinzler
16
 */
17
class DecimalMathTest extends \PHPUnit\Framework\TestCase {
18
19
	public function setUp() : void {
20
		if ( !\extension_loaded( 'bcmath' ) ) {
21
			$this->markTestSkipped( 'bcmath extension not loaded' );
22
		}
23
	}
24
25
	/**
26
	 * @dataProvider bumpProvider
27
	 */
28
	public function testBump( DecimalValue $value, $expected ) {
29
		$math = new DecimalMath();
30
		$actual = $math->bump( $value );
31
		$this->assertSame( $expected, $actual->getValue() );
32
	}
33
34
	public function bumpProvider() {
35
		return [
36
			[ new DecimalValue( '+0' ), '+1' ],
37
			[ new DecimalValue( '-0' ), '+1' ],
38
			[ new DecimalValue( '+0.0' ), '+0.1' ],
39
			[ new DecimalValue( '-0.0' ), '+0.1' ],
40
			[ new DecimalValue( '+1' ), '+2' ],
41
			[ new DecimalValue( '-1' ), '-2' ],
42
			[ new DecimalValue( '+10' ), '+11' ],
43
			[ new DecimalValue( '-10' ), '-11' ],
44
			[ new DecimalValue( '+9' ), '+10' ],
45
			[ new DecimalValue( '-9' ), '-10' ],
46
			[ new DecimalValue( '+0.01' ), '+0.02' ],
47
			[ new DecimalValue( '-0.01' ), '-0.02' ],
48
			[ new DecimalValue( '+0.09' ), '+0.10' ],
49
			[ new DecimalValue( '-0.09' ), '-0.10' ],
50
			[ new DecimalValue( '+0.9' ), '+1.0' ],
51
			[ new DecimalValue( '-0.9' ), '-1.0' ],
52
		];
53
	}
54
55
	/**
56
	 * @dataProvider slumpProvider
57
	 */
58
	public function testSlump( DecimalValue $value, $expected ) {
59
		$math = new DecimalMath();
60
		$actual = $math->slump( $value );
61
		$this->assertSame( $expected, $actual->getValue() );
62
	}
63
64
	public function slumpProvider() {
65
		return [
66
			[ new DecimalValue( '+0' ), '-1' ],
67
			[ new DecimalValue( '-0' ), '-1' ],
68
			[ new DecimalValue( '+0.0' ), '-0.1' ],
69
			[ new DecimalValue( '-0.0' ), '-0.1' ],
70
			[ new DecimalValue( '+0.00' ), '-0.01' ],
71
			[ new DecimalValue( '-0.00' ), '-0.01' ],
72
			[ new DecimalValue( '+1' ), '+0' ],
73
			[ new DecimalValue( '-1' ), '+0' ],
74
			[ new DecimalValue( '+1.0' ), '+0.9' ],
75
			[ new DecimalValue( '-1.0' ), '-0.9' ],
76
			[ new DecimalValue( '+0.1' ), '+0.0' ],
77
			[ new DecimalValue( '-0.1' ), '+0.0' ], // zero is always normalized to be positive
78
			[ new DecimalValue( '+0.01' ), '+0.00' ],
79
			[ new DecimalValue( '-0.01' ), '+0.00' ], // zero is always normalized to be positive
80
			[ new DecimalValue( '+12' ), '+11' ],
81
			[ new DecimalValue( '-12' ), '-11' ],
82
			[ new DecimalValue( '+10' ), '+9' ],
83
			[ new DecimalValue( '-10' ), '-9' ],
84
			[ new DecimalValue( '+100' ), '+99' ],
85
			[ new DecimalValue( '-100' ), '-99' ],
86
			[ new DecimalValue( '+0.02' ), '+0.01' ],
87
			[ new DecimalValue( '-0.02' ), '-0.01' ],
88
			[ new DecimalValue( '+0.10' ), '+0.09' ],
89
			[ new DecimalValue( '-0.10' ), '-0.09' ],
90
		];
91
	}
92
93
	/**
94
	 * @dataProvider productProvider
95
	 */
96
	public function testProduct( $useBC, DecimalValue $a, DecimalValue $b, $value ) {
97
		$math = new DecimalMath( $useBC );
98
99
		$actual = $math->product( $a, $b );
100
		$this->assertSame( $value, $actual->getValue() );
101
102
		$actual = $math->product( $b, $a );
103
		$this->assertSame( $value, $actual->getValue() );
104
	}
105
106
	public function productProvider() {
107
		$cases = [
108
			[ new DecimalValue( '+0' ), new DecimalValue( '+0' ), '+0' ],
109
			[ new DecimalValue( '+0' ), new DecimalValue( '+1' ), '+0' ],
110
			[ new DecimalValue( '+0' ), new DecimalValue( '+2' ), '+0' ],
111
112
			[ new DecimalValue( '+1' ), new DecimalValue( '+0' ), '+0' ],
113
			[ new DecimalValue( '+1' ), new DecimalValue( '+1' ), '+1' ],
114
			[ new DecimalValue( '+1' ), new DecimalValue( '+2' ), '+2' ],
115
116
			[ new DecimalValue( '+2' ), new DecimalValue( '+0' ), '+0' ],
117
			[ new DecimalValue( '+2' ), new DecimalValue( '+1' ), '+2' ],
118
			[ new DecimalValue( '+2' ), new DecimalValue( '+2' ), '+4' ],
119
120
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+0' ), '+0.0' ],
121
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+1' ), '+0.5' ],
122
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+2' ), '+1.0' ],
123
		];
124
125
		foreach ( $cases as $case ) {
126
			yield array_merge( [ true ], $case );
127
			yield array_merge( [ false ], $case );
128
		}
129
	}
130
131
	/**
132
	 * @dataProvider productLargeFloatProvider
133
	 */
134
	public function testProductLargeFloat( $useBC, DecimalValue $a, DecimalValue $b, $regex ) {
135
		$math = new DecimalMath( $useBC );
136
137
		$actual = $math->product( $a, $b );
138
		$this->assertRegExp( $regex, $actual->getValue() );
139
140
		$actual = $math->product( $b, $a );
141
		$this->assertRegExp( $regex, $actual->getValue() );
142
	}
143
144
	public function productLargeFloatProvider() {
145
		$cases = [
146
			[
147
				new DecimalValue( '+1600000000000000000000000000000000000000000000' ),
148
				new DecimalValue( '123.45' ),
149
				'/^\+1975200000000000\d{32}\.\d+$/'
150
			],
151
		];
152
153
		foreach ( $cases as $case ) {
154
			yield array_merge( [ true ], $case );
155
			yield array_merge( [ false ], $case );
156
		}
157
	}
158
159
	/**
160
	 * @dataProvider productWithBCProvider
161
	 */
162
	public function testProductWithBC( DecimalValue $a, DecimalValue $b, $value ) {
163
		$math = new DecimalMath();
164
165
		$actual = $math->product( $a, $b );
166
		$this->assertSame( $value, $actual->getValue() );
167
168
		$actual = $math->product( $b, $a );
169
		$this->assertSame( $value, $actual->getValue() );
170
	}
171
172
	public function productWithBCProvider() {
173
		return [
174
			[ new DecimalValue( '+0.1' ), new DecimalValue( '+0.1' ), '+0.01' ],
175
			[ new DecimalValue( '-5000000' ), new DecimalValue( '-0.1' ), '+500000.0' ],
176
		];
177
	}
178
179
	/**
180
	 * @dataProvider productLengthOverrunProvider
181
	 */
182
	public function testProductLengthOverrun( DecimalValue $a, DecimalValue $b ) {
183
		$math = new DecimalMath();
184
		$actual = $math->product( $a, $b );
185
186
		$this->assertSame( 127, strlen( $actual->getValue() ) );
187
	}
188
189
	public function productLengthOverrunProvider() {
190
		return [
191
			[
192
				new DecimalValue( '+0.' . str_repeat( '3', 124 ) ),
193
				new DecimalValue( '+0.' . str_repeat( '6', 124 ) )
194
			],
195
			[
196
				new DecimalValue( '+' . str_repeat( '9', 126 ) ),
197
				new DecimalValue( '+0.' . str_repeat( '9', 124 ) )
198
			],
199
		];
200
	}
201
202
	/**
203
	 * @dataProvider sumProvider
204
	 */
205
	public function testSum( DecimalValue $a, DecimalValue $b, $value ) {
206
		$math = new DecimalMath();
207
208
		$actual = $math->sum( $a, $b );
209
		$this->assertSame( $value, $actual->getValue() );
210
211
		$actual = $math->sum( $b, $a );
212
		$this->assertSame( $value, $actual->getValue() );
213
	}
214
215
	public function sumProvider() {
216
		return [
217
			[ new DecimalValue( '+0' ), new DecimalValue( '+0' ), '+0' ],
218
			[ new DecimalValue( '+0' ), new DecimalValue( '+1' ), '+1' ],
219
			[ new DecimalValue( '+0' ), new DecimalValue( '+2' ), '+2' ],
220
221
			[ new DecimalValue( '+2' ), new DecimalValue( '+0' ), '+2' ],
222
			[ new DecimalValue( '+2' ), new DecimalValue( '+1' ), '+3' ],
223
			[ new DecimalValue( '+2' ), new DecimalValue( '+2' ), '+4' ],
224
225
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+0' ), '+0.5' ],
226
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+0.5' ), '+1.0' ],
227
			[ new DecimalValue( '+0.5' ), new DecimalValue( '+2' ), '+2.5' ],
228
		];
229
	}
230
231
	/**
232
	 * @dataProvider minMaxProvider
233
	 */
234
	public function testMin( DecimalValue $min, DecimalValue $max ) {
235
		$math = new DecimalMath();
236
237
		$actual = $math->min( $min, $max );
238
		$this->assertSame( $min->getValue(), $actual->getValue() );
239
240
		$actual = $math->min( $max, $min );
241
		$this->assertSame( $min->getValue(), $actual->getValue() );
242
	}
243
244
	/**
245
	 * @dataProvider minMaxProvider
246
	 */
247
	public function testMax( DecimalValue $min, DecimalValue $max ) {
248
		$math = new DecimalMath();
249
250
		$actual = $math->max( $min, $max );
251
		$this->assertSame( $max->getValue(), $actual->getValue() );
252
253
		$actual = $math->max( $max, $min );
254
		$this->assertSame( $max->getValue(), $actual->getValue() );
255
	}
256
257
	public function minMaxProvider() {
258
		return [
259
			[ new DecimalValue( '+0' ), new DecimalValue( '+0' ) ],
260
			[ new DecimalValue( '+1' ), new DecimalValue( '+1' ) ],
261
			[ new DecimalValue( '-0.2' ), new DecimalValue( '-0.2' ) ],
262
263
			[ new DecimalValue( '-2' ), new DecimalValue( '+1' ) ],
264
			[ new DecimalValue( '+0.33333' ), new DecimalValue( '+1' ) ],
265
		];
266
	}
267
268
	/**
269
	 * @dataProvider roundToDigitProvider
270
	 */
271
	public function testRoundToDigit( DecimalValue $value, $digits, $expected ) {
272
		$math = new DecimalMath();
273
274
		$actual = $math->roundToDigit( $value, $digits );
275
		$this->assertSame( $expected, $actual->getValue() );
276
	}
277
278
	public function roundToDigitProvider() {
279
		$argLists = [];
280
281
		//NOTE: Rounding is applied using the "round half away from zero" logic.
282
283
		$argLists[] = [ new DecimalValue( '-2' ), 0, '+0' ]; // no digits left
284
285
		$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ];
286
		$argLists[] = [ new DecimalValue( '+0' ), 2, '+0' ];
287
		$argLists[] = [ new DecimalValue( '+0.0' ), 1, '+0' ];
288
		$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ];
289
		$argLists[] = [ new DecimalValue( '+0.0' ), 3, '+0.0' ];
290
291
		$argLists[] = [ new DecimalValue( '+1.45' ), 1, '+1' ];
292
		$argLists[] = [ new DecimalValue( '+1.45' ), 3, '+1.5' ];
293
		$argLists[] = [ new DecimalValue( '+1.45' ), 4, '+1.45' ];
294
295
		$argLists[] = [ new DecimalValue( '-1.45' ), 1, '-1' ];
296
		$argLists[] = [ new DecimalValue( '-1.45' ), 3, '-1.5' ];
297
		$argLists[] = [ new DecimalValue( '-1.45' ), 4, '-1.45' ];
298
299
		$argLists[] = [ new DecimalValue( '+9.99' ), 1, '+10' ];
300
		$argLists[] = [ new DecimalValue( '+9.99' ), 3, '+10.0' ];
301
		$argLists[] = [ new DecimalValue( '+9.99' ), 4, '+9.99' ];
302
303
		$argLists[] = [ new DecimalValue( '+135.7' ), 1, '+100' ];
304
		$argLists[] = [ new DecimalValue( '+135.7' ), 3, '+136' ];
305
		$argLists[] = [ new DecimalValue( '+135.7' ), 5, '+135.7' ];
306
307
		$argLists[] = [ new DecimalValue( '-2' ), 1, '-2' ];
308
		$argLists[] = [ new DecimalValue( '-2' ), 2, '-2' ];
309
310
		$argLists[] = [ new DecimalValue( '+23' ), 1, '+20' ];
311
		$argLists[] = [ new DecimalValue( '+23' ), 2, '+23' ];
312
		$argLists[] = [ new DecimalValue( '+23' ), 3, '+23' ];
313
		$argLists[] = [ new DecimalValue( '+23' ), 4, '+23' ];
314
315
		$argLists[] = [ new DecimalValue( '-234' ), 1, '-200' ];
316
		$argLists[] = [ new DecimalValue( '-234' ), 2, '-230' ];
317
		$argLists[] = [ new DecimalValue( '-234' ), 3, '-234' ];
318
319
		$argLists[] = [ new DecimalValue( '-2.0' ), 1, '-2' ];
320
		$argLists[] = [ new DecimalValue( '-2.0' ), 2, '-2' ];   // not padded (can't end with decimal point)
321
		$argLists[] = [ new DecimalValue( '-2.0' ), 3, '-2.0' ];
322
		$argLists[] = [ new DecimalValue( '-2.0' ), 4, '-2.0' ]; // no extra digits
323
324
		$argLists[] = [ new DecimalValue( '-2.000' ), 1, '-2' ];
325
		$argLists[] = [ new DecimalValue( '-2.000' ), 2, '-2' ];
326
		$argLists[] = [ new DecimalValue( '-2.000' ), 3, '-2.0' ];
327
		$argLists[] = [ new DecimalValue( '-2.000' ), 4, '-2.00' ];
328
329
		$argLists[] = [ new DecimalValue( '+2.5' ), 1, '+3' ]; // rounded up
330
		$argLists[] = [ new DecimalValue( '+2.5' ), 2, '+3' ];
331
		$argLists[] = [ new DecimalValue( '+2.5' ), 3, '+2.5' ];
332
		$argLists[] = [ new DecimalValue( '+2.5' ), 4, '+2.5' ];
333
334
		$argLists[] = [ new DecimalValue( '+2.05' ), 1, '+2' ];
335
		$argLists[] = [ new DecimalValue( '+2.05' ), 2, '+2' ];
336
		$argLists[] = [ new DecimalValue( '+2.05' ), 3, '+2.1' ]; // rounded up
337
		$argLists[] = [ new DecimalValue( '+2.05' ), 4, '+2.05' ];
338
339
		$argLists[] = [ new DecimalValue( '-23.05' ), 1, '-20' ];
340
		$argLists[] = [ new DecimalValue( '-23.05' ), 2, '-23' ];
341
		$argLists[] = [ new DecimalValue( '-23.05' ), 3, '-23' ]; // not padded (can't end with decimal point)
342
		$argLists[] = [ new DecimalValue( '-23.05' ), 4, '-23.1' ]; // rounded down
343
		$argLists[] = [ new DecimalValue( '-23.05' ), 5, '-23.05' ];
344
345
		$argLists[] = [ new DecimalValue( '+9.33' ), 1, '+9' ]; // no rounding
346
		$argLists[] = [ new DecimalValue( '+9.87' ), 1, '+10' ]; // rounding ripples up
347
		$argLists[] = [ new DecimalValue( '+9.87' ), 3, '+9.9' ]; // rounding ripples up
348
		$argLists[] = [ new DecimalValue( '+99' ), 1, '+100' ]; // rounding ripples up
349
		$argLists[] = [ new DecimalValue( '+99' ), 2, '+99' ]; // rounding ripples up
350
351
		$argLists[] = [ new DecimalValue( '-9.33' ), 1, '-9' ]; // no rounding
352
		$argLists[] = [ new DecimalValue( '-9.87' ), 1, '-10' ]; // rounding ripples down
353
		$argLists[] = [ new DecimalValue( '-9.87' ), 3, '-9.9' ]; // rounding ripples down
354
		$argLists[] = [ new DecimalValue( '-99' ), 1, '-100' ]; // rounding ripples down
355
		$argLists[] = [ new DecimalValue( '-99' ), 2, '-99' ]; // rounding ripples down
356
357
		return $argLists;
358
	}
359
360
	/**
361
	 * @dataProvider getPositionForExponentProvider
362
	 */
363
	public function testGetPositionForExponent( $exponent, DecimalValue $decimal, $expected ) {
364
		$math = new DecimalMath();
365
366
		$actual = $math->getPositionForExponent( $exponent, $decimal );
367
		$this->assertSame( $expected, $actual );
368
	}
369
370
	public function getPositionForExponentProvider() {
371
		$argLists = [];
372
373
		$argLists[] = [ 0, new DecimalValue( '+0' ), 1 ];
374
		$argLists[] = [ 1, new DecimalValue( '+10.25' ), 1 ];
375
		$argLists[] = [ 1, new DecimalValue( '-100.25' ), 2 ];
376
		$argLists[] = [ 2, new DecimalValue( '+100.25' ), 1 ];
377
		$argLists[] = [ -2, new DecimalValue( '+0.234' ), 4 ];
378
		$argLists[] = [ -2, new DecimalValue( '+11.234' ), 5 ];
379
380
		return $argLists;
381
	}
382
383
	/**
384
	 * @dataProvider roundToExponentProvider
385
	 */
386
	public function testRoundToExponent( DecimalValue $value, $digits, $expected ) {
387
		$math = new DecimalMath();
388
389
		$actual = $math->roundToExponent( $value, $digits );
390
		$this->assertSame( $expected, $actual->getValue() );
391
	}
392
393
	public function roundToExponentProvider() {
394
		$argLists = [];
395
396
		//NOTE: Rounding is applied using the "round half away from zero" logic.
397
398
		$argLists[] = [ new DecimalValue( '+0' ), 0, '+0' ];
399
		$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ];
400
		$argLists[] = [ new DecimalValue( '+0.0' ), 0, '+0' ];
401
		$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ];
402
		$argLists[] = [ new DecimalValue( '+0.0' ), -5, '+0.0' ]; // no extra digits
403
404
		$argLists[] = [ new DecimalValue( '+1.45' ), 0, '+1' ];
405
		$argLists[] = [ new DecimalValue( '+1.45' ), 2, '+0' ];
406
		$argLists[] = [ new DecimalValue( '+1.45' ), -5, '+1.45' ];
407
408
		$argLists[] = [ new DecimalValue( '+99.99' ), 0, '+100' ];
409
		$argLists[] = [ new DecimalValue( '+99.99' ), 2, '+0' ];
410
		$argLists[] = [ new DecimalValue( '+99.99' ), -1, '+100.0' ];
411
		$argLists[] = [ new DecimalValue( '+99.99' ), -5, '+99.99' ];
412
413
		$argLists[] = [ new DecimalValue( '-2' ), 0, '-2' ];
414
		$argLists[] = [ new DecimalValue( '-2' ), -1, '-2' ];
415
		$argLists[] = [ new DecimalValue( '-2' ), 1, '+0' ];
416
417
		$argLists[] = [ new DecimalValue( '+23' ), 0, '+23' ];
418
		$argLists[] = [ new DecimalValue( '+23' ), 1, '+20' ];
419
		$argLists[] = [ new DecimalValue( '+23' ), 2, '+0' ];
420
421
		$argLists[] = [ new DecimalValue( '-234' ), 2, '-200' ];
422
		$argLists[] = [ new DecimalValue( '-234' ), 1, '-230' ];
423
		$argLists[] = [ new DecimalValue( '-234' ), 0, '-234' ];
424
425
		$argLists[] = [ new DecimalValue( '-2.0' ), 0, '-2' ];
426
		$argLists[] = [ new DecimalValue( '-2.0' ), -1, '-2.0' ];
427
		$argLists[] = [ new DecimalValue( '-2.0' ), -2, '-2.0' ]; // no extra digits
428
429
		$argLists[] = [ new DecimalValue( '-2.000' ), 0, '-2' ];
430
		$argLists[] = [ new DecimalValue( '-2.000' ), -1, '-2.0' ];
431
		$argLists[] = [ new DecimalValue( '-2.000' ), -2, '-2.00' ];
432
433
		$argLists[] = [ new DecimalValue( '+2.5' ), 0, '+3' ]; // rounded up
434
		$argLists[] = [ new DecimalValue( '+2.5' ), -1, '+2.5' ];
435
		$argLists[] = [ new DecimalValue( '+2.5' ), -2, '+2.5' ]; // no extra digits
436
437
		$argLists[] = [ new DecimalValue( '+2.05' ), 0, '+2' ];
438
		$argLists[] = [ new DecimalValue( '+2.05' ), -1, '+2.1' ]; // rounded up
439
		$argLists[] = [ new DecimalValue( '+2.05' ), -2, '+2.05' ];
440
441
		$argLists[] = [ new DecimalValue( '-23.05' ), 1, '-20' ];
442
		$argLists[] = [ new DecimalValue( '-23.05' ), 0, '-23' ];
443
444
		$argLists[] = [ new DecimalValue( '-23.05' ), -1, '-23.1' ]; // rounded down
445
		$argLists[] = [ new DecimalValue( '-23.05' ), -2, '-23.05' ];
446
447
		$argLists[] = [ new DecimalValue( '+9.33' ), 0, '+9' ]; // no rounding
448
		$argLists[] = [ new DecimalValue( '+9.87' ), 0, '+10' ]; // rounding ripples up
449
		$argLists[] = [ new DecimalValue( '+9.87' ), -1, '+9.9' ]; // rounding ripples up
450
		$argLists[] = [ new DecimalValue( '+99' ), 1, '+100' ]; // rounding ripples up
451
		$argLists[] = [ new DecimalValue( '+99' ), 0, '+99' ]; // rounding ripples up
452
453
		$argLists[] = [ new DecimalValue( '-9.33' ), 0, '-9' ]; // no rounding
454
		$argLists[] = [ new DecimalValue( '-9.87' ), 0, '-10' ]; // rounding ripples down
455
		$argLists[] = [ new DecimalValue( '-9.87' ), -1, '-9.9' ]; // rounding ripples down
456
		$argLists[] = [ new DecimalValue( '-99' ), 1, '-100' ]; // rounding ripples down
457
		$argLists[] = [ new DecimalValue( '-99' ), 0, '-99' ]; // rounding ripples down
458
459
		return $argLists;
460
	}
461
462
	/**
463
	 * @dataProvider shiftProvider
464
	 */
465
	public function testShift( DecimalValue $value, $exponent, $expected ) {
466
		$math = new DecimalMath();
467
468
		$actual = $math->shift( $value, $exponent );
469
		$this->assertSame( $expected, $actual->getValue() );
470
	}
471
472
	public function shiftProvider() {
473
		$argLists = [];
474
475
		$argLists[] = [ new DecimalValue( '+0' ), 0, '+0' ];
476
		$argLists[] = [ new DecimalValue( '+0' ), 1, '+0' ];
477
		$argLists[] = [ new DecimalValue( '+0' ), 2, '+0' ];
478
		$argLists[] = [ new DecimalValue( '+0' ), -1, '+0.0' ];
479
		$argLists[] = [ new DecimalValue( '+0' ), -2, '+0.00' ];
480
481
		$argLists[] = [ new DecimalValue( '+0.0' ), 0, '+0.0' ];
482
		$argLists[] = [ new DecimalValue( '+0.0' ), 1, '+0' ];
483
		$argLists[] = [ new DecimalValue( '+0.0' ), 2, '+0' ];
484
		$argLists[] = [ new DecimalValue( '+0.0' ), -1, '+0.00' ];
485
		$argLists[] = [ new DecimalValue( '+0.0' ), -2, '+0.000' ];
486
487
		$argLists[] = [ new DecimalValue( '-125' ), 0, '-125' ];
488
		$argLists[] = [ new DecimalValue( '-125' ), 1, '-1250' ];
489
		$argLists[] = [ new DecimalValue( '-125' ), 2, '-12500' ];
490
		$argLists[] = [ new DecimalValue( '-125' ), -1, '-12.5' ];
491
		$argLists[] = [ new DecimalValue( '-125' ), -2, '-1.25' ];
492
		$argLists[] = [ new DecimalValue( '-125' ), -3, '-0.125' ];
493
		$argLists[] = [ new DecimalValue( '-125' ), -4, '-0.0125' ];
494
495
		$argLists[] = [ new DecimalValue( '-2.5' ), 0, '-2.5' ];
496
		$argLists[] = [ new DecimalValue( '-2.5' ), 1, '-25' ];
497
		$argLists[] = [ new DecimalValue( '-2.5' ), 2, '-250' ];
498
		$argLists[] = [ new DecimalValue( '-2.5' ), -1, '-0.25' ];
499
		$argLists[] = [ new DecimalValue( '-2.5' ), -2, '-0.025' ];
500
		$argLists[] = [ new DecimalValue( '-2.5' ), -3, '-0.0025' ];
501
502
		$argLists[] = [ new DecimalValue( '+5' ), -4, '+0.0005' ];
503
		$argLists[] = [ new DecimalValue( '+5.0' ), -4, '+0.00050' ];
504
		$argLists[] = [ new DecimalValue( '+5.00' ), -4, '+0.000500' ];
505
506
		return $argLists;
507
	}
508
509
}
510