File Coverage

GMP.xs
Criterion Covered Total %
statement 174 190 91.5
branch 32 52 61.5
condition n/a
subroutine n/a
pod n/a
total 206 242 85.1


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 243           pv2gmp(char* pv)
75             {
76             mpz_t* z;
77             SV* sv;
78              
79 243           z = malloc (sizeof(mpz_t));
80 243           mpz_init_set_str(*z, pv, 0);
81 243           sv = sv_newmortal();
82 243           sv_setref_pv(sv, "Math::GMP", (void*)z);
83 243           return z;
84             }
85              
86             mpz_t *
87 5546           sv2gmp(SV* sv)
88             {
89             char* pv;
90              
91             /* MAYCHANGE in perlguts.pod - bug in perl */
92 5546 50         if (SvGMAGICAL(sv)) mg_get(sv);
93              
94 5546 100         if (SvROK(sv) && sv_derived_from(sv, "Math::GMP")) {
    50          
95 5303 50         IV tmp = SvIV((SV*)SvRV(sv));
96 5303           return (mpz_t *)tmp;
97             }
98              
99 243 50         pv = SvPV_nolen(sv);
100 243           return pv2gmp(pv);
101             }
102              
103              
104             SV *
105 845           stringify(mpz_t *n)
106             {
107             char *buf;
108             char *pv;
109             int len;
110             SV *sv;
111              
112 845           len = mpz_sizeinbase(*n, 10);
113 845           buf = malloc(len + 2);
114              
115 845           mpz_get_str(buf, 10, *n);
116 845           sv = newSVpv(buf, strlen(buf));
117 845           free(buf);
118 845           return sv;
119             }
120              
121              
122             MODULE = Math::GMP PACKAGE = Math::GMP
123             PROTOTYPES: ENABLE
124              
125             mpz_t *
126             new_from_scalar(s)
127             char * s
128              
129             CODE:
130 1636           RETVAL = malloc (sizeof(mpz_t));
131 1636           mpz_init_set_str(*RETVAL, s, 0);
132             OUTPUT:
133             RETVAL
134              
135             mpz_t *
136             new_from_scalar_with_base(s, b)
137             char * s
138             int b
139              
140             CODE:
141 2           RETVAL = malloc (sizeof(mpz_t));
142 2           mpz_init_set_str(*RETVAL, s, b);
143             OUTPUT:
144             RETVAL
145              
146             void
147             destroy(n)
148             mpz_t *n
149              
150             CODE:
151 2817           mpz_clear(*n);
152 2817           free(n);
153              
154             SV *
155             _gmp_build_version()
156             CODE:
157 0           char buf[] = STRINGIFY(__GNU_MP_VERSION)
158             "." STRINGIFY(__GNU_MP_VERSION_MINOR)
159             "." STRINGIFY(__GNU_MP_VERSION_PATCHLEVEL);
160 0           RETVAL = newSV(6);
161 0           scan_vstring(buf, buf + sizeof(buf), RETVAL);
162             OUTPUT:
163             RETVAL
164              
165             SV *
166             _gmp_lib_version()
167             CODE:
168 0           const char* v = gmp_version;
169 0           RETVAL = newSV(6);
170 0           scan_vstring(v, v + strlen(v), RETVAL);
171             OUTPUT:
172             RETVAL
173              
174             SV *
175             stringify(n)
176             mpz_t * n
177              
178             CODE:
179 0           RETVAL = stringify(n);
180             OUTPUT:
181             RETVAL
182              
183              
184             SV *
185             get_str_gmp(n, b)
186             mpz_t * n
187             int b
188              
189             PREINIT:
190             int len;
191              
192             CODE:
193 1           len = mpz_sizeinbase(*n, b);
194             {
195             char *buf;
196 1           buf = malloc(len + 2);
197 1           mpz_get_str(buf, b, *n);
198 1           RETVAL = newSVpv(buf, strlen(buf));
199 1           free(buf);
200             }
201             OUTPUT:
202             RETVAL
203              
204             int
205             sizeinbase_gmp(n, b)
206             mpz_t * n
207             int b
208              
209             CODE:
210 7           RETVAL = mpz_sizeinbase(*n, b);
211             OUTPUT:
212             RETVAL
213              
214             unsigned long
215             uintify(n)
216             mpz_t * n
217              
218             CODE:
219 8           RETVAL = mpz_get_ui(*n);
220             OUTPUT:
221             RETVAL
222              
223             void
224             add_ui_gmp(n, v)
225             mpz_t * n
226             unsigned long v
227              
228             CODE:
229 7           mpz_add_ui(*n, *n, v);
230              
231              
232             long
233             intify(n)
234             mpz_t * n
235              
236             CODE:
237 5           RETVAL = mpz_get_si(*n);
238             OUTPUT:
239             RETVAL
240              
241             mpz_t *
242             mul_2exp_gmp(n, e)
243             mpz_t * n
244             unsigned long e
245              
246             CODE:
247 9           RETVAL = malloc (sizeof(mpz_t));
248 9           mpz_init(*RETVAL);
249 9           mpz_mul_2exp(*RETVAL, *n, e);
250             OUTPUT:
251             RETVAL
252              
253             mpz_t *
254             div_2exp_gmp(n, e)
255             mpz_t * n
256             unsigned long e
257              
258             CODE:
259 5           RETVAL = malloc (sizeof(mpz_t));
260 5           mpz_init(*RETVAL);
261 5           mpz_div_2exp(*RETVAL, *n, e);
262             OUTPUT:
263             RETVAL
264              
265              
266             mpz_t *
267             powm_gmp(n, exp, mod)
268             mpz_t * n
269             mpz_t * exp
270             mpz_t * mod
271              
272             CODE:
273 7           RETVAL = malloc (sizeof(mpz_t));
274 7           mpz_init(*RETVAL);
275 7           mpz_powm(*RETVAL, *n, *exp, *mod);
276             OUTPUT:
277             RETVAL
278              
279              
280             mpz_t *
281             mmod_gmp(a, b)
282             mpz_t * a
283             mpz_t * b
284              
285             CODE:
286 5           RETVAL = malloc (sizeof(mpz_t));
287 5           mpz_init(*RETVAL);
288 5           mpz_mmod(*RETVAL, *a, *b);
289             OUTPUT:
290             RETVAL
291              
292              
293             mpz_t *
294             mod_2exp_gmp(in, cnt)
295             mpz_t * in
296             unsigned long cnt
297              
298             CODE:
299 5           RETVAL = malloc (sizeof(mpz_t));
300 5           mpz_init(*RETVAL);
301 5           mpz_mod_2exp(*RETVAL, *in, cnt);
302             OUTPUT:
303             RETVAL
304              
305              
306             SV *
307             op_stringify(m,n,swap)
308             mpz_t * m
309             SV * n
310             bool swap
311              
312             CODE:
313             /* 'n' and 'swap' are dummy variables */
314 845           RETVAL = stringify(m);
315             OUTPUT:
316             RETVAL
317              
318              
319             SV *
320             op_numify(m,n,swap)
321             mpz_t * m
322             SV * n
323             bool swap
324              
325             CODE:
326             /* 'n' and 'swap' are dummy variables */
327 59 50         if (mpz_sgn(*m) < 0) {
328 0           RETVAL = newSViv(mpz_get_si(*m));
329             } else {
330 59           RETVAL = newSVuv(mpz_get_ui(*m));
331             }
332             OUTPUT:
333             RETVAL
334              
335              
336             SV *
337             op_bool(m,n,swap)
338             mpz_t * m
339             SV * n
340             bool swap
341              
342             CODE:
343             /* 'n' and 'swap' are dummy variables */
344 3 50         RETVAL = mpz_sgn(*m) ? &PL_sv_yes : &PL_sv_no;
    50          
345             OUTPUT:
346             RETVAL
347              
348              
349             mpz_t *
350             op_add(m,n,swap)
351             mpz_t * m
352             mpz_t * n
353             bool swap
354              
355             CODE:
356 73           RETVAL = malloc (sizeof(mpz_t));
357 73           mpz_init(*RETVAL);
358 73           mpz_add(*RETVAL, *m, *n);
359             OUTPUT:
360             RETVAL
361              
362              
363             mpz_t *
364             op_sub(m,n,swap)
365             mpz_t * m
366             mpz_t * n
367             bool swap
368              
369             CODE:
370 72 100         SWAP_GMP
371 72           RETVAL = malloc (sizeof(mpz_t));
372 72           mpz_init(*RETVAL);
373 72           mpz_sub(*RETVAL, *m, *n);
374             OUTPUT:
375             RETVAL
376              
377              
378             mpz_t *
379             op_mul(m,n,swap)
380             mpz_t * m
381             mpz_t * n
382             bool swap
383              
384             CODE:
385 63           RETVAL = malloc (sizeof(mpz_t));
386 63           mpz_init(*RETVAL);
387 63           mpz_mul(*RETVAL, *m, *n);
388             OUTPUT:
389             RETVAL
390              
391              
392             mpz_t *
393             bmulf(n,d)
394             mpz_t * n
395             double d
396              
397             PREINIT:
398             mpf_t nf, df;
399             mp_bitcnt_t prec;
400             CODE:
401             /*
402             Multiply (mpz_t) n by (double) d returning an (mpz_t) result.
403             Uses GMP floats with maximum needed precision.
404             */
405 46           prec = mpf_get_default_prec();
406 46           mpf_set_default_prec(mpz_sizeinbase(*n, 2) + 8 * sizeof(double));
407              
408 46           RETVAL = malloc (sizeof(mpz_t));
409 46           mpz_init(*RETVAL);
410 46           mpf_init(nf);
411 46           mpf_init(df);
412              
413 46           mpf_set_z(nf, *n);
414 46           mpf_set_d(df, d);
415 46           mpf_mul(nf, nf, df);
416 46           mpz_set_f(*RETVAL, nf);
417 46           mpf_clear(nf);
418 46           mpf_clear(df);
419             /* restore default */
420 46           mpf_set_default_prec(prec);
421             OUTPUT:
422             RETVAL
423              
424              
425             mpz_t *
426             op_div(m,n,swap)
427             mpz_t * m
428             mpz_t * n
429             bool swap
430              
431             CODE:
432 64 100         SWAP_GMP
433 64           RETVAL = malloc (sizeof(mpz_t));
434 64           mpz_init(*RETVAL);
435 64           mpz_div(*RETVAL, *m, *n);
436             OUTPUT:
437             RETVAL
438              
439              
440             void
441             bdiv(m,n)
442             mpz_t * m
443             mpz_t * n
444              
445             PREINIT:
446             mpz_t * quo;
447             mpz_t * rem;
448             PPCODE:
449 129           quo = malloc (sizeof(mpz_t));
450 129           rem = malloc (sizeof(mpz_t));
451 129           mpz_init(*quo);
452 129           mpz_init(*rem);
453 129           mpz_tdiv_qr(*quo, *rem, *m, *n);
454 129 50         EXTEND(SP, 2);
455 129           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)quo));
456 129           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)rem));
457              
458              
459              
460             mpz_t *
461             op_mod(m,n,swap)
462             mpz_t * m
463             mpz_t * n
464             bool swap
465              
466             CODE:
467 65 100         SWAP_GMP
468 65           RETVAL = malloc (sizeof(mpz_t));
469 65           mpz_init(*RETVAL);
470 65           mpz_mod(*RETVAL, *m, *n);
471             OUTPUT:
472             RETVAL
473              
474             mpz_t *
475             bmodinv(m,n)
476             mpz_t * m
477             mpz_t * n
478              
479             CODE:
480 11           RETVAL = malloc (sizeof(mpz_t));
481 11           mpz_init(*RETVAL);
482 11           mpz_invert(*RETVAL, *m, *n);
483             OUTPUT:
484             RETVAL
485              
486              
487             int
488             op_spaceship(m,n,swap)
489             mpz_t * m
490             mpz_t * n
491             bool swap
492              
493             PREINIT:
494             int i;
495             CODE:
496 46           i = mpz_cmp(*m, *n);
497 46 100         if (swap) {
498 4           i = -i;
499             }
500 46 100         RETVAL = (i < 0) ? -1 : (i > 0) ? 1 : 0;
501             OUTPUT:
502             RETVAL
503              
504             int
505             op_eq(m,n,swap)
506             mpz_t* m
507             mpz_t* n
508             bool swap
509              
510             PREINIT:
511             int i;
512             CODE:
513 0           i = mpz_cmp(*m, *n);
514 0           RETVAL = (i == 0) ? 1 : 0;
515             OUTPUT:
516             RETVAL
517              
518             int
519             legendre(m, n)
520             mpz_t * m
521             mpz_t * n
522              
523             CODE:
524 1           RETVAL = mpz_legendre(*m, *n);
525             OUTPUT:
526             RETVAL
527              
528             int
529             jacobi(m, n)
530             mpz_t * m
531             mpz_t * n
532              
533             CODE:
534 119           RETVAL = mpz_jacobi(*m, *n);
535             OUTPUT:
536             RETVAL
537              
538             int
539             probab_prime(m, reps)
540             mpz_t * m
541             int reps
542              
543             CODE:
544 25           RETVAL = mpz_probab_prime_p(*m, reps);
545             OUTPUT:
546             RETVAL
547              
548             mpz_t *
549             op_pow(m,n)
550             mpz_t * m
551             long n
552              
553             CODE:
554 2           RETVAL = malloc (sizeof(mpz_t));
555 2           mpz_init(*RETVAL);
556             /* fprintf(stderr, "n is %ld\n", n);*/
557 2           mpz_pow_ui(*RETVAL, *m, n);
558             OUTPUT:
559             RETVAL
560              
561              
562             mpz_t *
563             bgcd(m,n)
564             mpz_t * m
565             mpz_t * n
566              
567             CODE:
568 71           RETVAL = malloc (sizeof(mpz_t));
569 71           mpz_init(*RETVAL);
570 71           mpz_gcd(*RETVAL, *m, *n);
571             OUTPUT:
572             RETVAL
573              
574              
575             mpz_t *
576             blcm(m,n)
577             mpz_t * m
578             mpz_t * n
579              
580             CODE:
581 41           RETVAL = malloc (sizeof(mpz_t));
582 41           mpz_init(*RETVAL);
583 41           mpz_lcm(*RETVAL, *m, *n);
584             OUTPUT:
585             RETVAL
586              
587              
588             mpz_t *
589             fibonacci(n)
590             long n
591              
592             CODE:
593 19           RETVAL = malloc (sizeof(mpz_t));
594 19           mpz_init(*RETVAL);
595 19           mpz_fib_ui(*RETVAL, n);
596             OUTPUT:
597             RETVAL
598              
599              
600             mpz_t *
601             band(m,n, ...)
602             mpz_t * m
603             mpz_t * n
604              
605             CODE:
606 7           RETVAL = malloc (sizeof(mpz_t));
607 7           mpz_init(*RETVAL);
608 7           mpz_and(*RETVAL, *m, *n);
609             OUTPUT:
610             RETVAL
611              
612             mpz_t *
613             bxor(m,n, ...)
614             mpz_t * m
615             mpz_t * n
616              
617             CODE:
618 7           RETVAL = malloc (sizeof(mpz_t));
619 7           mpz_init(*RETVAL);
620 7           mpz_xor(*RETVAL, *m, *n);
621             OUTPUT:
622             RETVAL
623              
624             mpz_t *
625             bior(m,n, ...)
626             mpz_t * m
627             mpz_t * n
628              
629             CODE:
630 7           RETVAL = malloc (sizeof(mpz_t));
631 7           mpz_init(*RETVAL);
632 7           mpz_ior(*RETVAL, *m, *n);
633             OUTPUT:
634             RETVAL
635              
636             mpz_t *
637             blshift(m,n,swap)
638             mpz_t * m
639             mpz_t * n
640             bool swap
641              
642             CODE:
643 9 50         SWAP_GMP
644 9           RETVAL = malloc (sizeof(mpz_t));
645 9           mpz_init(*RETVAL);
646 9           mpz_mul_2exp(*RETVAL, *m, mpz_get_ui(*n));
647             OUTPUT:
648             RETVAL
649              
650             mpz_t *
651             brshift(m,n,swap)
652             mpz_t * m
653             mpz_t * n
654             bool swap
655              
656             CODE:
657 13 50         SWAP_GMP
658 13           RETVAL = malloc (sizeof(mpz_t));
659 13           mpz_init(*RETVAL);
660 13           mpz_div_2exp(*RETVAL, *m, mpz_get_ui(*n));
661             OUTPUT:
662             RETVAL
663              
664             mpz_t *
665             bfac(n)
666             long n
667              
668             CODE:
669 14           RETVAL = malloc (sizeof(mpz_t));
670 14           mpz_init(*RETVAL);
671 14           mpz_fac_ui(*RETVAL, n);
672             OUTPUT:
673             RETVAL
674              
675              
676             mpz_t *
677             bnok(n, k)
678             long n
679             long k
680              
681             CODE:
682 6           RETVAL = malloc (sizeof(mpz_t));
683 6           mpz_init(*RETVAL);
684 6           mpz_bin_uiui(*RETVAL, n, k);
685             OUTPUT:
686             RETVAL
687              
688              
689             mpz_t *
690             gmp_copy(m)
691             mpz_t * m
692              
693             CODE:
694 2           RETVAL = malloc (sizeof(mpz_t));
695 2           mpz_init_set(*RETVAL, *m);
696             OUTPUT:
697             RETVAL
698              
699             int
700             gmp_tstbit(m,n)
701             mpz_t * m
702             long n
703              
704             CODE:
705 10           RETVAL = mpz_tstbit(*m,n);
706             OUTPUT:
707             RETVAL
708              
709             mpz_t *
710             broot(m,n)
711             mpz_t * m
712             unsigned long n
713              
714             CODE:
715 10           RETVAL = malloc (sizeof(mpz_t));
716 10           mpz_init(*RETVAL);
717 10           mpz_root(*RETVAL, *m, n);
718             OUTPUT:
719             RETVAL
720              
721             void
722             brootrem(m,n)
723             mpz_t * m
724             unsigned long n
725              
726             PREINIT:
727             mpz_t * root;
728             mpz_t * remainder;
729             PPCODE:
730 6           root = malloc (sizeof(mpz_t));
731 6           remainder = malloc (sizeof(mpz_t));
732 6           mpz_init(*root);
733 6           mpz_init(*remainder);
734 6 50         if (need_rootrem_workaround(m, n)) {
735             /* Older libgmp have bugs for negative m, but if we need to we can
736             * work on abs(m) then negate the results.
737             */
738 0           mpz_neg(*root, *m);
739 0           mpz_rootrem(*root, *remainder, *root, n);
740 0           mpz_neg(*root, *root);
741 0           mpz_neg(*remainder, *remainder);
742             } else {
743 6           mpz_rootrem(*root, *remainder, *m, n);
744             }
745 6 50         EXTEND(SP, 2);
746 6           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)root));
747 6           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)remainder));
748              
749             mpz_t *
750             bsqrt(m)
751             mpz_t * m
752              
753             CODE:
754 13           RETVAL = malloc (sizeof(mpz_t));
755 13           mpz_init(*RETVAL);
756 13           mpz_sqrt(*RETVAL, *m);
757             OUTPUT:
758             RETVAL
759              
760             void
761             bsqrtrem(m)
762             mpz_t * m
763              
764             PREINIT:
765             mpz_t * sqrt;
766             mpz_t * remainder;
767             PPCODE:
768 10           sqrt = malloc (sizeof(mpz_t));
769 10           remainder = malloc (sizeof(mpz_t));
770 10           mpz_init(*sqrt);
771 10           mpz_init(*remainder);
772 10           mpz_sqrtrem(*sqrt, *remainder, *m);
773 10 50         EXTEND(SP, 2);
774 10           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)sqrt));
775 10           PUSHs(sv_setref_pv(sv_newmortal(), "Math::GMP", (void*)remainder));
776              
777             int
778             is_perfect_power(m)
779             mpz_t * m
780              
781             CODE:
782 12           RETVAL = mpz_perfect_power_p(*m) ? 1 : 0;
783             OUTPUT:
784             RETVAL
785              
786             int
787             is_perfect_square(m)
788             mpz_t * m
789              
790             CODE:
791 12           RETVAL = mpz_perfect_square_p(*m) ? 1 : 0;
792             OUTPUT:
793             RETVAL
794