File Coverage

blib/lib/Math/BigInt/GMPz.pm
Criterion Covered Total %
statement 12 14 85.7
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 17 19 89.4


line stmt bran cond sub pod time code
1             package Math::BigInt::GMPz;
2              
3 7     7   313382 use 5.006002;
  7         21  
4 7     7   23 use strict;
  7         11  
  7         810  
5 7     7   24 use warnings;
  7         8  
  7         191  
6              
7 7     7   3272 use Math::BigInt::Lib 1.999801;
  7         32609  
  7         29  
8              
9             our @ISA = qw< Math::BigInt::Lib >;
10              
11             our $VERSION = '0.0001';
12              
13 7     7   1571 use Math::GMPz qw< :mpz >;
  0            
  0            
14              
15             sub import { }
16              
17             my $zero = Rmpz_init(); # for _is_zero
18             my $one = Rmpz_init_set_str("1", 10); # for _is_one, _inc, and _dec
19             my $two = Rmpz_init_set_str("2", 10); # for _is_two
20             my $ten = Rmpz_init_set_str("10", 10); # for _is_ten, _digit
21              
22             sub api_version { 2; }
23              
24             sub _new {
25             Rmpz_init_set_str($_[1], 10);
26             }
27              
28             sub _zero {
29             Rmpz_init();
30             }
31              
32             sub _one {
33             Rmpz_init_set_str("1", 10);
34             }
35              
36             sub _two {
37             Rmpz_init_set_str("2", 10);
38             }
39              
40             sub _ten {
41             Rmpz_init_set_str("10", 10);
42             }
43              
44             sub _from_bin {
45             my $str = $_[1];
46             $str =~ s/^0[Bb]//; # remove leading '0b'
47             Rmpz_init_set_str($str, 2);
48             }
49              
50             sub _from_oct {
51             Rmpz_init_set_str($_[1], 8);
52             }
53              
54             #sub _from_dec {
55             # Rmpz_init_set_str($_[1], 10);
56             #}
57              
58             sub _from_hex {
59             my $str = $_[1];
60             $str =~ s/^0[Xx]//; # remove leading '0x'
61             Rmpz_init_set_str($str, 16);
62             }
63              
64             sub _from_bytes {
65             my $rop = Rmpz_init();
66             my $bstr = $_[1];
67             my $len = length $bstr;
68             my ($order, $size, $endian, $nails) = (1, 1, 0, 0);
69             Rmpz_import($rop, $len, $order, $size, $endian, $nails, $bstr);
70             return $rop;
71             }
72              
73             sub _1ex {
74             Rmpz_init_set_str("1" . ("0" x $_[1]));
75             }
76              
77             sub _add {
78             Rmpz_add($_[1], $_[1], $_[2]);
79             return $_[1];
80             }
81              
82             sub _mul {
83             Rmpz_mul($_[1], $_[1], $_[2]);
84             return $_[1];
85             }
86              
87             sub _div {
88             if (wantarray) {
89             my $r = Rmpz_init();
90             Rmpz_fdiv_qr($_[1], $r, $_[1], $_[2]);
91             return ($_[1], $r);
92             }
93             Rmpz_fdiv_q($_[1], $_[1], $_[2]);
94             return $_[1];
95             }
96              
97             sub _sub {
98             if ($_[3]) {
99             $_[2] = $_[1] - $_[2];
100             return $_[2];
101             }
102             Rmpz_sub($_[1], $_[1], $_[2]);
103             return $_[1];
104             }
105              
106             sub _dec {
107             Rmpz_sub_ui($_[1], $_[1], 1);
108             return $_[1];
109             }
110              
111             sub _inc {
112             Rmpz_add_ui($_[1], $_[1], 1);
113             return $_[1];
114             }
115              
116             sub _mod {
117             Rmpz_fdiv_r($_[1], $_[1], $_[2]);
118             return $_[1];
119             };
120              
121             sub _sqrt {
122             Rmpz_sqrt($_[1], $_[1]);
123             return $_[1];
124             }
125              
126             sub _root {
127             Rmpz_root($_[1], $_[1], $_[2]);
128             return $_[1];
129             }
130              
131             sub _fac {
132             Rmpz_fac_ui($_[1], $_[1]);
133             return $_[1];
134             }
135              
136             sub _dfac {
137             Rmpz_2fac_ui($_[1], $_[1]);
138             return $_[1];
139             }
140              
141             sub _pow {
142             Rmpz_pow_ui($_[1], $_[1], $_[2]);
143             return $_[1];
144             }
145              
146             sub _modinv {
147             my $bool = Rmpz_invert($_[1], $_[1], $_[2]);
148             return $bool ? ($_[1], '+') : (undef, undef);
149             }
150              
151             sub _modpow {
152             Rmpz_powm($_[1], $_[1], $_[2], $_[3]);
153             return $_[1];
154             }
155              
156             sub _rsft {
157             # (X, Y, N) = @_; means X >> Y in base N
158             if ($_[3] == 2) {
159             Rmpz_div_2exp($_[1], $_[1], $_[2]);
160             } else {
161             # N must be an unsigned integer
162             my $n = Rmpz_init_set_ui($_[3]);
163             # Y must be a Math::GMPz
164             my $y = Rmpz_get_ui($_[2]);
165             Rmpz_pow_ui($n, $n, $y);
166             Rmpz_div($_[1], $_[1], $n);
167             }
168             return $_[1];
169             }
170              
171             sub _lsft {
172             # (X, Y, N) = @_; means X << Y in base N (= X * N^Y)
173             if ($_[3] == 2) {
174             Rmpz_mul_2exp($_[1], $_[1], $_[2]);
175             } else {
176             # N must be an unsigned integer
177             my $n = Rmpz_init_set_ui($_[3]);
178             # Y must be a Math::GMPz
179             my $y = Rmpz_get_ui($_[2]);
180             #$_[1] = $_[1] * $n ** $y;
181             Rmpz_pow_ui($n, $n, $y);
182             Rmpz_mul($_[1], $_[1], $n);
183             }
184             return $_[1];
185             }
186              
187             #sub _log_int { }
188              
189             sub _gcd {
190             Rmpz_gcd($_[1], $_[1], $_[2]);
191             return $_[1];
192             }
193              
194             sub _lcm {
195             Rmpz_lcm($_[1], $_[1], $_[2]);
196             return $_[1];
197             }
198              
199             sub _and {
200             Rmpz_and($_[1], $_[1], $_[2]);
201             return $_[1];
202             }
203              
204             sub _or {
205             Rmpz_ior($_[1], $_[1], $_[2]);
206             return $_[1];
207             }
208              
209             sub _xor {
210             Rmpz_xor($_[1], $_[1], $_[2]);
211             return $_[1];
212             }
213              
214             sub _is_zero {
215             !Rmpz_cmp($_[1], $zero);
216             }
217              
218             sub _is_one {
219             !Rmpz_cmp($_[1], $one);
220             }
221              
222             sub _is_two {
223             !Rmpz_cmp($_[1], $two);
224             }
225              
226             sub _is_ten {
227             !Rmpz_cmp($_[1], $ten);
228             }
229              
230             sub _is_even {
231             Rmpz_even_p($_[1]);
232             }
233              
234             sub _is_odd {
235             Rmpz_odd_p($_[1]);
236             }
237              
238             sub _acmp {
239             Rmpz_cmp($_[1], $_[2]);
240             }
241              
242             sub _str {
243             Rmpz_get_str($_[1], 10);
244             }
245              
246             sub _as_bin {
247             '0b' . Rmpz_get_str($_[1], 2);
248             }
249              
250             sub _as_oct {
251             '0' . Rmpz_get_str($_[1], 8);
252             }
253              
254             sub _as_hex {
255             '0x' . Rmpz_get_str($_[1], 16);
256             }
257              
258             sub _to_bin {
259             Rmpz_get_str($_[1], 2);
260             }
261              
262             sub _to_oct {
263             Rmpz_get_str($_[1], 8);
264             }
265              
266             #sub _to_dec {
267             # Rmpz_get_str($_[1], 10);
268             #}
269              
270             sub _to_hex {
271             Rmpz_get_str($_[1], 16);
272             }
273              
274             sub _to_bytes {
275             my ($class, $x) = @_;
276             return "\x00" if $class -> _is_zero($x);
277             my ($order, $size, $endian, $nails) = (1, 1, 0, 0);
278             Rmpz_export($order, $size, $endian, $nails, $x);
279             }
280              
281             *_as_bytes = \&_to_bytes;
282              
283             sub _num {
284             0 + Rmpz_get_str($_[1], 10);
285             }
286              
287             sub _copy { Rmpz_init_set($_[1]); }
288              
289             sub _len {
290             length Rmpz_get_str($_[1], 10);
291             }
292              
293             sub _zeros {
294             return 0 unless Rmpz_cmp($_[1], $zero); # 0 has no trailing zeros
295             my $str = Rmpz_get_str($_[1], 10);
296             $str =~ /(0*)\z/;
297             return length($1);
298             }
299              
300             sub _digit {
301             substr(Rmpz_get_str($_[1], 10), -($_[2]+1), 1);
302             #if ($_[2] >= 0) {
303             # return( ($_[1] / (10 ** $_[2])) % 10);
304             #} else {
305             # substr(Rmpz_get_str($_[1], 10), -($_[2]+1), 1);
306             #}
307             }
308              
309             sub _check {
310             my ($class, $x) = @_;
311             return "Undefined" unless defined $x;
312             return "$x is not a reference to Math::GMPz"
313             unless ref($x) eq 'Math::GMPz';
314             return 0;
315             }
316              
317             sub _nok {
318             my ($class, $n, $k) = @_;
319              
320             # If k > n/2, use the fact that binomial(n, k) = binomial(n, n-k). To avoid
321             # division, don't test k > n/2, but rather 2*k > n.
322              
323             {
324             my $twok = Rmpz_init(); #
325             Rmpz_mul_2exp($twok, $k, 1); # $twok = 2 * $k
326             if (Rmpz_cmp($twok, $n) > 0) { # if 2*k > n
327             $k = Rmpz_init_set($k); # copy k
328             Rmpz_sub($k, $n, $k); # k = n - k
329             }
330             }
331              
332             Rmpz_bin_ui($n, $n, $k);
333             return $n;
334             }
335              
336             # XXX TODO: calc len in base 2 then appr. in base 10
337             sub _alen {
338             Rmpz_sizeinbase($_[1], 10);
339             }
340              
341             # _set() - set an already existing object to the given scalar value
342              
343             sub _set {
344             Rmpz_set($_[1], $_[2]);
345             return $_[1];
346             }
347              
348             1;
349              
350             __END__