File Coverage

blib/lib/Math/ModInt/BigInt.pm
Criterion Covered Total %
statement 78 78 100.0
branch 20 20 100.0
condition 6 6 100.0
subroutine 21 21 100.0
pod 2 2 100.0
total 127 127 100.0


line stmt bran cond sub pod time code
1             # Copyright (c) 2009-2019 Martin Becker, Blaubeuren.
2             # This package is free software; you can distribute it and/or modify it
3             # under the terms of the Artistic License 2.0 (see LICENSE file).
4              
5             package Math::ModInt::BigInt;
6              
7 4     4   1020 use 5.006;
  4         13  
8 4     4   21 use strict;
  4         8  
  4         76  
9 4     4   26 use warnings;
  4         6  
  4         105  
10 4     4   21 use Carp qw(croak);
  4         6  
  4         197  
11 4     4   1197 use Math::BigInt;
  4         26727  
  4         22  
12 4     4   26009 use constant _ISSUE_CPAN_RT79060 => -1 != Math::BigInt->new(-2) / 3;
  4         9  
  4         25  
13              
14             # ----- object definition -----
15              
16             # Math::ModInt::BigInt=ARRAY(...)
17              
18             # .......... index .......... # .......... value ..........
19 4     4   2866 use constant F_RESIDUE => 0; # residue r, 0 <= r < m
  4         8  
  4         187  
20 4     4   60 use constant F_MODULUS => 1; # modulus m
  4         9  
  4         239  
21 4     4   25 use constant NFIELDS => 2;
  4         32  
  4         313  
22              
23             # ----- class data -----
24              
25             BEGIN {
26 4     4   25 require Math::ModInt;
27 4         77 our @ISA = 'Math::ModInt';
28 4         2656 our $VERSION = '0.012';
29             }
30              
31             # ----- overridden methods -----
32              
33             sub _NEG {
34 7     7   381 my ($this) = @_;
35 7         15 return $this->_NEW(-$this->residue);
36             }
37              
38             sub _ADD {
39 33     33   49 my ($this, $that) = @_;
40 33         63 return $this->_NEW($this->residue + $that->residue);
41             }
42              
43             sub _SUB {
44 25     25   30 my ($this, $that) = @_;
45 25         36 return $this->_NEW($this->residue - $that->residue);
46             }
47              
48             sub _MUL {
49 41     41   68 my ($this, $that) = @_;
50 41         81 return $this->_NEW($this->residue * $that->residue);
51             }
52              
53             sub _DIV {
54 25     25   39 my ($this, $that) = @_;
55 25         38 my $i = $that->residue->copy->bmodinv($that->modulus);
56 25 100       4394 return $this->undefined if $i->is_nan;
57 14         73 return $this->_NEW($this->residue * $i);
58             }
59              
60             sub _POW {
61 71     71   106 my ($this, $exp) = @_;
62 71 100       122 if ($this->is_zero) {
63             # work around Math::BigInt bug rt.cpan.org #61543
64 12 100       1733 return $this->undefined if 0 > $exp;
65 8 100       20 return $this->_NEW(1) if 0 == $exp;
66 6         15 return $this;
67             }
68 59         7667 my $p = $this->residue->copy->bmodpow($exp, $this->modulus);
69 59 100       53694 return $this->undefined if $p->is_nan;
70 57         310 return $this->_NEW($p);
71             }
72              
73             sub _INV {
74 7     7   10 my ($this) = @_;
75 7         13 my $i = $this->residue->copy->bmodinv($this->modulus);
76 7 100       1311 return $this->undefined if $i->is_nan;
77 4         26 return $this->_NEW($i);
78             }
79              
80             sub _NEW {
81 301     301   9895 my ($this, $int, $modulus) = @_;
82 301         433 my $class = ref $this;
83 301 100       478 if ($class) {
84 289         427 $modulus = $this->modulus;
85             }
86             else {
87 12         19 $class = $this;
88             }
89 301         487 foreach my $arg ($int, $modulus) {
90 602 100 100     5364 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
91 90         186 $arg = Math::BigInt->new($arg);
92             }
93             }
94 301         877 return bless [$int % $modulus, $modulus], $class;
95             }
96              
97             sub _NEW2 {
98 3     3   6 my ($this, $int, $modulus) = @_;
99 3         5 my $class = ref $this;
100 3 100       8 if ($class) {
101 2         6 $modulus = $this->modulus;
102             }
103             else {
104 1         2 $class = $this;
105             }
106 3         7 foreach my $arg ($int, $modulus) {
107 6 100 100     178 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
108 2         5 $arg = Math::BigInt->new($arg);
109             }
110             }
111 3         7 my ($quotient, $remainder);
112 3         5 if (_ISSUE_CPAN_RT79060 && $int->is_neg) {
113             $remainder = $int % $modulus;
114             $quotient = ($int - $remainder) / $modulus;
115             }
116             else {
117 3         7 ($quotient, $remainder) = $int->copy->bdiv($modulus);
118             }
119 3         1127 return ($quotient, bless [$remainder, $modulus], $class);
120             }
121              
122             sub residue {
123 853     853 1 2045 my ($this) = @_;
124 853         1601 return $this->[F_RESIDUE];
125             }
126              
127             sub modulus {
128 1101     1101 1 8986 my ($this) = @_;
129 1101         1920 return $this->[F_MODULUS];
130             }
131              
132             1;
133              
134             __END__