# ---?--- # # $Id$ # # Multiprecision interface # # (c) 2000 Straylight/Edgeware # #----- Licensing notice ----------------------------------------------------- # # This file is part of the Perl interface to Catacomb. # # Catacomb/Perl is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # Catacomb/Perl is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Catacomb/Perl; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # MODULE = Catacomb PACKAGE = Catacomb::MP PREFIX = mp_ mp * new(me, sv = 0, radix = 0) SV *me SV *sv int radix CODE: RETVAL = sv ? mp_fromsv(sv, "sv", "Catacomb::MP", radix, 1) : MP_ZERO; OUTPUT: RETVAL mp * copy(x) mp *x CODE: RETVAL = MP_COPY(x); OUTPUT: RETVAL mp * loadb(me, sv) SV *me SV *sv PREINIT: char *p; STRLEN len; CODE: p = SvPV(sv, len); RETVAL = mp_loadb(MP_NEW, p, len); OUTPUT: RETVAL mp * loadl(me, sv) SV *me SV *sv PREINIT: char *p; STRLEN len; CODE: p = SvPV(sv, len); RETVAL = mp_loadl(MP_NEW, p, len); OUTPUT: RETVAL int metrics(m) mp *m INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: octets bits SV * storeb(m, i = -1) mp *m int i PREINIT: size_t sz; CODE: sz = (i < 0) ? mp_octets(m) : i; RETVAL = NEWSV(0, sz ? sz : 1); mp_storeb(m, SvPVX(RETVAL), sz); SvCUR_set(RETVAL, sz); SvPOK_on(RETVAL); OUTPUT: RETVAL SV * storel(m, i = -1) mp *m int i PREINIT: size_t sz; CODE: sz = (i < 0) ? mp_octets(m) : i; RETVAL = NEWSV(0, sz ? sz : 1); mp_storel(m, SvPVX(RETVAL), sz); SvCUR_set(RETVAL, sz); SvPOK_on(RETVAL); OUTPUT: RETVAL SV * tostring(m, radix = 10) mp *m int radix CODE: RETVAL = NEWSV(0, 0); mp_writesv(m, RETVAL, radix); OUTPUT: RETVAL SV * toint(m) mp *m CODE: RETVAL = newSViv(mp_toiv(m)); OUTPUT: RETVAL SV * DESTROY(m) mp *m CODE: mp_drop(m); XSRETURN_UNDEF; mp * unop(a) mp *a C_ARGS: MP_NEW, a INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: not sqr sqrt mp * neg(a) mp *a CODE: MP_COPY(a); RETVAL = mp_split(a); if (RETVAL->v < RETVAL->vl) RETVAL->f ^= MP_NEG; OUTPUT: RETVAL mp * mp_factorial(me, x) SV *me IV x C_ARGS: x mp * binop(a, b) mp *a mp *b C_ARGS: MP_NEW, a, b INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: add sub mul and2c or2c nand2c nor2c xor2c and or nand nor xor mp * shiftop(a, n) mp *a int n C_ARGS: MP_NEW, a, n INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: lsl lsr lsl2c lsr2c bool testbitop(a, n) mp *a unsigned long n INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: testbit testbit2c mp * flipbits(a, n) mp *a unsigned long n C_ARGS: MP_NEW, a, n INTERFACE_MACRO: XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: setbit clearbit setbit2c clearbit2c int mp_cmp(a, b) mp *a mp *b int mp_eq(a, b) mp *a mp *b int jacobi(a, n) mp *a mp *n CODE: if (!MP_LEN(n) || !(n->v[0] & 1)) croak("n must be odd in Catacomb::MP::jacobi"); RETVAL = mp_jacobi(a, n); OUTPUT: RETVAL mp * mp_modsqrt(p, x) mp *p mp *x C_ARGS: MP_NEW, x, p void div(a, b) mp *a mp *b PREINIT: mp *q = MP_NEW, *r = MP_NEW; PPCODE: if (MP_EQ(b, MP_ZERO)) croak("Divide by zero in Catacomb::MP::div"); q = MP_NEW; switch (GIMME_V) { case G_ARRAY: r = MP_NEW; mp_div(&q, &r, a, b); EXTEND(SP, 2); PUSHs(RET_MP(q)); PUSHs(RET_MP(r)); break; case G_VOID: break; default: mp_div(&q, &r, a, b); EXTEND(SP, 1); PUSHs(RET_MP(q)); break; } void gcd(a, b) mp *a mp *b PREINIT: mp *g = MP_NEW, *x = MP_NEW, *y = MP_NEW; PPCODE: switch (GIMME_V) { case G_ARRAY: mp_gcd(&g, &x, &y, a, b); EXTEND(SP, 3); PUSHs(RET_MP(g)); PUSHs(RET_MP(x)); PUSHs(RET_MP(y)); break; case G_VOID: break; default: mp_gcd(&g, 0, 0, a, b); EXTEND(SP, 1); PUSHs(RET_MP(g)); break; } void odd(m) mp *m PREINIT: mp *t; size_t s; PPCODE: t = mp_odd(MP_NEW, m, &s); EXTEND(SP, 2); PUSHs(RET_MP(t)); PUSHs(sv_2mortal(newSViv(s))); int smallfactor(x) mp *x CODE: RETVAL = pfilt_smallfactor(x); OUTPUT: RETVAL MP_Reduce * makereduce(x) mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::makereduce must be positive"); RETVAL = CREATE(MP_Reduce); mpreduce_create(RETVAL, x); OUTPUT: RETVAL MP_Mont * mont(x) mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::mont must be positive"); if (!MP_ODDP(x)) croak("Argument to Catacomb::MP::mont must be odd"); RETVAL = CREATE(MP_Mont); mpmont_create(RETVAL, x); OUTPUT: RETVAL MP_Barrett * barrett(x) mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::barrett must be positive"); RETVAL = CREATE(mpbarrett); mpbarrett_create(RETVAL, x); OUTPUT: RETVAL MP_Prime_Rabin * rabin(x) mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::rabin must be positive"); if (!MP_ODDP(x)) croak("Argument to Catacomb::MP::rabin must be odd"); RETVAL = CREATE(MP_Prime_Rabin); rabin_create(RETVAL, x); OUTPUT: RETVAL MODULE = Catacomb PACKAGE = Catacomb::MP::Mont PREFIX = mpmont_ MP_Mont * new(me, x) SV *me mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::Mont::new must be positive"); if (!MP_ODDP(x)) croak("Argument to Catacomb::MP::Mont::new must be odd"); RETVAL = CREATE(MP_Mont); mpmont_create(RETVAL, x); OUTPUT: RETVAL SV * DESTROY(mm) MP_Mont *mm CODE: mpmont_destroy(mm); DESTROY(mm); XSRETURN_UNDEF; mp * mpmont_reduce(mm, x) MP_Mont *mm mp *x C_ARGS: mm, MP_NEW, x mp * mpmont_mul(mm, x, y) MP_Mont *mm mp *x mp *y C_ARGS: mm, MP_NEW, x, y mp * mpmont_expr(mm, g, x) MP_Mont *mm mp *g mp *x C_ARGS: mm, MP_NEW, g, x mp * mpmont_exp(mm, g, x) MP_Mont *mm mp *g mp *x C_ARGS: mm, MP_NEW, g, x mp * mpmont_mexpr(mm, ...) MP_Mont *mm PREINIT: mp_expfactor *v; size_t i, j, n; CODE: if (items < 3 || !(items & 1)) { croak("Usage: Catacomb::MP::Mont::mexpr" "(mm, g_0, x_0, g_1, x_1, ..."); } n = (items - 1)/2; v = xmalloc(n * sizeof(mp_expfactor)); for (i = 1, j = 0; i < items; i += 2, j++) { v[j].base = mp_fromsv(ST(i), "g_i", "Catacomb::MP", 0, 0); v[j].exp = mp_fromsv(ST(i + 1), "x_i", "Catacomb::MP", 0, 0); } RETVAL = mpmont_mexpr(mm, MP_NEW, v, n); xfree(v); OUTPUT: RETVAL mp * mpmont_mexp(mm, ...) MP_Mont *mm PREINIT: mp_expfactor *v; size_t i, j, n; CODE: if (items < 3 || !(items & 1)) { croak("Usage: Catacomb::MP::Mont::mexp" "(mm, g_0, x_0, g_1, x_1, ..."); } n = (items - 1)/2; v = xmalloc(n * sizeof(mp_expfactor)); for (i = 1, j = 0; i < items; i += 2, j++) { v[j].base = mp_fromsv(ST(i), "g_%lu", "Catacomb::MP", 0, 0, (unsigned long)i); v[j].exp = mp_fromsv(ST(i + 1), "x_%lu", "Catacomb::MP", 0, 0, (unsigned long)i); } RETVAL = mpmont_mexp(mm, MP_NEW, v, n); xfree(v); OUTPUT: RETVAL mp * r(mm) MP_Mont *mm CODE: RETVAL = MP_COPY(mm->r); OUTPUT: RETVAL mp * r2(mm) MP_Mont *mm CODE: RETVAL = MP_COPY(mm->r2); OUTPUT: RETVAL mp * m(mm) MP_Mont *mm CODE: RETVAL = MP_COPY(mm->m); OUTPUT: RETVAL MODULE = Catacomb PACKAGE = Catacomb::MP::Barrett PREFIX = mpbarrett_ MP_Barrett * new(me, x) SV *me mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::Barrett::new must be positive"); RETVAL = CREATE(mpbarrett); mpbarrett_create(RETVAL, x); OUTPUT: RETVAL SV * DESTROY(mb) MP_Barrett *mb CODE: mpbarrett_destroy(mb); DESTROY(mb); XSRETURN_UNDEF; mp * mpbarrett_reduce(mb, x) MP_Barrett *mb mp *x C_ARGS: mb, MP_NEW, x mp * mpbarrett_exp(mb, g, x) MP_Barrett *mb mp *g mp *x C_ARGS: mb, MP_NEW, g, x mp * m(mb) MP_Barrett *mb CODE: RETVAL = MP_COPY(mb->m); OUTPUT: RETVAL MODULE = Catacomb PACKAGE = Catacomb::MP::Reduce PREFIX = mpreduce_ MP_Reduce * new(me, x) SV *me mp *x CODE: if (!MP_POSP(x)) croak("Argument to Catacomb::MP::Reduce::new must be positive"); RETVAL = CREATE(mpreduce); mpreduce_create(RETVAL, x); OUTPUT: RETVAL SV * DESTROY(r) MP_Reduce *r CODE: mpreduce_destroy(r); DESTROY(r); XSRETURN_UNDEF; mp * reduce(r, x) MP_Reduce *r mp *x CODE: RETVAL = mpreduce_do(r, MP_NEW, x); OUTPUT: RETVAL mp * mpreduce_exp(r, x, y) MP_Reduce *r mp *x mp *y C_ARGS: r, MP_NEW, x, y mp * m(r) MP_Reduce *r CODE: RETVAL = MP_COPY(r->p); OUTPUT: RETVAL MODULE = Catacomb PACKAGE = Catacomb::MP::CRT MP_CRT * new(me, ...) SV *me PREINIT: mpcrt_mod *v; size_t n, i; CODE: if (items < 1) croak("Usage: Catacomb::MP::CRT::new(me, n_0, n_1, ...)"); n = items - 1; v = xmalloc(n * sizeof(mpcrt_mod)); for (i = 0; i < n; i++) { v[i].m = mp_copy(mp_fromsv(ST(i + 1), "n_%lu", "Catacomb::MP", 0, 0, (unsigned long)i)); } RETVAL = CREATE(MP_CRT); mpcrt_create(RETVAL, v, n, 0); OUTPUT: RETVAL SV * DESTROY(mc) MP_CRT *mc CODE: mpcrt_destroy(mc); xfree(mc->v); DESTROY(mc); XSRETURN_UNDEF; mp * solve(mc, ...) MP_CRT *mc PREINIT: mp **v; size_t n, i; CODE: n = mc->k; if (items - 1 != n) croak("Wrong number of residues for this CRT context"); for (i = 0; i < n; i++) { v[i] = mp_fromsv(ST(i + 1), "r_%lu", "Catacomb::MP", 0, 0, (unsigned long)i); } RETVAL = mpcrt_solve(mc, MP_NEW, v); xfree(v); OUTPUT: RETVAL #----- That's all, folks ----------------------------------------------------