File Coverage

blib/lib/Math/ModInt/BigInt.pm
Criterion Covered Total %
statement 81 81 100.0
branch 22 22 100.0
condition 4 6 66.6
subroutine 21 21 100.0
pod 2 2 100.0
total 130 132 98.4


line stmt bran cond sub pod time code
1             # Copyright (c) 2009-2015 Martin Becker. All rights reserved.
2             # This package is free software; you can redistribute it and/or modify it
3             # under the same terms as Perl itself.
4             #
5             # $Id: BigInt.pm 60 2015-05-18 08:47:12Z demetri $
6              
7             package Math::ModInt::BigInt;
8              
9 4     4   1422 use 5.006;
  4         9  
  4         170  
10 4     4   18 use strict;
  4         5  
  4         130  
11 4     4   18 use warnings;
  4         6  
  4         130  
12 4     4   18 use Carp qw(croak);
  4         4  
  4         244  
13 4     4   978 use Math::BigInt;
  4         18735  
  4         38  
14 4     4   14158 use constant _ISSUE_CPAN_RT79060 => -1 != Math::BigInt->new(-2) / 3;
  4         8  
  4         23  
15              
16             # ----- object definition -----
17              
18             # Math::ModInt::BigInt=ARRAY(...)
19              
20             # .......... index .......... # .......... value ..........
21 4     4   2021 use constant F_RESIDUE => 0; # residue r, 0 <= r < m
  4         8  
  4         205  
22 4     4   21 use constant F_MODULUS => 1; # modulus m
  4         5  
  4         158  
23 4     4   18 use constant NFIELDS => 2;
  4         7  
  4         294  
24              
25             # ----- class data -----
26              
27             BEGIN {
28 4     4   19 require Math::ModInt;
29 4         48 our @ISA = 'Math::ModInt';
30 4         2683 our $VERSION = '0.011';
31             }
32              
33             # ----- overridden methods -----
34              
35             sub _NEG {
36 7     7   1117 my ($this) = @_;
37 7         17 return $this->_NEW(-$this->residue);
38             }
39              
40             sub _ADD {
41 33     33   39 my ($this, $that) = @_;
42 33         55 return $this->_NEW($this->residue + $that->residue);
43             }
44              
45             sub _SUB {
46 25     25   30 my ($this, $that) = @_;
47 25         36 return $this->_NEW($this->residue - $that->residue);
48             }
49              
50             sub _MUL {
51 41     41   45 my ($this, $that) = @_;
52 41         60 return $this->_NEW($this->residue * $that->residue);
53             }
54              
55             sub _DIV {
56 25     25   37 my ($this, $that) = @_;
57 25         35 my $i = $that->residue->copy->bmodinv($that->modulus);
58 25 100       3774 return $this->undefined if $i->is_nan;
59 14         78 return $this->_NEW($this->residue * $i);
60             }
61              
62             sub _POW {
63 71     71   92 my ($this, $exp) = @_;
64 71 100       153 if ($this->is_zero) {
65             # work around Math::BigInt bug rt.cpan.org #61543
66 12 100       1632 return $this->undefined if 0 > $exp;
67 8 100       21 return $this->_NEW(1) if 0 == $exp;
68 6         17 return $this;
69             }
70 59         7252 my $p = $this->residue->copy->bmodpow($exp, $this->modulus);
71 59 100       37069 return $this->undefined if $p->is_nan;
72 57         428 return $this->_NEW($p);
73             }
74              
75             sub _INV {
76 7     7   8 my ($this) = @_;
77 7         14 my $i = $this->residue->copy->bmodinv($this->modulus);
78 7 100       1215 return $this->undefined if $i->is_nan;
79 4         28 return $this->_NEW($i);
80             }
81              
82             sub _NEW {
83 301     301   9185 my ($this, $int, $modulus) = @_;
84 301         351 my $class = ref $this;
85 301 100       541 if ($class) {
86 289         446 $modulus = $this->modulus;
87             }
88             else {
89 12         17 $class = $this;
90             }
91 301         395 foreach my $arg ($int, $modulus) {
92 602 100 66     5481 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
93 90         228 $arg = Math::BigInt->new($arg);
94             }
95             }
96 301         1068 return bless [$int % $modulus, $modulus], $class;
97             }
98              
99             sub _NEW2 {
100 2     2   4 my ($this, $int, $modulus) = @_;
101 2         5 my $class = ref $this;
102 2 100       5 if ($class) {
103 1         5 $modulus = $this->modulus;
104             }
105             else {
106 1         2 $class = $this;
107             }
108 2         5 foreach my $arg ($int, $modulus) {
109 4 100 66     46 if (!ref($arg) || !$arg->isa('Math::BigInt')) {
110 1         3 $arg = Math::BigInt->new($arg);
111             }
112             }
113 2         4 my ($quotient, $remainder);
114 2 100       10 if (_ISSUE_CPAN_RT79060 && $int->is_neg) {
115 1         8 $remainder = $int % $modulus;
116 1         89 $quotient = ($int - $remainder) / $modulus;
117             }
118             else {
119 1         13 ($quotient, $remainder) = $int->copy->bdiv($modulus);
120             }
121 2         385 return ($quotient, bless [$remainder, $modulus], $class);
122             }
123              
124             sub residue {
125 852     852 1 2381 my ($this) = @_;
126 852         1903 return $this->[F_RESIDUE];
127             }
128              
129             sub modulus {
130 1099     1099 1 8785 my ($this) = @_;
131 1099         2218 return $this->[F_MODULUS];
132             }
133              
134             1;
135              
136             __END__