File Coverage

blib/lib/Math/Primality/BigPolynomial.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Math::Primality::BigPolynomial;
2             {
3             $Math::Primality::BigPolynomial::VERSION = '0.08';
4             }
5              
6 1     1   1555 use strict;
  1         1  
  1         27  
7 1     1   5 use warnings;
  1         1  
  1         21  
8 1     1   347 use Math::GMPz qw/:mpz/;
  0            
  0            
9              
10             # ABSTRACT: Big Polynomials
11              
12              
13              
14             sub new {
15             my $self = {};
16             my $class = shift;
17             my $construction_junk = shift;
18             if ($construction_junk) {
19             my $type = ref $construction_junk;
20             if ( $type eq 'ARRAY' ) {
21             $self->{COEF} = $construction_junk;
22             } elsif ( $type eq 'Math::Primality::BigPolynomial') {
23             foreach my $coef (@{$construction_junk->{COEF}}) {
24             my $temp = Rmpz_init_set($coef);
25             push @{$self->{COEF}}, $temp;
26             }
27             } else {
28             my $a = [];
29             for ( my $i = 0 ; $i < $construction_junk ; $i++ ) {
30             push @$a, Math::GMPz->new(0);
31             }
32             $self->{COEF} = $a;
33             }
34             }
35             else {
36             $self->{COEF} = [ Math::GMPz->new(0) ];
37             }
38             bless( $self, $class );
39             return $self;
40             }
41              
42             sub coef {
43             my $self = shift;
44             if (@_) { @{ $self->{COEF} } = @_ }
45             return @{ $self->{COEF} };
46             }
47              
48             sub degree {
49             my $self = shift;
50             return (scalar @{$self->{COEF}} - 1);
51             }
52              
53             sub getCoef {
54             my $self = shift;
55             my $i = shift;
56             if ( $i > $self->degree() ) {
57             return Math::GMPz->new(0);
58             }
59             return undef if $i < 0;
60             return $self->{COEF}->[$i];
61             }
62              
63             sub isEqual {
64             my $self = shift;
65             my $other_polynomial = shift;
66             if ( $self->degree() != $other_polynomial->degree() ) {
67             return 0;
68             }
69             for ( my $i = 0 ; $i < $self->degree() ; $i++ ) {
70             if ( $self->getCoef($i) != $other_polynomial->getCoef($i) ) {
71             return 0;
72             }
73             }
74             return 1;
75             }
76              
77             sub setCoef {
78             my $self = shift;
79             my $new_coef = shift;
80             my $index = shift;
81             if ( $index < 0 ) {
82             die "coef is less than 0";
83             }
84              
85             if ( $index > $self->degree() ) {
86             for ( my $j = $self->degree() + 1 ; $j < $index ; $j++ ) {
87             push @{ $self->{COEF} }, Math::GMPz->new(0);
88             }
89             $self->{COEF}->[$index] = $new_coef;
90             $self->degree($index);
91             }
92             else {
93             $self->{COEF}->[$index] = $new_coef;
94             }
95             }
96              
97             sub compact {
98             my $self = shift;
99             my $i = 0;
100             LOOP: for ( $i = $self->degree(); $i > 0 ; $i-- ) {
101             if ( Math::GMPz::Rmpz_cmp_ui( $self->getCoef($i), 0 ) != 0 ) {
102             last LOOP;
103             }
104             pop @{ $self->{COEF} };
105             }
106             if ( $i != $self->degree() ) {
107             $self->degree( $i );
108             }
109             }
110              
111             sub clear {
112             my $self = shift;
113             $self->{COEF} = [ Math::GMPz->new(0) ];
114             }
115              
116             sub mpz_poly_mod_mult {
117             my ( $rop, $copy_x, $copy_y, $mod, $polymod ) = @_;
118             my $x = Math::Primality::BigPolynomial->new($copy_x);
119             my $y = Math::Primality::BigPolynomial->new($copy_y);
120              
121             die "mpz_poly_mod_mult: polymod must be defined!" unless $polymod;
122              
123             $rop->clear();
124              
125             my $xdeg = ref $x ? $x->degree() : 0;
126             my $ydeg = ref $y ? $y->degree() : 0;
127             my $maxdeg = $xdeg < $ydeg ? $ydeg : $xdeg;
128              
129             LOOP: for ( my $i = 0 ; $i < $polymod ; $i++ ) {
130             my $sum = Math::GMPz->new(0);
131             my $temp = Math::GMPz->new(0);
132             for ( my $j = 0 ; $j <= $i ; $j++ ) {
133             Rmpz_add($temp, $y->getCoef( $i - $j ),
134             $y->getCoef( $i + $polymod - $j ) );
135             Rmpz_mul( $temp, $x->getCoef($j), $temp );
136             Rmpz_add( $sum, $sum, $temp );
137             }
138              
139             for ( my $j = 0 ; $j < ( $i + $polymod ) ; $j++ ) {
140             Rmpz_mul( $temp, $x->getCoef($j),
141             $y->getCoef( $i + $polymod - $j ) );
142             Rmpz_add( $sum, $sum, $temp );
143             }
144              
145             Rmpz_mod( $temp, $sum, $mod );
146             $rop->setCoef( $temp, $i );
147              
148             if ( $i > $maxdeg && Rmpz_cmp_ui( $sum, 0 ) == 0 ) {
149             last LOOP;
150             }
151             }
152              
153             $rop->compact();
154             }
155              
156             sub mpz_poly_mod_power {
157             my ( $rop, $x, $power, $mult_mod, $poly_mod ) = @_;
158              
159             die "mpz_poly_mod_power: polymod must be defined!" unless $poly_mod;
160              
161             $rop->clear();
162             $rop->setCoef( Math::GMPz->new(1), 0 );
163              
164             my $i = Rmpz_sizeinbase( $power, 2 );
165              
166             LOOP: for ( ; $i >= 0 ; $i-- ) {
167             mpz_poly_mod_mult( $rop, $rop, $rop, $mult_mod, $poly_mod );
168              
169             if ( Rmpz_tstbit( $power, $i ) ) {
170             mpz_poly_mod_mult( $rop, $rop, $x, $mult_mod, $poly_mod );
171             }
172              
173             if ( $i == 0 ) {
174             last LOOP;
175             }
176             }
177              
178             $rop->compact();
179             }
180              
181             1;
182              
183             __END__