Commit | Line | Data |
58cde26e |
1 | #!/usr/bin/perl -w |
2 | |
ee15d750 |
3 | # test rounding, accuracy, precicion and fallback, round_mode and mixing |
4 | # of classes |
58cde26e |
5 | |
dccbb853 |
6 | # Make sure you always quote any bare floating-point values, lest 123.46 will |
7 | # be stringified to 123.4599999999 due to limited float prevision. |
8 | |
58cde26e |
9 | use strict; |
10 | use Test; |
11 | |
12 | BEGIN |
13 | { |
14 | $| = 1; |
027dc388 |
15 | chdir 't' if -d 't'; |
58cde26e |
16 | unshift @INC, '../lib'; # for running manually |
027dc388 |
17 | plan tests => 260; |
58cde26e |
18 | } |
19 | |
ee15d750 |
20 | # for finding out whether round finds correct class |
21 | package Foo; |
22 | |
23 | use Math::BigInt; |
24 | use vars qw/@ISA $precision $accuracy $div_scale $round_mode/; |
25 | @ISA = qw/Math::BigInt/; |
26 | |
27 | $precision = 6; |
28 | $accuracy = 8; |
29 | $div_scale = 5; |
30 | $round_mode = 'odd'; |
31 | |
32 | sub new |
33 | { |
34 | my $class = shift; |
35 | my $self = { _a => undef, _p => undef, value => 5 }; |
36 | bless $self, $class; |
37 | } |
38 | |
39 | sub bstr |
40 | { |
41 | my $self = shift; |
42 | |
43 | return "$self->{value}"; |
44 | } |
45 | |
46 | # these will be called with the rounding precision or accuracy, depending on |
47 | # class |
48 | sub bround |
49 | { |
50 | my ($self,$a,$r) = @_; |
51 | $self->{value} = 'a' x $a; |
52 | return $self; |
53 | } |
54 | |
55 | sub bnorm |
56 | { |
57 | my $self = shift; |
58 | return $self; |
59 | } |
60 | |
61 | sub bfround |
62 | { |
63 | my ($self,$p,$r) = @_; |
64 | $self->{value} = 'p' x $p; |
65 | return $self; |
66 | } |
67 | |
68 | package main; |
69 | |
58cde26e |
70 | use Math::BigInt; |
71 | use Math::BigFloat; |
72 | |
73 | my ($x,$y,$z,$u); |
74 | |
75 | ############################################################################### |
76 | # test defaults and set/get |
77 | |
78 | ok_undef ($Math::BigInt::accuracy); |
79 | ok_undef ($Math::BigInt::precision); |
dccbb853 |
80 | ok_undef (Math::BigInt::accuracy()); |
81 | ok_undef (Math::BigInt::precision()); |
ee15d750 |
82 | ok_undef (Math::BigInt->accuracy()); |
83 | ok_undef (Math::BigInt->precision()); |
58cde26e |
84 | ok ($Math::BigInt::div_scale,40); |
ee15d750 |
85 | ok (Math::BigInt::div_scale(),40); |
86 | ok ($Math::BigInt::round_mode,'even'); |
58cde26e |
87 | ok (Math::BigInt::round_mode(),'even'); |
dccbb853 |
88 | ok (Math::BigInt->round_mode(),'even'); |
58cde26e |
89 | |
90 | ok_undef ($Math::BigFloat::accuracy); |
91 | ok_undef ($Math::BigFloat::precision); |
dccbb853 |
92 | ok_undef (Math::BigFloat::accuracy()); |
93 | ok_undef (Math::BigFloat::accuracy()); |
94 | ok_undef (Math::BigFloat->precision()); |
ee15d750 |
95 | ok_undef (Math::BigFloat->precision()); |
58cde26e |
96 | ok ($Math::BigFloat::div_scale,40); |
ee15d750 |
97 | ok (Math::BigFloat::div_scale(),40); |
98 | ok ($Math::BigFloat::round_mode,'even'); |
99 | ok (Math::BigFloat::round_mode(),'even'); |
dccbb853 |
100 | ok (Math::BigFloat->round_mode(),'even'); |
101 | |
027dc388 |
102 | # old way |
103 | ok ($Math::BigInt::rnd_mode,'even'); |
104 | ok ($Math::BigFloat::rnd_mode,'even'); |
105 | |
dccbb853 |
106 | $x = eval 'Math::BigInt->round_mode("huhmbi");'; |
107 | ok ($@ =~ /^Unknown round mode huhmbi at/); |
108 | |
109 | $x = eval 'Math::BigFloat->round_mode("huhmbf");'; |
110 | ok ($@ =~ /^Unknown round mode huhmbf at/); |
ee15d750 |
111 | |
027dc388 |
112 | # old way (now with test for validity) |
113 | $x = eval '$Math::BigInt::rnd_mode = "huhmbi";'; |
114 | ok ($@ =~ /^Unknown round mode huhmbi at/); |
115 | $x = eval '$Math::BigFloat::rnd_mode = "huhmbi";'; |
116 | ok ($@ =~ /^Unknown round mode huhmbi at/); |
117 | # see if accessor also changes old variable |
118 | Math::BigInt->round_mode('odd'); |
119 | ok ($Math::BigInt::rnd_mode,'odd'); |
120 | Math::BigFloat->round_mode('odd'); |
121 | ok ($Math::BigFloat::rnd_mode,'odd'); |
122 | |
123 | Math::BigInt->round_mode('even'); |
124 | Math::BigFloat->round_mode('even'); |
125 | |
ee15d750 |
126 | # accessors |
127 | foreach my $class (qw/Math::BigInt Math::BigFloat/) |
128 | { |
129 | ok_undef ($class->accuracy()); |
130 | ok_undef ($class->precision()); |
131 | ok ($class->round_mode(),'even'); |
132 | ok ($class->div_scale(),40); |
133 | |
134 | ok ($class->div_scale(20),20); |
135 | $class->div_scale(40); ok ($class->div_scale(),40); |
136 | |
137 | ok ($class->round_mode('odd'),'odd'); |
138 | $class->round_mode('even'); ok ($class->round_mode(),'even'); |
139 | |
140 | ok ($class->accuracy(2),2); |
141 | $class->accuracy(3); ok ($class->accuracy(),3); |
142 | ok_undef ($class->accuracy(undef)); |
143 | |
144 | ok ($class->precision(2),2); |
145 | ok ($class->precision(-2),-2); |
146 | $class->precision(3); ok ($class->precision(),3); |
147 | ok_undef ($class->precision(undef)); |
148 | } |
58cde26e |
149 | |
150 | # accuracy |
151 | foreach (qw/5 42 -1 0/) |
152 | { |
153 | ok ($Math::BigFloat::accuracy = $_,$_); |
154 | ok ($Math::BigInt::accuracy = $_,$_); |
155 | } |
156 | ok_undef ($Math::BigFloat::accuracy = undef); |
157 | ok_undef ($Math::BigInt::accuracy = undef); |
158 | |
159 | # precision |
160 | foreach (qw/5 42 -1 0/) |
161 | { |
162 | ok ($Math::BigFloat::precision = $_,$_); |
163 | ok ($Math::BigInt::precision = $_,$_); |
164 | } |
165 | ok_undef ($Math::BigFloat::precision = undef); |
166 | ok_undef ($Math::BigInt::precision = undef); |
167 | |
168 | # fallback |
169 | foreach (qw/5 42 1/) |
170 | { |
171 | ok ($Math::BigFloat::div_scale = $_,$_); |
172 | ok ($Math::BigInt::div_scale = $_,$_); |
173 | } |
174 | # illegal values are possible for fallback due to no accessor |
175 | |
176 | # round_mode |
177 | foreach (qw/odd even zero trunc +inf -inf/) |
178 | { |
ee15d750 |
179 | ok ($Math::BigFloat::round_mode = $_,$_); |
180 | ok ($Math::BigInt::round_mode = $_,$_); |
58cde26e |
181 | } |
ee15d750 |
182 | $Math::BigFloat::round_mode = 'zero'; |
183 | ok ($Math::BigFloat::round_mode,'zero'); |
184 | ok ($Math::BigInt::round_mode,'-inf'); # from above |
58cde26e |
185 | |
186 | $Math::BigInt::accuracy = undef; |
187 | $Math::BigInt::precision = undef; |
188 | # local copies |
dccbb853 |
189 | $x = Math::BigFloat->new('123.456'); |
58cde26e |
190 | ok_undef ($x->accuracy()); |
191 | ok ($x->accuracy(5),5); |
192 | ok_undef ($x->accuracy(undef),undef); |
193 | ok_undef ($x->precision()); |
194 | ok ($x->precision(5),5); |
195 | ok_undef ($x->precision(undef),undef); |
196 | |
197 | # see if MBF changes MBIs values |
198 | ok ($Math::BigInt::accuracy = 42,42); |
199 | ok ($Math::BigFloat::accuracy = 64,64); |
200 | ok ($Math::BigInt::accuracy,42); # should be still 42 |
201 | ok ($Math::BigFloat::accuracy,64); # should be still 64 |
202 | |
203 | ############################################################################### |
204 | # see if creating a number under set A or P will round it |
205 | |
206 | $Math::BigInt::accuracy = 4; |
207 | $Math::BigInt::precision = 3; |
208 | |
209 | ok (Math::BigInt->new(123456),123500); # with A |
210 | $Math::BigInt::accuracy = undef; |
211 | ok (Math::BigInt->new(123456),123000); # with P |
212 | |
213 | $Math::BigFloat::accuracy = 4; |
214 | $Math::BigFloat::precision = -1; |
215 | $Math::BigInt::precision = undef; |
216 | |
dccbb853 |
217 | ok (Math::BigFloat->new('123.456'),'123.5'); # with A |
58cde26e |
218 | $Math::BigFloat::accuracy = undef; |
dccbb853 |
219 | ok (Math::BigFloat->new('123.456'),'123.5'); # with P from MBF, not MBI! |
58cde26e |
220 | |
221 | $Math::BigFloat::precision = undef; |
222 | |
223 | ############################################################################### |
224 | # see if setting accuracy/precision actually rounds the number |
225 | |
dccbb853 |
226 | $x = Math::BigFloat->new('123.456'); $x->accuracy(4); ok ($x,'123.5'); |
227 | $x = Math::BigFloat->new('123.456'); $x->precision(-2); ok ($x,'123.46'); |
58cde26e |
228 | |
027dc388 |
229 | $x = Math::BigInt->new(123456); $x->accuracy(4); ok ($x,123500); |
230 | $x = Math::BigInt->new(123456); $x->precision(2); ok ($x,123500); |
58cde26e |
231 | |
232 | ############################################################################### |
233 | # test actual rounding via round() |
234 | |
dccbb853 |
235 | $x = Math::BigFloat->new('123.456'); |
236 | ok ($x->copy()->round(5,2),'123.46'); |
237 | ok ($x->copy()->round(4,2),'123.5'); |
238 | ok ($x->copy()->round(undef,-2),'123.46'); |
58cde26e |
239 | ok ($x->copy()->round(undef,2),100); |
240 | |
dccbb853 |
241 | $x = Math::BigFloat->new('123.45000'); |
242 | ok ($x->copy()->round(undef,-1,'odd'),'123.5'); |
58cde26e |
243 | |
244 | # see if rounding is 'sticky' |
dccbb853 |
245 | $x = Math::BigFloat->new('123.4567'); |
58cde26e |
246 | $y = $x->copy()->bround(); # no-op since nowhere A or P defined |
247 | |
248 | ok ($y,123.4567); |
249 | $y = $x->copy()->round(5,2); |
250 | ok ($y->accuracy(),5); |
251 | ok_undef ($y->precision()); # A has precedence, so P still unset |
252 | $y = $x->copy()->round(undef,2); |
253 | ok ($y->precision(),2); |
254 | ok_undef ($y->accuracy()); # P has precedence, so A still unset |
255 | |
ee15d750 |
256 | # see if setting A clears P and vice versa |
dccbb853 |
257 | $x = Math::BigFloat->new('123.4567'); |
258 | ok ($x,'123.4567'); |
ee15d750 |
259 | ok ($x->accuracy(4),4); |
260 | ok ($x->precision(-2),-2); # clear A |
261 | ok_undef ($x->accuracy()); |
262 | |
dccbb853 |
263 | $x = Math::BigFloat->new('123.4567'); |
264 | ok ($x,'123.4567'); |
ee15d750 |
265 | ok ($x->precision(-2),-2); |
266 | ok ($x->accuracy(4),4); # clear P |
267 | ok_undef ($x->precision()); |
268 | |
58cde26e |
269 | # does copy work? |
270 | $x = Math::BigFloat->new(123.456); $x->accuracy(4); $x->precision(2); |
ee15d750 |
271 | $z = $x->copy(); ok_undef ($z->accuracy(),undef); ok ($z->precision(),2); |
58cde26e |
272 | |
273 | ############################################################################### |
274 | # test wether operations round properly afterwards |
275 | # These tests are not complete, since they do not excercise every "return" |
276 | # statement in the op's. But heh, it's better than nothing... |
277 | |
dccbb853 |
278 | $x = Math::BigFloat->new('123.456'); |
279 | $y = Math::BigFloat->new('654.321'); |
58cde26e |
280 | $x->{_a} = 5; # $x->accuracy(5) would round $x straightaway |
281 | $y->{_a} = 4; # $y->accuracy(4) would round $x straightaway |
282 | |
dccbb853 |
283 | $z = $x + $y; ok ($z,'777.8'); |
284 | $z = $y - $x; ok ($z,'530.9'); |
285 | $z = $y * $x; ok ($z,'80780'); |
286 | $z = $x ** 2; ok ($z,'15241'); |
287 | $z = $x * $x; ok ($z,'15241'); |
ee15d750 |
288 | |
dccbb853 |
289 | # not: $z = -$x; ok ($z,'-123.46'); ok ($x,'123.456'); |
58cde26e |
290 | $z = $x->copy(); $z->{_a} = 2; $z = $z / 2; ok ($z,62); |
291 | $x = Math::BigFloat->new(123456); $x->{_a} = 4; |
292 | $z = $x->copy; $z++; ok ($z,123500); |
293 | |
294 | $x = Math::BigInt->new(123456); |
295 | $y = Math::BigInt->new(654321); |
296 | $x->{_a} = 5; # $x->accuracy(5) would round $x straightaway |
297 | $y->{_a} = 4; # $y->accuracy(4) would round $x straightaway |
298 | |
299 | $z = $x + $y; ok ($z,777800); |
300 | $z = $y - $x; ok ($z,530900); |
301 | $z = $y * $x; ok ($z,80780000000); |
302 | $z = $x ** 2; ok ($z,15241000000); |
303 | # not yet: $z = -$x; ok ($z,-123460); ok ($x,123456); |
304 | $z = $x->copy; $z++; ok ($z,123460); |
305 | $z = $x->copy(); $z->{_a} = 2; $z = $z / 2; ok ($z,62000); |
306 | |
ee15d750 |
307 | $x = Math::BigInt->new(123400); $x->{_a} = 4; |
308 | ok ($x->bnot(),-123400); # not -1234001 |
309 | |
310 | # both babs() and bneg() don't need to round, since the input will already |
311 | # be rounded (either as $x or via new($string)), and they don't change the |
312 | # value |
313 | # The two tests below peek at this by using _a illegally |
314 | $x = Math::BigInt->new(-123401); $x->{_a} = 4; |
315 | ok ($x->babs(),123401); |
316 | $x = Math::BigInt->new(-123401); $x->{_a} = 4; |
317 | ok ($x->bneg(),123401); |
318 | |
58cde26e |
319 | ############################################################################### |
320 | # test mixed arguments |
321 | |
322 | $x = Math::BigFloat->new(10); |
323 | $u = Math::BigFloat->new(2.5); |
324 | $y = Math::BigInt->new(2); |
325 | |
326 | $z = $x + $y; ok ($z,12); ok (ref($z),'Math::BigFloat'); |
327 | $z = $x / $y; ok ($z,5); ok (ref($z),'Math::BigFloat'); |
328 | $z = $u * $y; ok ($z,5); ok (ref($z),'Math::BigFloat'); |
329 | |
330 | $y = Math::BigInt->new(12345); |
331 | $z = $u->copy()->bmul($y,2,0,'odd'); ok ($z,31000); |
332 | $z = $u->copy()->bmul($y,3,0,'odd'); ok ($z,30900); |
333 | $z = $u->copy()->bmul($y,undef,0,'odd'); ok ($z,30863); |
334 | $z = $u->copy()->bmul($y,undef,1,'odd'); ok ($z,30860); |
335 | $z = $u->copy()->bmul($y,undef,-1,'odd'); ok ($z,30862.5); |
336 | |
337 | # breakage: |
338 | # $z = $y->copy()->bmul($u,2,0,'odd'); ok ($z,31000); |
339 | # $z = $y * $u; ok ($z,5); ok (ref($z),'Math::BigInt'); |
340 | # $z = $y + $x; ok ($z,12); ok (ref($z),'Math::BigInt'); |
341 | # $z = $y / $x; ok ($z,0); ok (ref($z),'Math::BigInt'); |
342 | |
ee15d750 |
343 | ############################################################################### |
344 | # rounding in bdiv with fallback and already set A or P |
345 | |
346 | $Math::BigFloat::accuracy = undef; |
347 | $Math::BigFloat::precision = undef; |
348 | $Math::BigFloat::div_scale = 40; |
349 | |
350 | $x = Math::BigFloat->new(10); $x->{_a} = 4; |
351 | ok ($x->bdiv(3),'3.333'); |
352 | ok ($x->{_a},4); # set's it since no fallback |
353 | |
354 | $x = Math::BigFloat->new(10); $x->{_a} = 4; $y = Math::BigFloat->new(3); |
355 | ok ($x->bdiv($y),'3.333'); |
356 | ok ($x->{_a},4); # set's it since no fallback |
357 | |
358 | # rounding to P of x |
359 | $x = Math::BigFloat->new(10); $x->{_p} = -2; |
360 | ok ($x->bdiv(3),'3.33'); |
361 | |
362 | # round in div with requested P |
363 | $x = Math::BigFloat->new(10); |
364 | ok ($x->bdiv(3,undef,-2),'3.33'); |
365 | |
366 | # round in div with requested P greater than fallback |
367 | $Math::BigFloat::div_scale = 5; |
368 | $x = Math::BigFloat->new(10); |
369 | ok ($x->bdiv(3,undef,-8),'3.33333333'); |
370 | $Math::BigFloat::div_scale = 40; |
371 | |
372 | $x = Math::BigFloat->new(10); $y = Math::BigFloat->new(3); $y->{_a} = 4; |
373 | ok ($x->bdiv($y),'3.333'); |
374 | ok ($x->{_a},4); ok ($y->{_a},4); # set's it since no fallback |
375 | ok_undef ($x->{_p}); ok_undef ($y->{_p}); |
376 | |
377 | # rounding to P of y |
378 | $x = Math::BigFloat->new(10); $y = Math::BigFloat->new(3); $y->{_p} = -2; |
379 | ok ($x->bdiv($y),'3.33'); |
380 | ok ($x->{_p},-2); |
381 | ok ($y->{_p},-2); |
382 | ok_undef ($x->{_a}); ok_undef ($y->{_a}); |
383 | |
384 | ############################################################################### |
385 | # test whether bround(-n) fails in MBF (undocumented in MBI) |
386 | eval { $x = Math::BigFloat->new(1); $x->bround(-2); }; |
387 | ok ($@ =~ /^bround\(\) needs positive accuracy/,1); |
388 | |
389 | # test whether rounding to higher accuracy is no-op |
390 | $x = Math::BigFloat->new(1); $x->{_a} = 4; |
391 | ok ($x,'1.000'); |
392 | $x->bround(6); # must be no-op |
393 | ok ($x->{_a},4); |
394 | ok ($x,'1.000'); |
395 | |
396 | $x = Math::BigInt->new(1230); $x->{_a} = 3; |
397 | ok ($x,'1230'); |
398 | $x->bround(6); # must be no-op |
399 | ok ($x->{_a},3); |
400 | ok ($x,'1230'); |
401 | |
402 | # bround(n) should set _a |
403 | $x->bround(2); # smaller works |
404 | ok ($x,'1200'); |
405 | ok ($x->{_a},2); |
406 | |
407 | # bround(-n) is undocumented and only used by MBF |
408 | # bround(-n) should set _a |
409 | $x = Math::BigInt->new(12345); |
410 | $x->bround(-1); |
411 | ok ($x,'12300'); |
412 | ok ($x->{_a},4); |
413 | |
414 | # bround(-n) should set _a |
415 | $x = Math::BigInt->new(12345); |
416 | $x->bround(-2); |
417 | ok ($x,'12000'); |
418 | ok ($x->{_a},3); |
419 | |
420 | # bround(-n) should set _a |
421 | $x = Math::BigInt->new(12345); $x->{_a} = 5; |
422 | $x->bround(-3); |
423 | ok ($x,'10000'); |
424 | ok ($x->{_a},2); |
425 | |
426 | # bround(-n) should set _a |
427 | $x = Math::BigInt->new(12345); $x->{_a} = 5; |
428 | $x->bround(-4); |
429 | ok ($x,'00000'); |
430 | ok ($x->{_a},1); |
431 | |
432 | # bround(-n) should be noop if n too big |
433 | $x = Math::BigInt->new(12345); |
434 | $x->bround(-5); |
435 | ok ($x,'0'); # scale to "big" => 0 |
436 | ok ($x->{_a},0); |
437 | |
438 | # bround(-n) should be noop if n too big |
439 | $x = Math::BigInt->new(54321); |
440 | $x->bround(-5); |
441 | ok ($x,'100000'); # used by MBF to round 0.0054321 at 0.0_6_00000 |
442 | ok ($x->{_a},0); |
443 | |
444 | # bround(-n) should be noop if n too big |
445 | $x = Math::BigInt->new(54321); $x->{_a} = 5; |
446 | $x->bround(-6); |
447 | ok ($x,'100000'); # no-op |
448 | ok ($x->{_a},0); |
449 | |
450 | # bround(n) should set _a |
451 | $x = Math::BigInt->new(12345); $x->{_a} = 5; |
452 | $x->bround(5); # must be no-op |
453 | ok ($x,'12345'); |
454 | ok ($x->{_a},5); |
455 | |
456 | # bround(n) should set _a |
457 | $x = Math::BigInt->new(12345); $x->{_a} = 5; |
458 | $x->bround(6); # must be no-op |
459 | ok ($x,'12345'); |
460 | |
e745a66c |
461 | $x = Math::BigFloat->new('0.0061'); $x->bfround(-2); |
462 | ok ($x,'0.01'); |
ee15d750 |
463 | |
464 | ############################################################################### |
465 | # rounding with already set precision/accuracy |
466 | |
467 | $x = Math::BigFloat->new(1); $x->{_p} = -5; |
468 | ok ($x,'1.00000'); |
469 | |
470 | # further rounding donw |
471 | ok ($x->bfround(-2),'1.00'); |
472 | ok ($x->{_p},-2); |
473 | |
474 | $x = Math::BigFloat->new(12345); $x->{_a} = 5; |
475 | ok ($x->bround(2),'12000'); |
476 | ok ($x->{_a},2); |
477 | |
dccbb853 |
478 | $x = Math::BigFloat->new('1.2345'); $x->{_a} = 5; |
ee15d750 |
479 | ok ($x->bround(2),'1.2'); |
480 | ok ($x->{_a},2); |
481 | |
482 | # mantissa/exponent format and A/P |
dccbb853 |
483 | $x = Math::BigFloat->new('12345.678'); $x->accuracy(4); |
ee15d750 |
484 | ok ($x,'12350'); ok ($x->{_a},4); ok_undef ($x->{_p}); |
485 | ok ($x->{_m}->{_f},1); ok ($x->{_e}->{_f},1); |
486 | ok_undef ($x->{_m}->{_a}); ok_undef ($x->{_e}->{_a}); |
487 | ok_undef ($x->{_m}->{_p}); ok_undef ($x->{_e}->{_p}); |
488 | |
489 | # check for no A/P in case of fallback |
490 | # result |
491 | $x = Math::BigFloat->new(100) / 3; |
492 | ok_undef ($x->{_a}); ok_undef ($x->{_p}); |
493 | |
494 | # result & reminder |
495 | $x = Math::BigFloat->new(100) / 3; ($x,$y) = $x->bdiv(3); |
496 | ok_undef ($x->{_a}); ok_undef ($x->{_p}); |
497 | ok_undef ($y->{_a}); ok_undef ($y->{_p}); |
498 | |
499 | ############################################################################### |
500 | # math with two numbers with differen A and P |
501 | |
502 | $x = Math::BigFloat->new(12345); $x->accuracy(4); # '12340' |
503 | $y = Math::BigFloat->new(12345); $y->accuracy(2); # '12000' |
504 | ok ($x+$y,24000); # 12340+12000=> 24340 => 24000 |
505 | |
506 | $x = Math::BigFloat->new(54321); $x->accuracy(4); # '12340' |
507 | $y = Math::BigFloat->new(12345); $y->accuracy(3); # '12000' |
508 | ok ($x-$y,42000); # 54320+12300=> 42020 => 42000 |
509 | |
dccbb853 |
510 | $x = Math::BigFloat->new('1.2345'); $x->precision(-2); # '1.23' |
511 | $y = Math::BigFloat->new('1.2345'); $y->precision(-4); # '1.2345' |
512 | ok ($x+$y,'2.46'); # 1.2345+1.2300=> 2.4645 => 2.46 |
ee15d750 |
513 | |
514 | ############################################################################### |
515 | # round should find and use proper class |
516 | |
517 | $x = Foo->new(); |
518 | ok ($x->round($Foo::accuracy),'a' x $Foo::accuracy); |
519 | ok ($x->round(undef,$Foo::precision),'p' x $Foo::precision); |
520 | ok ($x->bfround($Foo::precision),'p' x $Foo::precision); |
521 | ok ($x->bround($Foo::accuracy),'a' x $Foo::accuracy); |
522 | |
523 | ############################################################################### |
524 | # find out whether _find_round_parameters is doing what's it's supposed to do |
525 | |
526 | $Math::BigInt::accuracy = undef; |
527 | $Math::BigInt::precision = undef; |
528 | $Math::BigInt::div_scale = 40; |
529 | $Math::BigInt::round_mode = 'odd'; |
530 | |
531 | $x = Math::BigInt->new(123); |
532 | my @params = $x->_find_round_parameters(); |
533 | ok (scalar @params,1); # nothing to round |
534 | |
535 | @params = $x->_find_round_parameters(1); |
536 | ok (scalar @params,4); # a=1 |
537 | ok ($params[0],$x); # self |
538 | ok ($params[1],1); # a |
539 | ok_undef ($params[2]); # p |
540 | ok ($params[3],'odd'); # round_mode |
541 | |
542 | @params = $x->_find_round_parameters(undef,2); |
543 | ok (scalar @params,4); # p=2 |
544 | ok ($params[0],$x); # self |
545 | ok_undef ($params[1]); # a |
546 | ok ($params[2],2); # p |
547 | ok ($params[3],'odd'); # round_mode |
548 | |
549 | eval { @params = $x->_find_round_parameters(undef,2,'foo'); }; |
550 | ok ($@ =~ /^Unknown round mode 'foo'/,1); |
551 | |
552 | @params = $x->_find_round_parameters(undef,2,'+inf'); |
553 | ok (scalar @params,4); # p=2 |
554 | ok ($params[0],$x); # self |
555 | ok_undef ($params[1]); # a |
556 | ok ($params[2],2); # p |
557 | ok ($params[3],'+inf'); # round_mode |
558 | |
559 | @params = $x->_find_round_parameters(2,-2,'+inf'); |
560 | ok (scalar @params,4); # p=2 |
561 | ok ($params[0],$x); # self |
562 | ok ($params[1],2); # a |
563 | ok ($params[2],-2); # p |
564 | ok ($params[3],'+inf'); # round_mode |
565 | |
58cde26e |
566 | # all done |
567 | |
568 | ############################################################################### |
569 | # Perl 5.005 does not like ok ($x,undef) |
570 | |
571 | sub ok_undef |
572 | { |
573 | my $x = shift; |
574 | |
575 | ok (1,1) and return if !defined $x; |
576 | ok ($x,'undef'); |
577 | } |
578 | |