File Coverage

GMP.xs
Criterion Covered Total %
statement 168 182 92.3
branch 30 46 65.2
condition n/a
subroutine n/a
pod n/a
total 198 228 86.8


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include "gmp.h"
5              
6             /*
7             Math::GMP, a Perl module for high-speed arbitrary size integer
8             calculations
9             Copyright (C) 2000 James H. Turner
10              
11             This library is free software; you can redistribute it and/or
12             modify it under the terms of the GNU Library General Public
13             License as published by the Free Software Foundation; either
14             version 2 of the License, or (at your option) any later version.
15              
16             This library is distributed in the hope that it will be useful,
17             but WITHOUT ANY WARRANTY; without even the implied warranty of
18             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19             Library General Public License for more details.
20              
21             You should have received a copy of the GNU Library General Public
22             License along with this library; if not, write to the Free
23             Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24              
25             You can contact the author at chip@redhat.com, chipt@cpan.org, or by mail:
26              
27             Chip Turner
28             Red Hat Inc.
29             2600 Meridian Park Blvd
30             Durham, NC 27713
31             */
32              
33             #define SWAP_GMP if (swap) { mpz_t* t = m; m = n; n = t; }
34              
35             /*
36             * mpz_rootrem() has bug with negative first argument before 5.1.0
37             */
38 6           static int need_rootrem_workaround(mpz_t* m, unsigned long n) {
39             /* workaround only valid for n odd (n even should be an error) */
40 6 100         if ((n & 1) == 0)
41 2           return 0;
42              
43             /* workaround only relevant for m negative */
44 4 100         if (mpz_sgn(*m) >= 0)
45 2           return 0;
46              
47             /* workaround only needed for gmp_version < 5.1.0 */
48 2 50         if ((gmp_version[0] && gmp_version[1] != '.') /* >= 10.0.0 */
    50          
49 2 50         || (gmp_version[0] > '5') /* >= 6.0.0 */
50 0 0         || (gmp_version[0] == '5' && gmp_version[2] != '0') /* >= 5.1.0 */
    0          
51             )
52 2           return 0;
53              
54 0           return 1;
55             }
56              
57             #if 0
58             static double
59             constant(char *name, int arg)
60             {
61             errno = 0;
62             switch (*name) {
63             }
64             errno = EINVAL;
65             return 0;
66              
67             not_there:
68             errno = ENOENT;
69             return 0;
70             }
71             #endif
72              
73             mpz_t *
74 306           pv2gmp(char* pv)
75             {
76             mpz_t* z;
77             SV* sv;
78              
79 306           z = malloc (sizeof(mpz_t));
80 306           mpz_init_set_str(*z, pv, 0);
81 306           sv = sv_newmortal();
82 306           sv_setref_pv(sv, "Math::GMP", (void*)z);
83 306           return z;
84             }
85              
86             mpz_t *
87 5732           sv2gmp(SV* sv)
88             {
89             char* pv;
90              
91             /* MAYCHANGE in perlguts.pod - bug in perl */
92 5732 50         if (SvGMAGICAL(sv)) mg_get(sv);
93              
94 5732 100         if (SvROK(sv) && sv_derived_from(sv, "Math::GMP")) {
    50          
95 5426 50         IV tmp = SvIV((SV*)SvRV(sv));
96 5426           return (mpz_t *)tmp;
97             }
98              
99 306 100         pv = SvPV_nolen(sv);
100 306           return pv2gmp(pv);
101             }
102              
103              
104             MODULE = Math::GMP PACKAGE = Math::GMP
105             PROTOTYPES: ENABLE
106              
107             mpz_t *
108             new_from_scalar(s)
109             char * s
110              
111             CODE:
112 1636           RETVAL = malloc (sizeof(mpz_t));
113 1636           mpz_init_set_str(*RETVAL, s, 0);
114             OUTPUT:
115             RETVAL
116              
117             mpz_t *
118             new_from_scalar_with_base(s, b)
119             char * s
120             int b
121              
122             CODE:
123 2           RETVAL = malloc (sizeof(mpz_t));
124 2           mpz_init_set_str(*RETVAL, s, b);
125             OUTPUT:
126             RETVAL
127              
128             void
129             destroy(n)
130             mpz_t *n
131              
132             CODE:
133 2880           mpz_clear(*n);
134 2880           free(n);
135              
136             SV *
137             _gmp_build_version()
138             CODE:
139 0           char buf[] = STRINGIFY(__GNU_MP_VERSION)
140             "." STRINGIFY(__GNU_MP_VERSION_MINOR)
141             "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL);
142 0           RETVAL = newSV(6);
143 0           scan_vstring(buf, buf + sizeof(buf), RETVAL);
144             OUTPUT:
145             RETVAL
146              
147             SV *
148             _gmp_lib_version()
149             CODE:
150 0           const char* v = gmp_version;
151 0           RETVAL = newSV(6);
152 0           scan_vstring(v, v + strlen(v), RETVAL);
153             OUTPUT:
154             RETVAL
155              
156             SV *
157             stringify(n)
158             mpz_t * n
159              
160             PREINIT:
161             int len;
162              
163             CODE:
164 845           len = mpz_sizeinbase(*n, 10);
165             {
166             char *buf;
167 845           buf = malloc(len + 2);
168 845           mpz_get_str(buf, 10, *n);
169 845           RETVAL = newSVpv(buf, strlen(buf));
170 845           free(buf);
171             }
172             OUTPUT:
173             RETVAL
174              
175              
176             SV *
177             get_str_gmp(n, b)
178             mpz_t * n
179             int b
180              
181             PREINIT:
182             int len;
183              
184             CODE:
185 1           len = mpz_sizeinbase(*n, b);
186             {
187             char *buf;
188 1           buf = malloc(len + 2);
189 1           mpz_get_str(buf, b, *n);
190 1           RETVAL = newSVpv(buf, strlen(buf));
191 1           free(buf);
192             }
193             OUTPUT:
194             RETVAL
195              
196             int
197             sizeinbase_gmp(n, b)
198             mpz_t * n
199             int b
200              
201             CODE:
202 7           RETVAL = mpz_sizeinbase(*n, b);
203             OUTPUT:
204             RETVAL
205              
206             unsigned long
207             uintify(n)
208             mpz_t * n
209              
210             CODE:
211 67           RETVAL = mpz_get_ui(*n);
212             OUTPUT:
213             RETVAL
214              
215             void
216             add_ui_gmp(n, v)
217             mpz_t * n
218             unsigned long v
219              
220             CODE:
221 7           mpz_add_ui(*n, *n, v);
222              
223              
224             long
225             intify(n)
226             mpz_t * n
227              
228             CODE:
229 5           RETVAL = mpz_get_si(*n);
230             OUTPUT:
231             RETVAL
232              
233             mpz_t *
234             mul_2exp_gmp(n, e)
235             mpz_t * n
236             unsigned long e
237              
238             CODE:
239 9           RETVAL = malloc (sizeof(mpz_t));
240 9           mpz_init(*RETVAL);
241 9           mpz_mul_2exp(*RETVAL, *n, e);
242             OUTPUT:
243             RETVAL
244              
245             mpz_t *
246             div_2exp_gmp(n, e)
247             mpz_t * n
248             unsigned long e
249              
250             CODE:
251 5           RETVAL = malloc (sizeof(mpz_t));
252 5           mpz_init(*RETVAL);
253 5           mpz_div_2exp(*RETVAL, *n, e);
254             OUTPUT:
255             RETVAL
256              
257              
258             mpz_t *
259             powm_gmp(n, exp, mod)
260             mpz_t * n
261             mpz_t * exp
262             mpz_t * mod
263              
264             CODE:
265 7           RETVAL = malloc (sizeof(mpz_t));
266 7           mpz_init(*RETVAL);
267 7           mpz_powm(*RETVAL, *n, *exp, *mod);
268             OUTPUT:
269             RETVAL
270              
271              
272             mpz_t *
273             mmod_gmp(a, b)
274             mpz_t * a
275             mpz_t * b
276              
277             CODE:
278 5           RETVAL = malloc (sizeof(mpz_t));
279 5           mpz_init(*RETVAL);
280 5           mpz_mmod(*RETVAL, *a, *b);
281             OUTPUT:
282             RETVAL
283              
284              
285             mpz_t *
286             mod_2exp_gmp(in, cnt)
287             mpz_t * in
288             unsigned long cnt
289              
290             CODE:
291 5           RETVAL = malloc (sizeof(mpz_t));
292 5           mpz_init(*RETVAL);
293 5           mpz_mod_2exp(*RETVAL, *in, cnt);
294             OUTPUT:
295             RETVAL
296              
297              
298             mpz_t *
299             op_add(m,n,swap)
300             mpz_t * m
301             mpz_t * n
302             bool swap
303              
304             CODE:
305 73           RETVAL = malloc (sizeof(mpz_t));
306 73           mpz_init(*RETVAL);
307 73           mpz_add(*RETVAL, *m, *n);
308             OUTPUT:
309             RETVAL
310              
311              
312             mpz_t *
313             op_sub(m,n,swap)
314             mpz_t * m
315             mpz_t * n
316             bool swap
317              
318             CODE:
319 72 100         SWAP_GMP
320 72           RETVAL = malloc (sizeof(mpz_t));
321 72           mpz_init(*RETVAL);
322 72           mpz_sub(*RETVAL, *m, *n);
323             OUTPUT:
324             RETVAL
325              
326              
327             mpz_t *
328             op_mul(m,n,swap)
329             mpz_t * m
330             mpz_t * n
331             bool swap
332              
333             CODE:
334 63           RETVAL = malloc (sizeof(mpz_t));
335 63           mpz_init(*RETVAL);
336 63           mpz_mul(*RETVAL, *m, *n);
337             OUTPUT:
338             RETVAL
339              
340              
341             mpz_t *
342             bmulf(n,d)
343             mpz_t * n
344             double d
345              
346             PREINIT:
347             mpf_t nf, df;
348             mp_bitcnt_t prec;
349             CODE:
350             /*
351             Multiply (mpz_t) n by (double) d returning an (mpz_t) result.
352             Uses GMP floats with maximum needed precision.
353             */
354 46           prec = mpf_get_default_prec();
355 46           mpf_set_default_prec(mpz_sizeinbase(*n, 2) + 8 * sizeof(double));
356              
357 46           RETVAL = malloc (sizeof(mpz_t));
358 46           mpz_init(*RETVAL);
359 46           mpf_init(nf);
360 46           mpf_init(df);
361              
362 46           mpf_set_z(nf, *n);
363 46           mpf_set_d(df, d);
364 46           mpf_mul(nf, nf, df);
365 46           mpz_set_f(*RETVAL, nf);
366 46           mpf_clear(nf);
367 46           mpf_clear(df);
368             /* restore default */
369 46           mpf_set_default_prec(prec);
370             OUTPUT:
371             RETVAL
372              
373              
374             mpz_t *
375             op_div(m,n,swap)
376             mpz_t * m
377             mpz_t * n
378             bool swap
379              
380             CODE:
381 64 100         SWAP_GMP
382 64           RETVAL = malloc (sizeof(mpz_t));
383 64           mpz_init(*RETVAL);
384 64           mpz_div(*RETVAL, *m, *n);
385             OUTPUT:
386             RETVAL
387              
388              
389             void
390             bdiv(m,n)
391             mpz_t * m
392             mpz_t * n
393              
394             PREINIT:
395             mpz_t * quo;
396             mpz_t * rem;
397             PPCODE:
398 129           quo = malloc (sizeof(mpz_t));
399 129           rem = malloc (sizeof(mpz_t));
400 129           mpz_init(*quo);
401 129           mpz_init(*rem);
402 129           mpz_tdiv_qr(*quo, *rem, *m, *n);
403 129 50         EXTEND(SP, 2);
404 129           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)quo));
405 129           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)rem));
406              
407              
408              
409             mpz_t *
410             op_mod(m,n,swap)
411             mpz_t * m
412             mpz_t * n
413             bool swap
414              
415             CODE:
416 65 100         SWAP_GMP
417 65           RETVAL = malloc (sizeof(mpz_t));
418 65           mpz_init(*RETVAL);
419 65           mpz_mod(*RETVAL, *m, *n);
420             OUTPUT:
421             RETVAL
422              
423             mpz_t *
424             bmodinv(m,n)
425             mpz_t * m
426             mpz_t * n
427              
428             CODE:
429 11           RETVAL = malloc (sizeof(mpz_t));
430 11           mpz_init(*RETVAL);
431 11           mpz_invert(*RETVAL, *m, *n);
432             OUTPUT:
433             RETVAL
434              
435              
436             int
437             op_spaceship(m,n,swap)
438             mpz_t * m
439             mpz_t * n
440             bool swap
441              
442             PREINIT:
443             int i;
444             CODE:
445 109           i = mpz_cmp(*m, *n);
446 109 100         if (swap) {
447 4           i = -i;
448             }
449 109 100         RETVAL = (i < 0) ? -1 : (i > 0) ? 1 : 0;
450             OUTPUT:
451             RETVAL
452              
453             int
454             op_eq(m,n,swap)
455             mpz_t* m
456             mpz_t* n
457             bool swap
458              
459             PREINIT:
460             int i;
461             CODE:
462 0           i = mpz_cmp(*m, *n);
463 0           RETVAL = (i == 0) ? 1 : 0;
464             OUTPUT:
465             RETVAL
466              
467             int
468             legendre(m, n)
469             mpz_t * m
470             mpz_t * n
471              
472             CODE:
473 1           RETVAL = mpz_legendre(*m, *n);
474             OUTPUT:
475             RETVAL
476              
477             int
478             jacobi(m, n)
479             mpz_t * m
480             mpz_t * n
481              
482             CODE:
483 119           RETVAL = mpz_jacobi(*m, *n);
484             OUTPUT:
485             RETVAL
486              
487             int
488             probab_prime(m, reps)
489             mpz_t * m
490             int reps
491              
492             CODE:
493 25           RETVAL = mpz_probab_prime_p(*m, reps);
494             OUTPUT:
495             RETVAL
496              
497             mpz_t *
498             op_pow(m,n)
499             mpz_t * m
500             long n
501              
502             CODE:
503 2           RETVAL = malloc (sizeof(mpz_t));
504 2           mpz_init(*RETVAL);
505             /* fprintf(stderr, "n is %ld\n", n);*/
506 2           mpz_pow_ui(*RETVAL, *m, n);
507             OUTPUT:
508             RETVAL
509              
510              
511             mpz_t *
512             bgcd(m,n)
513             mpz_t * m
514             mpz_t * n
515              
516             CODE:
517 71           RETVAL = malloc (sizeof(mpz_t));
518 71           mpz_init(*RETVAL);
519 71           mpz_gcd(*RETVAL, *m, *n);
520             OUTPUT:
521             RETVAL
522              
523              
524             mpz_t *
525             blcm(m,n)
526             mpz_t * m
527             mpz_t * n
528              
529             CODE:
530 41           RETVAL = malloc (sizeof(mpz_t));
531 41           mpz_init(*RETVAL);
532 41           mpz_lcm(*RETVAL, *m, *n);
533             OUTPUT:
534             RETVAL
535              
536              
537             mpz_t *
538             fibonacci(n)
539             long n
540              
541             CODE:
542 19           RETVAL = malloc (sizeof(mpz_t));
543 19           mpz_init(*RETVAL);
544 19           mpz_fib_ui(*RETVAL, n);
545             OUTPUT:
546             RETVAL
547              
548              
549             mpz_t *
550             band(m,n, ...)
551             mpz_t * m
552             mpz_t * n
553              
554             CODE:
555 7           RETVAL = malloc (sizeof(mpz_t));
556 7           mpz_init(*RETVAL);
557 7           mpz_and(*RETVAL, *m, *n);
558             OUTPUT:
559             RETVAL
560              
561             mpz_t *
562             bxor(m,n, ...)
563             mpz_t * m
564             mpz_t * n
565              
566             CODE:
567 7           RETVAL = malloc (sizeof(mpz_t));
568 7           mpz_init(*RETVAL);
569 7           mpz_xor(*RETVAL, *m, *n);
570             OUTPUT:
571             RETVAL
572              
573             mpz_t *
574             bior(m,n, ...)
575             mpz_t * m
576             mpz_t * n
577              
578             CODE:
579 7           RETVAL = malloc (sizeof(mpz_t));
580 7           mpz_init(*RETVAL);
581 7           mpz_ior(*RETVAL, *m, *n);
582             OUTPUT:
583             RETVAL
584              
585             mpz_t *
586             blshift(m,n,swap)
587             mpz_t * m
588             mpz_t * n
589             bool swap
590              
591             CODE:
592 9 50         SWAP_GMP
593 9           RETVAL = malloc (sizeof(mpz_t));
594 9           mpz_init(*RETVAL);
595 9           mpz_mul_2exp(*RETVAL, *m, mpz_get_ui(*n));
596             OUTPUT:
597             RETVAL
598              
599             mpz_t *
600             brshift(m,n,swap)
601             mpz_t * m
602             mpz_t * n
603             bool swap
604              
605             CODE:
606 13 50         SWAP_GMP
607 13           RETVAL = malloc (sizeof(mpz_t));
608 13           mpz_init(*RETVAL);
609 13           mpz_div_2exp(*RETVAL, *m, mpz_get_ui(*n));
610             OUTPUT:
611             RETVAL
612              
613             mpz_t *
614             bfac(n)
615             long n
616              
617             CODE:
618 14           RETVAL = malloc (sizeof(mpz_t));
619 14           mpz_init(*RETVAL);
620 14           mpz_fac_ui(*RETVAL, n);
621             OUTPUT:
622             RETVAL
623              
624              
625             mpz_t *
626             bnok(n, k)
627             long n
628             long k
629              
630             CODE:
631 6           RETVAL = malloc (sizeof(mpz_t));
632 6           mpz_init(*RETVAL);
633 6           mpz_bin_uiui(*RETVAL, n, k);
634             OUTPUT:
635             RETVAL
636              
637              
638             mpz_t *
639             gmp_copy(m)
640             mpz_t * m
641              
642             CODE:
643 2           RETVAL = malloc (sizeof(mpz_t));
644 2           mpz_init_set(*RETVAL, *m);
645             OUTPUT:
646             RETVAL
647              
648             int
649             gmp_tstbit(m,n)
650             mpz_t * m
651             long n
652              
653             CODE:
654 10           RETVAL = mpz_tstbit(*m,n);
655             OUTPUT:
656             RETVAL
657              
658             mpz_t *
659             broot(m,n)
660             mpz_t * m
661             unsigned long n
662              
663             CODE:
664 10           RETVAL = malloc (sizeof(mpz_t));
665 10           mpz_init(*RETVAL);
666 10           mpz_root(*RETVAL, *m, n);
667             OUTPUT:
668             RETVAL
669              
670             void
671             brootrem(m,n)
672             mpz_t * m
673             unsigned long n
674              
675             PREINIT:
676             mpz_t * root;
677             mpz_t * remainder;
678             PPCODE:
679 6           root = malloc (sizeof(mpz_t));
680 6           remainder = malloc (sizeof(mpz_t));
681 6           mpz_init(*root);
682 6           mpz_init(*remainder);
683 6 50         if (need_rootrem_workaround(m, n)) {
684             /* Older libgmp have bugs for negative m, but if we need to we can
685             * work on abs(m) then negate the results.
686             */
687 0           mpz_neg(*root, *m);
688 0           mpz_rootrem(*root, *remainder, *root, n);
689 0           mpz_neg(*root, *root);
690 0           mpz_neg(*remainder, *remainder);
691             } else {
692 6           mpz_rootrem(*root, *remainder, *m, n);
693             }
694 6 50         EXTEND(SP, 2);
695 6           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)root));
696 6           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)remainder));
697              
698             mpz_t *
699             bsqrt(m)
700             mpz_t * m
701              
702             CODE:
703 13           RETVAL = malloc (sizeof(mpz_t));
704 13           mpz_init(*RETVAL);
705 13           mpz_sqrt(*RETVAL, *m);
706             OUTPUT:
707             RETVAL
708              
709             void
710             bsqrtrem(m)
711             mpz_t * m
712              
713             PREINIT:
714             mpz_t * sqrt;
715             mpz_t * remainder;
716             PPCODE:
717 10           sqrt = malloc (sizeof(mpz_t));
718 10           remainder = malloc (sizeof(mpz_t));
719 10           mpz_init(*sqrt);
720 10           mpz_init(*remainder);
721 10           mpz_sqrtrem(*sqrt, *remainder, *m);
722 10 50         EXTEND(SP, 2);
723 10           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)sqrt));
724 10           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)remainder));
725              
726             int
727             is_perfect_power(m)
728             mpz_t * m
729              
730             CODE:
731 12           RETVAL = mpz_perfect_power_p(*m) ? 1 : 0;
732             OUTPUT:
733             RETVAL
734              
735             int
736             is_perfect_square(m)
737             mpz_t * m
738              
739             CODE:
740 12           RETVAL = mpz_perfect_square_p(*m) ? 1 : 0;
741             OUTPUT:
742             RETVAL
743