1# -*- mode: perl; -*-
2
3use strict;
4use warnings;
5
6use Test::More tests => 356;;
7
8use Math::BigInt::GMP;
9
10# testing of Math::BigInt::GMP
11
12my $LIB = 'Math::BigInt::GMP';            # pass classname to sub's
13
14# _new and _str
15my $x = $LIB->_new("123");
16my $y = $LIB->_new("321");
17is(ref($x), 'Math::BigInt::GMP');
18is($LIB->_str($x), 123);
19is($LIB->_str($y), 321);
20
21###############################################################################
22
23note "_set()";
24
25my $b = $LIB->_new("123");
26$LIB->_set($b, 12);
27is($LIB->_str($b), 12);
28
29###############################################################################
30
31note "_add(), _sub(), _mul(), _div()";
32
33is($LIB->_str($LIB->_add($x, $y)), 444);
34is($LIB->_str($LIB->_sub($x, $y)), 123);
35is($LIB->_str($x), 123);
36is($LIB->_str($y), 321);
37is($LIB->_str($LIB->_mul($x, $y)), 39483);
38is($LIB->_str(scalar $LIB->_div($x, $y)), 123);
39
40# check that mul/div doesn't change $y
41# and returns the same reference, not something new
42
43is($LIB->_str($LIB->_mul($x, $y)), 39483);
44is($LIB->_str($x), 39483);
45is($LIB->_str($y), 321);
46
47is($LIB->_str(scalar $LIB->_div($x, $y)), 123);
48is($LIB->_str($x), 123);
49is($LIB->_str($y), 321);
50
51$x = $LIB->_new("39483");
52my ($x1, $r1) = $LIB->_div($x, $y);
53is("$x1", "$x");
54$LIB->_inc($x1);
55is("$x1", "$x");
56is($LIB->_str($r1), '0');
57
58# check that sub modifies the right argument:
59
60$x = $LIB->_new("221");
61$y = $LIB->_new("444");
62
63$x = $LIB->_sub($y, $x, 1);                       # 444 - 221 => 223
64
65is($LIB->_str($x), 223);
66is($LIB->_str($y), 444);
67
68$x = $LIB->_new("444");
69$y = $LIB->_new("221");
70
71is($LIB->_str($LIB->_sub($x, $y)), 223);    # 444 - 221 => 223
72
73is($LIB->_str($x), 223);
74is($LIB->_str($y), 221);
75
76###############################################################################
77
78$x = $LIB->_new("39483"); # reset
79$y = $LIB->_new("321");   # reset
80
81my $z = $LIB->_new("2");
82is($LIB->_str($LIB->_add($x, $z)), 39485);
83my ($re, $rr) = $LIB->_div($x, $y);
84
85is($LIB->_str($re), 123);
86is($LIB->_str($rr), 2);
87
88##############################################################################
89
90note "is_zero()";
91
92is($LIB->_is_zero($x) || 0, 0);
93
94note "_is_one()";
95
96is($LIB->_is_one($x)  || 0, 0);
97
98note "_one()";
99
100is($LIB->_str($LIB->_zero()), "0");
101
102note "_zero()";
103
104is($LIB->_str($LIB->_one()),  "1");
105
106##############################################################################
107
108note "_two()";
109
110is($LIB->_str($LIB->_two()), "2");
111is($LIB->_is_ten($LIB->_two()), 0);
112is($LIB->_is_two($LIB->_two()), 1);
113
114note "_ten()";
115
116is($LIB->_str($LIB->_ten()), "10");
117is($LIB->_is_ten($LIB->_ten()), 1);
118is($LIB->_is_two($LIB->_ten()), 0);
119
120is($LIB->_is_one($LIB->_one()), 1);
121is($LIB->_is_one($LIB->_two()), 0);
122is($LIB->_is_one($LIB->_ten()), 0);
123
124is($LIB->_is_one($LIB->_zero()) || 0, 0);
125
126is($LIB->_is_zero($LIB->_zero()), 1);
127
128is($LIB->_is_zero($LIB->_one()) || 0, 0);
129
130###############################################################################
131
132note "is_odd()";
133
134is($LIB->_is_odd($LIB->_one()), 1);
135is($LIB->_is_odd($LIB->_zero()) || 0, 0);
136
137note "is_even()";
138
139is($LIB->_is_even($LIB->_one()) || 0, 0);
140is($LIB->_is_even($LIB->_zero()), 1);
141
142###############################################################################
143
144note "_len() and _alen()";
145
146sub _check_len {
147    my ($str, $method) = @_;
148
149    my $n  = length($str);
150    my $x = $LIB->_new($str);
151
152    # _len() is exact
153    is($LIB->_len($x), $n);
154
155    # _alen() is equal or at most one bigger
156    my $alen = $LIB->_alen($x);
157    ok($n -1 <= $alen && $alen <= $n + 1,
158       qq|\$x = $LIB->_new("$str"); $LIB->_alen(\$x)|)
159      or diag sprintf <<"EOF", $alen, $n - 1, $n, $n + 1;
160         got: '%d'
161    expected: '%d', '%d' or '%d'
162EOF
163}
164
165_check_len("1");
166_check_len("12");
167_check_len("123");
168_check_len("1234");
169_check_len("12345");
170_check_len("123456");
171_check_len("1234567");
172_check_len("12345678");
173_check_len("123456789");
174_check_len("1234567890");
175_check_len("7");
176_check_len("8");
177_check_len("9");
178_check_len("10");
179_check_len("11");
180_check_len("21");
181_check_len("321");
182_check_len("320");
183_check_len("4321");
184_check_len("54321");
185_check_len("654321");
186_check_len("7654321");
187_check_len("7654321");
188_check_len("87654321");
189_check_len("987654321");
190_check_len("9876543219876543210");
191_check_len("1234567890" x 10);
192_check_len("1234567890" x 100);
193
194for (my $i = 1; $i < 9; $i++) {
195    my $a = "$i" . '0' x ($i-1);
196    _check_len($a);
197}
198
199###############################################################################
200
201note "_digit()";
202
203$x = $LIB->_new("123456789");
204is($LIB->_digit($x, 0), 9);
205is($LIB->_digit($x, 1), 8);
206is($LIB->_digit($x, 2), 7);
207is($LIB->_digit($x, -1), 1);
208is($LIB->_digit($x, -2), 2);
209is($LIB->_digit($x, -3), 3);
210
211###############################################################################
212
213note "_copy()";
214
215foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) {
216    $x = $LIB->_new("$_");
217    is($LIB->_str($LIB->_copy($x)), "$_");
218    is($LIB->_str($x), "$_");     # did _copy destroy original x?
219}
220
221###############################################################################
222
223note "_zeros()";
224
225$x = $LIB->_new("1256000000");
226is($LIB->_zeros($x), 6);
227
228$x = $LIB->_new("152");
229is($LIB->_zeros($x), 0);
230
231$x = $LIB->_new("123000");
232is($LIB->_zeros($x), 3);
233
234$x = $LIB->_new("123001");
235is($LIB->_zeros($x), 0);
236
237$x = $LIB->_new("1");
238is($LIB->_zeros($x), 0);
239
240$x = $LIB->_new("8");
241is($LIB->_zeros($x), 0);
242
243$x = $LIB->_new("10");
244is($LIB->_zeros($x), 1);
245
246$x = $LIB->_new("11");
247is($LIB->_zeros($x), 0);
248
249$x = $LIB->_new("0");
250is($LIB->_zeros($x), 0);
251
252###############################################################################
253
254note "_lsft()";
255
256$x = $LIB->_new("10");
257$y = $LIB->_new("3");
258is($LIB->_str($LIB->_lsft($x, $y, 10)), 10000);
259
260$x = $LIB->_new("20");
261$y = $LIB->_new("3");
262is($LIB->_str($LIB->_lsft($x, $y, 10)), 20000);
263
264$x = $LIB->_new("128");
265$y = $LIB->_new("4");
266is($LIB->_str($LIB->_lsft($x, $y, 2)), 128 << 4);
267
268note "_rsft()";
269
270$x = $LIB->_new("1000");
271$y = $LIB->_new("3");
272is($LIB->_str($LIB->_rsft($x, $y, 10)), 1);
273
274$x = $LIB->_new("20000");
275$y = $LIB->_new("3");
276is($LIB->_str($LIB->_rsft($x, $y, 10)), 20);
277
278$x = $LIB->_new("256");
279$y = $LIB->_new("4");
280is($LIB->_str($LIB->_rsft($x, $y, 2)), 256 >> 4);
281
282$x = $LIB->_new("6411906467305339182857313397200584952398");
283$y = $LIB->_new("45");
284is($LIB->_str($LIB->_rsft($x, $y, 10)), 0);
285
286###############################################################################
287
288note "_acmp()";
289
290$x = $LIB->_new("123456789");
291$y = $LIB->_new("987654321");
292is($LIB->_acmp($x, $y), -1);
293is($LIB->_acmp($y, $x), 1);
294is($LIB->_acmp($x, $x), 0);
295is($LIB->_acmp($y, $y), 0);
296$x = $LIB->_new("12");
297$y = $LIB->_new("12");
298is($LIB->_acmp($x, $y), 0);
299$x = $LIB->_new("21");
300is($LIB->_acmp($x, $y), 1);
301is($LIB->_acmp($y, $x), -1);
302$x = $LIB->_new("123456789");
303$y = $LIB->_new("1987654321");
304is($LIB->_acmp($x, $y), -1);
305is($LIB->_acmp($y, $x), +1);
306
307$x = $LIB->_new("1234567890123456789");
308$y = $LIB->_new("987654321012345678");
309is($LIB->_acmp($x, $y), 1);
310is($LIB->_acmp($y, $x), -1);
311is($LIB->_acmp($x, $x), 0);
312is($LIB->_acmp($y, $y), 0);
313
314$x = $LIB->_new("1234");
315$y = $LIB->_new("987654321012345678");
316is($LIB->_acmp($x, $y), -1);
317is($LIB->_acmp($y, $x), 1);
318is($LIB->_acmp($x, $x), 0);
319is($LIB->_acmp($y, $y), 0);
320
321###############################################################################
322
323note "_modinv()";
324
325$x = $LIB->_new("8");
326$y = $LIB->_new("5033");
327my ($xmod, $sign) = $LIB->_modinv($x, $y);
328is($LIB->_str($xmod), '4404');
329           # (4404 * 8) % 5033 = 1
330is($sign, '+');
331
332###############################################################################
333
334note "_div()";
335
336$x = $LIB->_new("3333");
337$y = $LIB->_new("1111");
338is($LIB->_str(scalar $LIB->_div($x, $y)), 3);
339$x = $LIB->_new("33333");
340$y = $LIB->_new("1111");
341($x, $y) = $LIB->_div($x, $y);
342is($LIB->_str($x), 30);
343is($LIB->_str($y), 3);
344$x = $LIB->_new("123");
345$y = $LIB->_new("1111");
346($x, $y) = $LIB->_div($x, $y);
347is($LIB->_str($x), 0);
348is($LIB->_str($y), 123);
349
350###############################################################################
351
352note "_num()";
353
354foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) {
355    $x = $LIB->_new("$_");
356    is(ref($x) || '', 'Math::BigInt::GMP');
357    is($LIB->_str($x), "$_");
358    $x = $LIB->_num($x);
359    is(ref($x) || '', '');
360    is($x, $_);
361}
362
363###############################################################################
364
365note "_sqrt()";
366
367$x = $LIB->_new("144");
368is($LIB->_str($LIB->_sqrt($x)), '12');
369$x = $LIB->_new("144000000000000");
370is($LIB->_str($LIB->_sqrt($x)), '12000000');
371
372###############################################################################
373
374note "_root()";
375
376$x = $LIB->_new("81");
377my $n = $LIB->_new("3");
378is($LIB->_str($LIB->_root($x, $n)), '4');   # 4*4*4 = 64, 5*5*5 = 125
379
380$x = $LIB->_new("81");
381$n = $LIB->_new("4");
382is($LIB->_str($LIB->_root($x, $n)), '3');   # 3*3*3*3 == 81
383
384###############################################################################
385
386note "_pow() (and _root())";
387
388$x = $LIB->_new("0");
389$n = $LIB->_new("3");
390is($LIB->_str($LIB->_pow($x, $n)), 0);      # 0 ** y => 0
391
392$x = $LIB->_new("3");
393$n = $LIB->_new("0");
394is($LIB->_str($LIB->_pow($x, $n)), 1);      # x ** 0 => 1
395
396$x = $LIB->_new("1");
397$n = $LIB->_new("3");
398is($LIB->_str($LIB->_pow($x, $n)), 1);      # 1 ** y => 1
399
400$x = $LIB->_new("5");
401$n = $LIB->_new("1");
402is($LIB->_str($LIB->_pow($x, $n)), 5);      # x ** 1 => x
403
404$x = $LIB->_new("81");
405$n = $LIB->_new("3");
406
407is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3);    # 81 ** 3 == 531441
408
409is($LIB->_str($LIB->_root($x, $n)), 81);
410
411$x = $LIB->_new("81");
412is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3);
413is($LIB->_str($LIB->_pow($x, $n)), '150094635296999121');   # 531441 ** 3 ==
414
415is($LIB->_str($LIB->_root($x, $n)), '531441');
416is($LIB->_str($LIB->_root($x, $n)), '81');
417
418$x = $LIB->_new("81");
419$n = $LIB->_new("14");
420is($LIB->_str($LIB->_pow($x, $n)), '523347633027360537213511521');
421is($LIB->_str($LIB->_root($x, $n)), '81');
422
423$x = $LIB->_new("523347633027360537213511520");
424is($LIB->_str($LIB->_root($x, $n)), '80');
425
426$x = $LIB->_new("523347633027360537213511522");
427is($LIB->_str($LIB->_root($x, $n)), '81');
428
429my $res = [ qw/ 9 31 99 316 999 3162 9999/ ];
430
431# 99 ** 2 = 9801, 999 ** 2 = 998001 etc
432for my $i (2 .. 9) {
433    $x = '9' x $i;
434    $x = $LIB->_new($x);
435    $n = $LIB->_new("2");
436    my $rc = '9' x ($i-1). '8' . '0' x ($i-1) . '1';
437    is($LIB->_str($LIB->_pow($x, $n)), $rc,
438       "_pow(" . ('9' x $i) . ", 2)");
439
440    if ($i <= 7) {
441        $x = '9' x $i;
442        $x = $LIB->_new($x);
443        $n = '9' x $i;
444        $n = $LIB->_new($n);
445        is($LIB->_str($LIB->_root($x, $n)), '1',
446           "_root(" . ('9' x $i) . ", " . (9 x $i) . ")");
447
448
449        $x = '9' x $i;
450        $x = $LIB->_new($x);
451        $n = $LIB->_new("2");
452        is($LIB->_str($LIB->_root($x, $n)), $res->[$i-2],
453           "_root(" . ('9' x $i) . ", " . (9 x $i) . ")");
454    }
455}
456
457##############################################################################
458# _fac
459
460$x = $LIB->_new("0");
461is($LIB->_str($LIB->_fac($x)), '1');
462
463$x = $LIB->_new("1");
464is($LIB->_str($LIB->_fac($x)), '1');
465
466$x = $LIB->_new("2");
467is($LIB->_str($LIB->_fac($x)), '2');
468
469$x = $LIB->_new("3");
470is($LIB->_str($LIB->_fac($x)), '6');
471
472$x = $LIB->_new("4");
473is($LIB->_str($LIB->_fac($x)), '24');
474
475$x = $LIB->_new("5");
476is($LIB->_str($LIB->_fac($x)), '120');
477
478$x = $LIB->_new("10");
479is($LIB->_str($LIB->_fac($x)), '3628800');
480
481$x = $LIB->_new("11");
482is($LIB->_str($LIB->_fac($x)), '39916800');
483
484$x = $LIB->_new("12");
485is($LIB->_str($LIB->_fac($x)), '479001600');
486
487$x = $LIB->_new("13");
488is($LIB->_str($LIB->_fac($x)), '6227020800');
489
490# test that _fac modifes $x in place for small arguments
491
492$x = $LIB->_new("3");  $LIB->_fac($x); is($LIB->_str($x), '6');
493$x = $LIB->_new("13"); $LIB->_fac($x); is($LIB->_str($x), '6227020800');
494
495##############################################################################
496
497note "_inc() and _dec()";
498
499foreach (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) {
500    $x = $LIB->_new("$_");
501    $LIB->_inc($x);
502    print "# \$x = ", $LIB->_str($x), "\n"
503      unless is($LIB->_str($x), substr($_, 0, length($_)-1) . '2');
504    $LIB->_dec($x);
505    is($LIB->_str($x), $_);
506}
507
508foreach (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) {
509    $x = $LIB->_new("$_");
510    $LIB->_inc($x);
511    print "# \$x = ", $LIB->_str($x), "\n"
512      unless is($LIB->_str($x), substr($_, 0, length($_)-2) . '20');
513    $LIB->_dec($x);
514    is($LIB->_str($x), $_);
515}
516
517foreach (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) {
518    $x = $LIB->_new("$_");
519    $LIB->_inc($x);
520    print "# \$x = ", $LIB->_str($x), "\n"
521      unless is($LIB->_str($x), '1' . '0' x (length($_)));
522    $LIB->_dec($x);
523    is($LIB->_str($x), $_);
524}
525
526$x = $LIB->_new("1000");
527$LIB->_inc($x);
528is($LIB->_str($x), '1001');
529$LIB->_dec($x);
530is($LIB->_str($x), '1000');
531
532###############################################################################
533
534note "_log_int()";
535
536# test handling of plain scalar as base, bug up to v1.17)
537
538$x = $LIB->_new("81");
539
540my ($r, $exact) = $LIB->_log_int($x, $LIB->_new("3"));
541is($LIB->_str($r), '4');
542ok($LIB->_str($x) eq '81' || $LIB->_str($x) eq '4');
543is($exact, 1);
544
545$x = $LIB->_new("81");
546
547($r, $exact) = $LIB->_log_int($x, 3);
548is($LIB->_str($r), '4');
549ok($LIB->_str($x) eq '81' || $LIB->_str($x) eq '4');
550is($exact, 1);
551
552###############################################################################
553
554note "_mod()";
555
556$x = $LIB->_new("1000");
557$y = $LIB->_new("3");
558is($LIB->_str(scalar $LIB->_mod($x, $y)), 1);
559$x = $LIB->_new("1000");
560$y = $LIB->_new("2");
561is($LIB->_str(scalar $LIB->_mod($x, $y)), 0);
562
563###############################################################################
564
565note "_and(), _or(), _xor()";
566
567$x = $LIB->_new("5");
568$y = $LIB->_new("2");
569is($LIB->_str(scalar $LIB->_xor($x, $y)), 7);
570$x = $LIB->_new("5");
571$y = $LIB->_new("2");
572is($LIB->_str(scalar $LIB->_or($x, $y)), 7);
573$x = $LIB->_new("5");
574$y = $LIB->_new("3");
575is($LIB->_str(scalar $LIB->_and($x, $y)), 1);
576
577###############################################################################
578
579note "_from_hex() and _from_bin()";
580
581is($LIB->_str($LIB->_from_hex("0xFf")), 255);
582is($LIB->_str($LIB->_from_bin("0b10101011")), 160+11);
583
584###############################################################################
585
586note "_as_hex() and _as_bin()";
587
588is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("128")))), 128);
589is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("128")))), 128);
590is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("0")))), 0);
591is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("0")))), 0);
592is($LIB->_as_hex($LIB->_new("0")), '0x0');
593is($LIB->_as_bin($LIB->_new("0")), '0b0');
594is($LIB->_as_hex($LIB->_new("12")), '0xc');
595is($LIB->_as_bin($LIB->_new("12")), '0b1100');
596
597###############################################################################
598
599note "_from_oct()";
600
601$x = $LIB->_from_oct("001");      is($LIB->_str($x), '1');
602$x = $LIB->_from_oct("07");       is($LIB->_str($x), '7');
603$x = $LIB->_from_oct("077");      is($LIB->_str($x), '63');
604$x = $LIB->_from_oct("07654321"); is($LIB->_str($x), '2054353');
605
606###############################################################################
607
608note "_as_oct()";
609
610$x = $LIB->_new("2054353"); is($LIB->_as_oct($x), '07654321');
611$x = $LIB->_new("63");      is($LIB->_as_oct($x), '077');
612$x = $LIB->_new("0");       is($LIB->_as_oct($x), '00');
613
614###############################################################################
615
616note "_1ex()";
617
618is($LIB->_str($LIB->_1ex(0)), "1");
619is($LIB->_str($LIB->_1ex(1)), "10");
620is($LIB->_str($LIB->_1ex(2)), "100");
621is($LIB->_str($LIB->_1ex(12)), "1000000000000");
622is($LIB->_str($LIB->_1ex(16)), "10000000000000000");
623
624###############################################################################
625
626note "_check()";
627
628$x = $LIB->_new("123456789");
629is($LIB->_check($x), 0);
630is($LIB->_check(123), '123 is not a reference to Math::BigInt::GMP');
631
632# done
633
6341;
635