X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-perl/blobdiff_plain/a24b5cfdde0be71a5bb2b85d94be3b93c7719e2a..9b46ee0d9f144189d9df836347402c3b3df97936:/mp.xs diff --git a/mp.xs b/mp.xs index 56c8756..9eb7fe2 100644 --- a/mp.xs +++ b/mp.xs @@ -1,6 +1,6 @@ # ---?--- # -# $Id: mp.xs,v 1.2 2004/04/08 01:36:21 mdw Exp $ +# $Id$ # # Multiprecision interface # @@ -39,8 +39,12 @@ new(me, sv = 0, radix = 0) RETVAL mp * -mp_copy(x) +copy(x) mp *x + CODE: + RETVAL = MP_COPY(x); + OUTPUT: + RETVAL mp * loadb(me, sv) @@ -68,6 +72,32 @@ loadl(me, sv) OUTPUT: RETVAL +mp * +loadb2c(me, sv) + SV *me + SV *sv + PREINIT: + char *p; + STRLEN len; + CODE: + p = SvPV(sv, len); + RETVAL = mp_loadb2c(MP_NEW, p, len); + OUTPUT: + RETVAL + +mp * +loadl2c(me, sv) + SV *me + SV *sv + PREINIT: + char *p; + STRLEN len; + CODE: + p = SvPV(sv, len); + RETVAL = mp_loadl2c(MP_NEW, p, len); + OUTPUT: + RETVAL + int metrics(m) mp *m @@ -75,7 +105,7 @@ metrics(m) XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: - octets bits + octets bits octets2c SV * storeb(m, i = -1) @@ -84,7 +114,13 @@ storeb(m, i = -1) PREINIT: size_t sz; CODE: - sz = (i < 0) ? mp_octets(m) : i; + if (i >= 0) + sz = i; + else { + sz = mp_octets(m); + if (!sz) + sz = 1; + } RETVAL = NEWSV(0, sz ? sz : 1); mp_storeb(m, SvPVX(RETVAL), sz); SvCUR_set(RETVAL, sz); @@ -108,6 +144,36 @@ storel(m, i = -1) RETVAL SV * +storeb2c(m, i = -1) + mp *m + int i + PREINIT: + size_t sz; + CODE: + sz = (i < 0) ? mp_octets2c(m) : i; + RETVAL = NEWSV(0, sz ? sz : 1); + mp_storeb(m, SvPVX(RETVAL), sz); + SvCUR_set(RETVAL, sz); + SvPOK_on(RETVAL); + OUTPUT: + RETVAL + +SV * +storel2c(m, i = -1) + mp *m + int i + PREINIT: + size_t sz; + CODE: + sz = (i < 0) ? mp_octets2c(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 @@ -117,6 +183,25 @@ tostring(m, radix = 10) OUTPUT: RETVAL +void +fromstring(me, s, radix = 10) + SV *me + SV *s + int radix + PREINIT: + mptext_stringctx ms; + STRLEN len; + mp *x; + PPCODE: + ms.buf = SvPV(s, len); + ms.lim = ms.buf + len; + x = mp_read(MP_NEW, radix, &mptext_stringops, &ms); + if (x) { + XPUSHs(RET_MP(x)); + if (GIMME_V == G_ARRAY) + XPUSHs(sv_2mortal(newSVpvn(ms.buf, ms.lim - ms.buf))); + } + SV * toint(m) mp *m @@ -141,13 +226,13 @@ unop(a) XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: - not sqr sqrt + not not2c sqr sqrt mp * neg(a) mp *a CODE: - mp_copy(a); + MP_COPY(a); RETVAL = mp_split(a); if (RETVAL->v < RETVAL->vl) RETVAL->f ^= MP_NEG; @@ -171,7 +256,7 @@ binop(a, b) XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: - add sub mul and or xor + add sub mul and2c or2c nand2c nor2c xor2c and or nand nor xor exp mp * shiftop(a, n) @@ -183,7 +268,29 @@ shiftop(a, n) XSINTERFACE_FUNC XSINTERFACE_FUNC_SETMP INTERFACE: - lsl lsr + 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) @@ -210,6 +317,11 @@ mp * mp_modsqrt(p, x) mp *p mp *x + INIT: + if (!MP_POSP(p) || !MP_ODDP(p)) + croak("p is not positive and odd"); + if (mp_jacobi(x, p) != 1) + croak("x not a quadratic residue mod p"); C_ARGS: MP_NEW, x, p @@ -234,7 +346,7 @@ div(a, b) case G_VOID: break; default: - mp_div(&q, &r, a, b); + mp_div(&q, 0, a, b); EXTEND(SP, 1); PUSHs(RET_MP(q)); break; @@ -273,53 +385,21 @@ odd(m) PPCODE: t = mp_odd(MP_NEW, m, &s); EXTEND(SP, 2); - PUSHs(RET_MP(t)); PUSHs(sv_2mortal(newSViv(s))); + PUSHs(RET_MP(t)); -int -smallfactor(x) - mp *x - CODE: - RETVAL = pfilt_smallfactor(x); - OUTPUT: - RETVAL +MODULE = Catacomb PACKAGE = Catacomb::MP PREFIX = pgen_ -MP_Mont * -mont(x) +bool +pgen_primep(x, r = &rand_global) mp *x - CODE: - if (x->f & MP_NEG) - croak("Argument to Catacomb::MP::mont must be positive"); - if (x->v == x->vl || !(x->v[0] & 1u)) - croak("Argument to Catacomb::MP::mont must be odd"); - RETVAL = CREATE(MP_Mont); - mpmont_create(RETVAL, x); - OUTPUT: - RETVAL + grand *r -MP_Barrett * -barrett(x) - mp *x - CODE: - if (x->f & MP_NEG) - croak("Argument to Catacomb::MP::barrett must be positive"); - RETVAL = CREATE(mpbarrett); - mpbarrett_create(RETVAL, x); - OUTPUT: - RETVAL +MODULE = Catacomb PACKAGE = Catacomb::MP PREFIX = pfilt_ -MP_Prime_Rabin * -rabin(x) +int +pfilt_smallfactor(x) mp *x - CODE: - if (x->f & MP_NEG) - croak("Argument to Catacomb::MP::rabin must be positive"); - if (x->v == x->vl || !(x->v[0] & 1u)) - 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_ @@ -328,12 +408,11 @@ new(me, x) SV *me mp *x CODE: - if (x->f & MP_NEG) - croak("Argument to Catacomb::MP::Mont::new must be positive"); - if (x->v == x->vl || !(x->v[0] & 1u)) - croak("Argument to Catacomb::MP::Mont::new must be odd"); - RETVAL = CREATE(MP_Mont); - mpmont_create(RETVAL, x); + RETVAL = CREATE(MP_Mont); + if (mpmont_create(RETVAL, x)) { + DESTROY(RETVAL); + RETVAL = 0; + } OUTPUT: RETVAL @@ -361,6 +440,17 @@ mpmont_mul(mm, x, y) mm, MP_NEW, x, y mp * +in(mm, x) + MP_Mont *mm + mp *x + CODE: + RETVAL = MP_NEW; + mp_div(0, &RETVAL, x, mm->m); + RETVAL = mpmont_mul(mm, RETVAL, RETVAL, mm->r2); + OUTPUT: + RETVAL + +mp * mpmont_expr(mm, g, x) MP_Mont *mm mp *g @@ -424,7 +514,7 @@ mp * r(mm) MP_Mont *mm CODE: - RETVAL = mp_copy(mm->r); + RETVAL = MP_COPY(mm->r); OUTPUT: RETVAL @@ -432,7 +522,7 @@ mp * r2(mm) MP_Mont *mm CODE: - RETVAL = mp_copy(mm->r2); + RETVAL = MP_COPY(mm->r2); OUTPUT: RETVAL @@ -440,7 +530,7 @@ mp * m(mm) MP_Mont *mm CODE: - RETVAL = mp_copy(mm->m); + RETVAL = MP_COPY(mm->m); OUTPUT: RETVAL @@ -451,10 +541,11 @@ new(me, x) SV *me mp *x CODE: - if (x->f & MP_NEG) - croak("Argument to Catacomb::MP::Barrett::new must be positive"); RETVAL = CREATE(mpbarrett); - mpbarrett_create(RETVAL, x); + if (mpbarrett_create(RETVAL, x)) { + DESTROY(RETVAL); + RETVAL = 0; + } OUTPUT: RETVAL @@ -485,7 +576,55 @@ mp * m(mb) MP_Barrett *mb CODE: - RETVAL = mp_copy(mb->m); + 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: + RETVAL = CREATE(MP_Reduce); + if (mpreduce_create(RETVAL, x)) { + DESTROY(RETVAL); + RETVAL = 0; + } + 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 @@ -503,14 +642,35 @@ new(me, ...) 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", 0, 0, - (unsigned long)i)); + v[i].m = mp_copy(mp_fromsv(ST(i + 1), "n_%lu", + 0, 0, (unsigned long)i)); + v[i].n = v[i].ni = v[i].nni = 0; } RETVAL = CREATE(MP_CRT); mpcrt_create(RETVAL, v, n, 0); OUTPUT: RETVAL +mp * +product(mc) + MP_CRT *mc + CODE: + RETVAL = MP_COPY(mc->mb.m); + OUTPUT: + RETVAL + +void +moduli(mc) + MP_CRT *mc + PREINIT: + size_t n, i; + PPCODE: + n = mc->k; + if (GIMME_V == G_SCALAR) + XPUSHs(sv_2mortal(newSViv(n))); + else for (i = 0; i < n; i++) + XPUSHs(RET_MP(MP_COPY(mc->v[i].m))); + SV * DESTROY(mc) MP_CRT *mc @@ -530,6 +690,7 @@ solve(mc, ...) n = mc->k; if (items - 1 != n) croak("Wrong number of residues for this CRT context"); + v = xmalloc(n * sizeof(mp *)); for (i = 0; i < n; i++) v[i] = mp_fromsv(ST(i + 1), "r_%lu", 0, 0, (unsigned long)i); RETVAL = mpcrt_solve(mc, MP_NEW, v);