xref: /openbsd-src/gnu/usr.bin/perl/cpan/Math-BigInt/t/bigrat.t (revision 5486feefcc8cb79b19e014ab332cc5dfd05b3b33)
1# -*- mode: perl; -*-
2
3use strict;
4use warnings;
5
6use Test::More tests => 203;
7
8# basic testing of Math::BigRat
9
10use Math::BigRat;
11use Math::BigInt;
12use Math::BigFloat;
13
14# shortcuts
15my $mbr = 'Math::BigRat';
16my $mbi = 'Math::BigInt';
17my $mbf = 'Math::BigFloat';
18
19my ($x, $y, $z);
20
21$x = Math::BigRat->new(1234);
22is($x, 1234, 'value of $x');
23isa_ok($x, 'Math::BigRat');
24ok(!$x->isa('Math::BigInt'),
25   "An object of class '" . ref($x) . "' isn't a 'Math::BigInt'");
26ok(!$x->isa('Math::BigFloat'),
27   "An object of class '" . ref($x) . "' isn't a 'Math::BigFloat'");
28
29##############################################################################
30# new and bnorm()
31
32foreach my $method (qw/ new bnorm /) {
33    $x = $mbr->$method(1234);
34    is($x, 1234, qq|\$x = $mbr->$method(1234)|);
35
36    $x = $mbr->$method("1234/1");
37    is($x, 1234, qq|\$x = $mbr->$method("1234/1")|);
38
39    $x = $mbr->$method("1234/2");
40    is($x, 617, qq|\$x = $mbr->$method("1234/2")|);
41
42    $x = $mbr->$method("100/1.0");
43    is($x, 100, qq|\$x = $mbr->$method("100/1.0")|);
44
45    $x = $mbr->$method("10.0/1.0");
46    is($x, 10, qq|\$x = $mbr->$method("10.0/1.0")|);
47
48    $x = $mbr->$method("0.1/10");
49    is($x, "1/100", qq|\$x = $mbr->$method("0.1/10")|);
50
51    $x = $mbr->$method("0.1/0.1");
52    is($x, "1", qq|\$x = $mbr->$method("0.1/0.1")|);
53
54    $x = $mbr->$method("1e2/10");
55    is($x, 10, qq|\$x = $mbr->$method("1e2/10")|);
56
57    $x = $mbr->$method("5/1e2");
58    is($x, "1/20", qq|\$x = $mbr->$method("5/1e2")|);
59
60    $x = $mbr->$method("1e2/1e1");
61    is($x, 10, qq|\$x = $mbr->$method("1e2/1e1")|);
62
63    $x = $mbr->$method("1 / 3");
64    is($x, "1/3", qq|\$x = $mbr->$method("1 / 3")|);
65
66    $x = $mbr->$method("-1 / 3");
67    is($x, "-1/3", qq|\$x = $mbr->$method("-1 / 3")|);
68
69    $x = $mbr->$method("NaN");
70    is($x, "NaN", qq|\$x = $mbr->$method("NaN")|);
71
72    $x = $mbr->$method("inf");
73    is($x, "inf", qq|\$x = $mbr->$method("inf")|);
74
75    $x = $mbr->$method("-inf");
76    is($x, "-inf", qq|\$x = $mbr->$method("-inf")|);
77
78    $x = $mbr->$method("1/");
79    is($x, "NaN", qq|\$x = $mbr->$method("1/")|);
80
81    $x = $mbr->$method("0x7e");
82    is($x, 126, qq|\$x = $mbr->$method("0x7e")|);
83
84    # input ala "1+1/3" isn"t parsed ok yet
85    $x = $mbr->$method("1+1/3");
86    is($x, "NaN", qq|\$x = $mbr->$method("1+1/3")|);
87
88    $x = $mbr->$method("1/1.2");
89    is($x, "5/6", qq|\$x = $mbr->$method("1/1.2")|);
90
91    $x = $mbr->$method("1.3/1.2");
92    is($x, "13/12", qq|\$x = $mbr->$method("1.3/1.2")|);
93
94    $x = $mbr->$method("1.2/1");
95    is($x, "6/5", qq|\$x = $mbr->$method("1.2/1")|);
96
97    ############################################################################
98    # other classes as input
99
100    $x = $mbr->$method($mbi->new(1231));
101    is($x, "1231", qq|\$x = $mbr->$method($mbi->new(1231))|);
102
103    $x = $mbr->$method($mbf->new(1232));
104    is($x, "1232", qq|\$x = $mbr->$method($mbf->new(1232))|);
105
106    $x = $mbr->$method($mbf->new(1232.3));
107    is($x, "12323/10", qq|\$x = $mbr->$method($mbf->new(1232.3))|);
108}
109
110my $n = 'numerator';
111my $d = 'denominator';
112
113$x = $mbr->new('-0');
114is($x, '0');
115is($x->$n(), '0');
116is($x->$d(), '1');
117
118$x = $mbr->new('NaN');
119is($x, 'NaN');  is($x->$n(), 'NaN');
120is($x->$d(), 'NaN');
121
122$x = $mbr->new('-NaN');
123is($x, 'NaN');  is($x->$n(), 'NaN');
124is($x->$d(), 'NaN');
125
126$x = $mbr->new('-1r4');
127is($x, 'NaN');  is($x->$n(), 'NaN');
128is($x->$d(), 'NaN');
129
130$x = $mbr->new('+inf');
131is($x, 'inf');  is($x->$n(), 'inf');
132is($x->$d(), '1');
133
134$x = $mbr->new('-inf');
135is($x, '-inf');
136is($x->$n(), '-inf');
137is($x->$d(), '1');
138
139$x = $mbr->new('123a4');
140is($x, 'NaN');
141is($x->$n(), 'NaN');
142is($x->$d(), 'NaN');
143
144# wrong inputs
145$x = $mbr->new('1e2e2');
146is($x, 'NaN');
147is($x->$n(), 'NaN');
148is($x->$d(), 'NaN');
149
150$x = $mbr->new('1+2+2');
151is($x, 'NaN');
152is($x->$n(), 'NaN');
153is($x->$d(), 'NaN');
154
155# failed due to BigFloat bug
156$x = $mbr->new('1.2.2');
157is($x, 'NaN');
158is($x->$n(), 'NaN');
159is($x->$d(), 'NaN');
160
161is($mbr->new('123a4'), 'NaN');
162is($mbr->new('123e4'), '1230000');
163is($mbr->new('-NaN'), 'NaN');
164is($mbr->new('NaN'), 'NaN');
165is($mbr->new('+inf'), 'inf');
166is($mbr->new('-inf'), '-inf');
167
168##############################################################################
169# two Bigints
170
171is($mbr->new($mbi->new(3), $mbi->new(7))->badd(1), '10/7');
172is($mbr->new($mbi->new(-13), $mbi->new(7)), '-13/7');
173is($mbr->new($mbi->new(13), $mbi->new(-7)), '-13/7');
174is($mbr->new($mbi->new(-13), $mbi->new(-7)), '13/7');
175
176##############################################################################
177# mixed arguments
178
179is($mbr->new('3/7')->badd(1), '10/7');
180is($mbr->new('3/10')->badd(1.1), '7/5');
181is($mbr->new('3/7')->badd($mbi->new(1)), '10/7');
182is($mbr->new('3/10')->badd($mbf->new('1.1')), '7/5');
183
184is($mbr->new('3/7')->bsub(1), '-4/7');
185is($mbr->new('3/10')->bsub(1.1), '-4/5');
186is($mbr->new('3/7')->bsub($mbi->new(1)), '-4/7');
187is($mbr->new('3/10')->bsub($mbf->new('1.1')), '-4/5');
188
189is($mbr->new('3/7')->bmul(1), '3/7');
190is($mbr->new('3/10')->bmul(1.1), '33/100');
191is($mbr->new('3/7')->bmul($mbi->new(1)), '3/7');
192is($mbr->new('3/10')->bmul($mbf->new('1.1')), '33/100');
193
194is($mbr->new('3/7')->bdiv(1), '3/7');
195is($mbr->new('3/10')->bdiv(1.1), '3/11');
196is($mbr->new('3/7')->bdiv($mbi->new(1)), '3/7');
197is($mbr->new('3/10')->bdiv($mbf->new('1.1')), '3/11');
198
199##############################################################################
200$x = $mbr->new('1/4');
201$y = $mbr->new('1/3');
202
203is($x + $y, '7/12');
204is($x * $y, '1/12');
205is($x / $y, '3/4');
206
207$x = $mbr->new('7/5');
208$x *= '3/2';
209is($x, '21/10');
210$x -= '0.1';
211is($x, '2');                    # not 21/10
212
213$x = $mbr->new('2/3');
214$y = $mbr->new('3/2');
215is($x > $y, '');
216is($x < $y, 1);
217is($x == $y, '');
218
219$x = $mbr->new('-2/3');
220$y = $mbr->new('3/2');
221is($x > $y, '');
222is($x < $y, '1');
223is($x == $y, '');
224
225$x = $mbr->new('-2/3');
226$y = $mbr->new('-2/3');
227is($x > $y, '');
228is($x < $y, '');
229is($x == $y, '1');
230
231$x = $mbr->new('-2/3');
232$y = $mbr->new('-1/3');
233is($x > $y, '');
234is($x < $y, '1');
235is($x == $y, '');
236
237$x = $mbr->new('-124');
238$y = $mbr->new('-122');
239is($x->bacmp($y), 1);
240
241$x = $mbr->new('-124');
242$y = $mbr->new('-122');
243is($x->bcmp($y), -1);
244
245$x = $mbr->new('3/7');
246$y = $mbr->new('5/7');
247is($x+$y, '8/7');
248
249$x = $mbr->new('3/7');
250$y = $mbr->new('5/7');
251is($x*$y, '15/49');
252
253$x = $mbr->new('3/5');
254$y = $mbr->new('5/7');
255is($x*$y, '3/7');
256
257$x = $mbr->new('3/5');
258$y = $mbr->new('5/7');
259is($x/$y, '21/25');
260
261$x = $mbr->new('7/4');
262$y = $mbr->new('1');
263is($x % $y, '3/4');
264
265$x = $mbr->new('7/4');
266$y = $mbr->new('5/13');
267is($x % $y, '11/52');
268
269$x = $mbr->new('7/4');
270$y = $mbr->new('5/9');
271is($x % $y, '1/12');
272
273$x = $mbr->new('-144/9')->bsqrt();
274is($x, 'NaN');
275
276$x = $mbr->new('144/9')->bsqrt();
277is($x, '4');
278
279$x = $mbr->new('3/4')->bsqrt();
280is($x,
281   '4330127018922193233818615853764680917357/' .
282   '5000000000000000000000000000000000000000');
283
284##############################################################################
285# bpow
286
287$x = $mbr->new('2/1');
288$z = $x->bpow('3/1');
289is($x, '8');
290
291$x = $mbr->new('1/2');
292$z = $x->bpow('3/1');
293is($x, '1/8');
294
295$x = $mbr->new('1/3');
296$z = $x->bpow('4/1');
297is($x, '1/81');
298
299$x = $mbr->new('2/3');
300$z = $x->bpow('4/1');
301is($x, '16/81');
302
303$x = $mbr->new('2/3');
304$z = $x->bpow('5/3');
305is($x, '31797617848703662994667839220546583581/62500000000000000000000000000000000000');
306
307##############################################################################
308# bfac
309
310$x = $mbr->new('1');
311$x->bfac();
312is($x, '1');
313
314for (my $i = 0; $i < 8; $i++) {
315    $x = $mbr->new("$i/1")->bfac();
316    is($x, $mbi->new($i)->bfac());
317}
318
319# test for $self->bnan() vs. $x->bnan();
320$x = $mbr->new('-1');
321$x->bfac();
322is($x, 'NaN');
323
324##############################################################################
325# binc/bdec
326
327note("binc()");
328$x = $mbr->new('3/2');
329is($x->binc(), '5/2');
330
331note("bdec()");
332
333$x = $mbr->new('15/6');
334is($x->bdec(), '3/2');
335
336##############################################################################
337# bfloor
338
339note("bfloor()");
340$x = $mbr->new('-7/7');
341is($x->$n(), '-1');
342is($x->$d(), '1');
343$x = $mbr->new('-7/7')->bfloor();
344is($x->$n(), '-1');
345is($x->$d(), '1');
346
347##############################################################################
348# bsstr
349
350$x = $mbr->new('7/5')->bsstr();
351is($x, '7/5');
352$x = $mbr->new('-7/5')->bsstr();
353is($x, '-7/5');
354
355##############################################################################
356
357note("numify()");
358
359my @array = qw/1 2 3 4 5 6 7 8 9/;
360$x = $mbr->new('8/8');
361is($array[$x], 2);
362
363$x = $mbr->new('16/8');
364is($array[$x], 3);
365
366$x = $mbr->new('17/8');
367is($array[$x], 3);
368
369$x = $mbr->new('33/8');
370is($array[$x], 5);
371
372$x = $mbr->new('-33/8');
373is($array[$x], 6);
374
375$x = $mbr->new('-8/1');
376is($array[$x], 2);      # -8 => 2
377
378require Math::Complex;
379
380my $inf = $Math::Complex::Inf;
381my $nan = $inf - $inf;
382
383sub isnumeric {
384    my $value = shift;
385    ($value ^ $value) eq "0";
386}
387
388subtest qq|$mbr -> new("33/8") -> numify()| => sub {
389    plan tests => 3;
390
391    $x = $mbr -> new("33/8") -> numify();
392    is(ref($x), "", '$x is a scalar');
393    ok(isnumeric($x), '$x is numeric');
394    cmp_ok($x, "==", 4.125, '$x has the right value');
395};
396
397subtest qq|$mbr -> new("-33/8") -> numify()| => sub {
398    plan tests => 3;
399
400    $x = $mbr -> new("-33/8") -> numify();
401    is(ref($x), "", '$x is a scalar');
402    ok(isnumeric($x), '$x is numeric');
403    cmp_ok($x, "==", -4.125, '$x has the right value');
404};
405
406subtest qq|$mbr -> new("inf") -> numify()| => sub {
407    plan tests => 3;
408
409    $x = $mbr -> new("inf") -> numify();
410    is(ref($x), "", '$x is a scalar');
411    ok(isnumeric($x), '$x is numeric');
412    cmp_ok($x, "==", $inf, '$x has the right value');
413};
414
415subtest qq|$mbr -> new("-inf") -> numify()| => sub {
416    plan tests => 3;
417
418    $x = $mbr -> new("-inf") -> numify();
419    is(ref($x), "", '$x is a scalar');
420    ok(isnumeric($x), '$x is numeric');
421    cmp_ok($x, "==", -$inf, '$x has the right value');
422};
423
424subtest qq|$mbr -> new("NaN") -> numify()| => sub {
425    plan tests => 3;
426
427    $x = $mbr -> new("NaN") -> numify();
428    is(ref($x), "", '$x is a scalar');
429    ok(isnumeric($x), '$x is numeric');
430    cmp_ok($x, "!=", $nan, '$x has the right value');   # Note: NaN != NaN
431};
432
433##############################################################################
434# as_hex(), as_bin(), as_oct()
435
436note("as_hex(), as_bin(), as_oct()");
437
438$x = $mbr->new('8/8');
439is($x->as_hex(), '0x1');
440is($x->as_bin(), '0b1');
441is($x->as_oct(), '01');
442
443$x = $mbr->new('80/8');
444is($x->as_hex(), '0xa');
445is($x->as_bin(), '0b1010');
446is($x->as_oct(), '012');
447
448##############################################################################
449# broot(), blog(), bmodpow() and bmodinv()
450
451note("broot(), blog(), bmodpow(), bmodinv()");
452
453$x = $mbr->new(2) ** 32;
454$y = $mbr->new(4);
455$z = $mbr->new(3);
456
457is($x->copy()->broot($y), 2 ** 8);
458is(ref($x->copy()->broot($y)), $mbr, "\$x is a $mbr");
459
460is($x->copy()->bmodpow($y, $z), 1);
461is(ref($x->copy()->bmodpow($y, $z)), $mbr, "\$x is a $mbr");
462
463$x = $mbr->new(8);
464$y = $mbr->new(5033);
465$z = $mbr->new(4404);
466
467is($x->copy()->bmodinv($y), $z);
468is(ref($x->copy()->bmodinv($y)), $mbr, "\$x is a $mbr");
469
470# square root with exact result
471$x = $mbr->new('1.44');
472is($x->copy()->broot(2), '6/5');
473is(ref($x->copy()->broot(2)), $mbr, "\$x is a $mbr");
474
475# log with exact result
476$x = $mbr->new('256.1');
477is($x->copy()->blog(2),
478   '8000563442710106079310294693803606983661/1000000000000000000000000000000000000000',
479   "\$x = $mbr->new('256.1')->blog(2)");
480is(ref($x->copy()->blog(2)), $mbr, "\$x is a $mbr");
481
482$x = $mbr->new(144);
483is($x->copy()->broot('2'), 12, 'v/144 = 12');
484
485$x = $mbr->new(12*12*12);
486is($x->copy()->broot('3'), 12, '(12*12*12) ** 1/3 = 12');
487
488##############################################################################
489# from_hex(), from_bin(), from_oct()
490
491note("from_hex(), from_bin(), from_oct()");
492
493$x = Math::BigRat->from_hex('0x100');
494is($x, '256', 'from_hex');
495
496$x = $mbr->from_hex('0x100');
497is($x, '256', 'from_hex');
498
499$x = Math::BigRat->from_bin('0b100');
500is($x, '4', 'from_bin');
501
502$x = $mbr->from_bin('0b100');
503is($x, '4', 'from_bin');
504
505$x = Math::BigRat->from_oct('0100');
506is($x, '64', 'from_oct');
507
508$x = $mbr->from_oct('0100');
509is($x, '64', 'from_oct');
510
511##############################################################################
512# as_float()
513
514$x = Math::BigRat->new('1/2');
515my $f = $x->as_float();
516
517is($x, '1/2', '$x unmodified');
518is($f, '0.5', 'as_float(0.5)');
519
520$x = Math::BigRat->new('2/3');
521$f = $x->as_float(5);
522
523is($x, '2/3', '$x unmodified');
524is($f, '0.66667', 'as_float(2/3, 5)');
525
526# Integers should be converted exactly.
527$x = Math::BigRat->new("3141592653589793238462643383279502884197169399375106");
528$f = $x->as_float();
529
530is($x, "3141592653589793238462643383279502884197169399375106", '$x unmodified');
531is($f, "3141592653589793238462643383279502884197169399375106",
532   'as_float(3141592653589793238462643383279502884197169399375106, 5)');
533
534##############################################################################
535# int()
536
537$x = Math::BigRat->new('5/2');
538is(int($x), '2', '5/2 converted to integer');
539
540$x = Math::BigRat->new('-1/2');
541is(int($x), '0', '-1/2 converted to integer');
542
543##############################################################################
544# done
545
5461;
547