File Coverage

lib/Crypt/Perl/BigInt.pm
Criterion Covered Total %
statement 49 56 87.5
branch 9 14 64.2
condition n/a
subroutine 12 14 85.7
pod 0 2 0.0
total 70 86 81.4


line stmt bran cond sub pod time code
1             package Crypt::Perl::BigInt;
2              
3 22     22   2781320 use strict;
  22         185  
  22         732  
4 22     22   150 use warnings;
  22         54  
  22         1242  
5              
6             # Even though Crypt::Perl intends to be pure Perl, there’s no reason
7             # not to use faster computation methods when they’re available.
8             #
9             #No FastCalc because of bugs shown in the following test runs:
10             #http://www.cpantesters.org/cpan/report/a03dce70-c698-11e6-a1ce-1a99c671d6e6
11             #http://www.cpantesters.org/cpan/report/0a3e797e-c693-11e6-8c46-2488c671d6e6
12              
13 22         49 use constant _LTM_IS_OK => eval {
14 22         10465 require CryptX;
15 22         53503 CryptX->VERSION('0.074');
16 22     22   159 };
  22         55  
17              
18 22         1277 use constant _TRY => join(
19             ',',
20             'GMP',
21             ( _LTM_IS_OK ? 'LTM' : () ),
22             qw( GMPz Pari BitVect ),
23 22     22   194 );
  22         61  
24              
25             # Sorted in descending order of observed speed:
26 22     22   35684 use Math::BigInt try => _TRY;
  22         815352  
  22         132  
27              
28             #To test pure Perl speed, comment out the above and enable:
29             #use Math::BigInt;
30              
31 22     22   162262 use parent -norequire => 'Math::BigInt';
  22         695  
  22         214  
32              
33             #There has been some trouble getting GMP and Pari to do from_bytes()
34             #and as_bytes(), so let’s check on those here.
35             BEGIN {
36 22 50   22   3558 if ( !eval { __PACKAGE__->fffrom_bytes('1234') } ) {
  22         599  
37 22         122 *from_bytes = \&_pp_from_bytes;
38             }
39              
40 22 50       83 if ( !eval { __PACKAGE__->new(1234)->aaas_bytes() } ) {
  22         173  
41 22         4084 *as_bytes = \&_pp_as_bytes;
42             }
43              
44             # Accommodate Math::BigInt::GMP 1.51 …
45 22 50       218 if ( !eval { __PACKAGE__->new(1234)->to_bin() } ) {
  22         114  
46 0         0 *to_bin = \&_pp_to_bin;
47             }
48 22 50       2885 if ( !eval { __PACKAGE__->new(1234)->to_hex() } ) {
  22         101  
49 0         0 *to_hex = \&_pp_to_hex;
50             }
51              
52 22         2565 $@ = q<>;
53             }
54              
55 22     22   10440 use Crypt::Perl::X ();
  22         76  
  22         7263  
56              
57             sub _pp_to_hex {
58 0     0   0 return substr( $_[0]->as_hex(), 2 );
59             }
60              
61             sub _pp_from_bytes {
62 3661     3661   453049 my $class = shift;
63              
64 3661         23464 return $class->from_hex( unpack 'H*', $_[0] );
65             }
66              
67             sub _pp_as_bytes {
68 7399     7399   28571 my ($self) = @_;
69              
70 7399 50       27296 die Crypt::Perl::X::create('Generic', "Negatives ($self) can’t convert to bytes!") if $self < 0;
71              
72 7399         1465103 my $hex = $self->as_hex();
73              
74             #Ensure that we have an even number of hex digits.
75 7399 100       225326 if (length($hex) % 2) {
76 2382         7398 substr($hex, 1, 1) = q<>; #just remove the “x” of “0x”
77             }
78             else {
79 5017         12964 substr($hex, 0, 2) = q<>; #remove “0x”
80             }
81              
82 7399         62845 return pack 'H*', $hex;
83             }
84              
85             sub _pp_to_bin {
86 0     0   0 my ($self) = @_;
87              
88 0         0 my $bin = unpack 'B*', $self->as_bytes();
89 0         0 $bin =~ s<\A0+><>;
90              
91 0         0 return $bin;
92             }
93              
94             sub bit_length {
95 2485     2485 0 10527 my ($self) = @_;
96              
97             #Probably faster than 1 + $self->copy()->blog(2) …
98 2485         11170 return( length($self->as_bin()) - 2 );
99             }
100              
101             sub test_bit {
102 370564     370564 0 747981 my ($self, $bit_from_least) = @_;
103              
104 370564         910259 my $bstr = substr( $self->as_bin(), 2 );
105              
106 370564 100       12735010 return 0 if $bit_from_least >= length($bstr);
107              
108 370563         1438408 return substr($bstr, -$bit_from_least - 1, 1);
109             }
110              
111             1;