diff options
author | Karel Miko <karel.miko@gmail.com> | 2016-04-13 11:45:46 +0200 |
---|---|---|
committer | Karel Miko <karel.miko@gmail.com> | 2016-04-13 11:45:46 +0200 |
commit | be6a221ec9e1b69fcdc1fda22d87bb0a0e894fdf (patch) | |
tree | 1ee43e9e0ee50a9d2a23c8d299bea587ce5030f2 /inc/CryptX_BigInt_LTM.xs.inc | |
parent | e5c6fb2be187f5af00ed74880d9a66e395560d0b (diff) |
v0.030
Diffstat (limited to 'inc/CryptX_BigInt_LTM.xs.inc')
-rwxr-xr-x | inc/CryptX_BigInt_LTM.xs.inc | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/inc/CryptX_BigInt_LTM.xs.inc b/inc/CryptX_BigInt_LTM.xs.inc new file mode 100755 index 00000000..e764ad9a --- /dev/null +++ b/inc/CryptX_BigInt_LTM.xs.inc @@ -0,0 +1,641 @@ +MODULE = CryptX PACKAGE = Math::BigInt::LTM + + +############################################################################## +# _new() + +Math::BigInt::LTM +_new(Class, SV *x) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + if ((SvUOK(x) || SvIOK(x)) && (sizeof(UV) <= sizeof(unsigned long) || SvUV(x) == (unsigned long)SvUV(x))) { + mp_set_int(RETVAL, (unsigned long)SvUV(x)); + } + else { + mp_read_radix(RETVAL, SvPV_nolen(x), 10); + } + OUTPUT: + RETVAL + +############################################################################## +# _from_bin() + +Math::BigInt::LTM +_from_bin(Class, SV *x) + PREINIT: + char *str, *start; + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + str = SvPV_nolen(x); + start = (strlen(str)>2 && str[0] == '0' && str[1] == 'b') ? str+2 : str; + mp_read_radix(RETVAL, start, 2); + OUTPUT: + RETVAL + +############################################################################## +# _from_hex() + +Math::BigInt::LTM +_from_hex(Class, SV *x) + PREINIT: + char *str, *start; + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + str = SvPV_nolen(x); + start = (strlen(str)>2 && str[0] == '0' && str[1] == 'x') ? str+2 : str; + mp_read_radix(RETVAL, start, 16); + OUTPUT: + RETVAL + +############################################################################## +# _from_oct() + +Math::BigInt::LTM +_from_oct(Class, SV *x) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_read_radix(RETVAL, SvPV_nolen(x), 8); + OUTPUT: + RETVAL + +############################################################################## +# _set() - set an already existing object to the given scalar value + +void +_set(Class, Math::BigInt::LTM n, SV *x) + CODE: + mp_set_int(n, SvIV(x)); + +############################################################################## +# _zero() + +Math::BigInt::LTM +_zero(Class) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_set_int(RETVAL, 0); + OUTPUT: + RETVAL + +############################################################################## +# _one() + +Math::BigInt::LTM +_one(Class) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_set_int(RETVAL, 1); + OUTPUT: + RETVAL + +############################################################################## +# _two() + +Math::BigInt::LTM +_two(Class) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_set_int(RETVAL, 2); + OUTPUT: + RETVAL + +############################################################################## +# _ten() + +Math::BigInt::LTM +_ten(Class) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_set_int(RETVAL, 10); + OUTPUT: + RETVAL + +############################################################################## +# _1ex() + +Math::BigInt::LTM +_1ex(Class, int x) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_set_int(RETVAL, 10); + mp_expt_d(RETVAL, x, RETVAL); + OUTPUT: + RETVAL + +############################################################################## +# DESTROY() - free memory of a GMP number + +void +DESTROY(Math::BigInt::LTM n) + PPCODE: + if (n) { + mp_clear(n); + Safefree(n); + } + +############################################################################## +# _str() - return string so that atof() and atoi() can use it + +SV * +_str(Class, Math::BigInt::LTM n) + PREINIT: + int len; + char *buf; + CODE: + if (mp_iszero(n) == MP_YES) { + RETVAL = newSVpv("0", 0); + } + else { + len = mp_unsigned_bin_size(n) * 3 + 2; /* decimal size ~ 3 * bin size +1 for sign +1 for NUL-byte */ + Newz(0, buf, len, char); + mp_toradix_n(n, buf, 10, len); + RETVAL = newSVpv(buf, 0); + Safefree(buf); + } + OUTPUT: + RETVAL + +############################################################################## +# _len() - return the length of the number in base 10 (costly) + +int +_len(Class, Math::BigInt::LTM n) + PREINIT: + int len; + char *buf; + CODE: + if (mp_iszero(n) == MP_YES) { + RETVAL = 1; + } + else { + len = mp_unsigned_bin_size(n) * 3 + 2; /* decimal size ~ 3 * bin size +1 for sign +1 for NUL-byte */ + Newz(0, buf, len, char); + mp_toradix_n(n, buf, 10, len); + RETVAL = strlen(buf); + Safefree(buf); + } + OUTPUT: + RETVAL + +############################################################################## +# _alen() - return the approx. length of the number in base 10 (fast) + +int +_alen(Class, Math::BigInt::LTM n) + CODE: + RETVAL = mp_unsigned_bin_size(n) * 3 + 2; /* decimal size ~ 3 * bin size XXX-FIXME very bad estimate */ + OUTPUT: + RETVAL + +############################################################################## +# _zeros() - return number of trailing zeros (in decimal form) + +int +_zeros(Class, Math::BigInt::LTM n) + PREINIT: + int len; + char *buf; + CODE: + if (mp_iszero(n) == MP_YES) { + RETVAL = 0; /* '0' has no trailing zeros! */ + } + else { + len = mp_unsigned_bin_size(n) * 3 + 2; /* decimal size ~ 3 * bin size +1 for sign +1 for NUL-byte */ + Newz(0, buf, len, char); + mp_toradix_n(n, buf, 10, len); + len = strlen(buf); + RETVAL = 0; + while (len > 0) { + if (buf[len-1] != '0') break; + RETVAL++; + len--; + } + Safefree(buf); + } + OUTPUT: + RETVAL + +############################################################################## +# _as_hex() - return ref to hexadecimal string (prefixed with 0x) + +SV * +_as_hex(Class, Math::BigInt::LTM n) + PREINIT: + int i, len; + char *buf; + CODE: + len = mp_unsigned_bin_size(n) * 2 + 3; + RETVAL = newSV(len); + SvPOK_on(RETVAL); + buf = SvPVX(RETVAL); /* get ptr to storage */ + *buf++ = '0'; *buf++ = 'x'; /* prepend '0x' */ + mp_tohex(n, buf); + for (i=0; i<len && buf[i]>0; i++) buf[i] = toLOWER(buf[i]); + SvCUR_set(RETVAL, strlen(buf)+2); /* set real length */ + OUTPUT: + RETVAL + +############################################################################## +# _as_bin() - return ref to binary string (prefixed with 0b) + +SV * +_as_bin(Class, Math::BigInt::LTM n) + PREINIT: + int len; + char *buf; + CODE: + len = mp_unsigned_bin_size(n) * 8 + 3; + RETVAL = newSV(len); + SvPOK_on(RETVAL); + buf = SvPVX(RETVAL); /* get ptr to storage */ + *buf++ = '0'; *buf++ = 'b'; /* prepend '0b' */ + mp_tobinary(n, buf); + SvCUR_set(RETVAL, strlen(buf)+2); /* set real length */ + OUTPUT: + RETVAL + +############################################################################## +# _as_oct() - return ref to octal string (prefixed with 0) + +SV * +_as_oct(Class, Math::BigInt::LTM n) + PREINIT: + int len; + char *buf; + CODE: + len = mp_unsigned_bin_size(n) * 3 + 3; + RETVAL = newSV(len); + SvPOK_on(RETVAL); + buf = SvPVX(RETVAL); + *buf++ = '0'; /* prepend '0' */ + mp_tooctal(n, buf); + SvCUR_set(RETVAL, strlen(buf)+1); /* set real length */ + OUTPUT: + RETVAL + +############################################################################## +# _modpow() - ($n ** $exp) % $mod + +Math::BigInt::LTM +_modpow(Class, Math::BigInt::LTM n, Math::BigInt::LTM exp, Math::BigInt::LTM mod) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + if (mp_cmp_d(mod, 1) == MP_EQ) { + mp_set_int(RETVAL, 0); + } + else { + mp_exptmod(n, exp, mod, RETVAL); + } + OUTPUT: + RETVAL + +############################################################################## +# _modinv() - compute the inverse of x % y + +void +_modinv(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PREINIT: + int rc, sign; + SV* s; + mp_int* RETVAL; + PPCODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + rc = mp_invmod(x, y, RETVAL); + EXTEND(SP, 2); /* we return two values */ + if (rc != MP_OKAY) { + /* Inverse doesn't exist. Return both values undefined. */ + PUSHs(&PL_sv_undef); + PUSHs(&PL_sv_undef); + } + else { + /* Inverse exists. When the modulus to mp_invert() is positive, + * the returned value is also positive. */ + PUSHs(sv_2mortal(sv_from_mpi(RETVAL))); + s = sv_newmortal(); + sv_setpvn(s, "+", 1); + PUSHs(s); + } + +############################################################################## +# _add() - add $y to $x in place + +void +_add(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_add(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _inc() - modify x inline by doing x++ + +void +_inc(Class, Math::BigInt::LTM x) + PPCODE: + mp_add_d(x, 1, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _dec() - modify x inline by doing x-- + +void +_dec(Class, Math::BigInt::LTM x) + PPCODE: + mp_sub_d(x, 1, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _sub() - $x - $y +# $x is always larger than $y! So overflow/underflow can not happen here. + +void +_sub(Class, Math::BigInt::LTM x, Math::BigInt::LTM y, ...) + PPCODE: + if ( items == 4 && SvTRUE(ST(3)) ) { + /* y -= x */ + mp_sub(x, y, y); + XPUSHs(ST(2)); /* y */ + } + else { + /* x -= y */ + mp_sub(x, y, x); + XPUSHs(ST(1)); /* x */ + } + +############################################################################## +# _rsft() + +void +_rsft(Class, Math::BigInt::LTM x, Math::BigInt::LTM y, unsigned long base_int) + PREINIT: + mp_int* BASE; + PPCODE: + Newz(0, BASE, 1, mp_int); + mp_init_set_int(BASE, base_int); + mp_expt_d(BASE, mp_get_long(y), BASE); + mp_div(x, BASE, x, NULL); + mp_clear(BASE); + Safefree(BASE); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _lsft() + +void +_lsft(Class, Math::BigInt::LTM x, Math::BigInt::LTM y, unsigned long base_int) + PREINIT: + mp_int* BASE; + PPCODE: + Newz(0, BASE, 1, mp_int); + mp_init_set_int(BASE, base_int); + mp_expt_d(BASE, mp_get_long(y), BASE); + mp_mul(x, BASE, x); + mp_clear(BASE); + Safefree(BASE); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _mul() + +void +_mul(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_mul(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _div(): x /= y or (x,rem) = x / y + +void +_div(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PREINIT: + mp_int * rem; + PPCODE: + if (GIMME_V == G_ARRAY) { + Newz(0, rem, 1, mp_int); + mp_init(rem); + mp_div(x, y, x, rem); + EXTEND(SP, 2); + PUSHs(ST(1)); /* x */ + PUSHs(sv_2mortal(sv_from_mpi(rem))); + } + else { + mp_div(x, y, x, NULL); + XPUSHs(ST(1)); /* x */ + } + +############################################################################## +# _mod() - x %= y + +void +_mod(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_mod(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _acmp() - cmp two numbers + +int +_acmp(Class, Math::BigInt::LTM m, Math::BigInt::LTM n) + CODE: + RETVAL = mp_cmp(m, n); + if ( RETVAL < 0) RETVAL = -1; + if ( RETVAL > 0) RETVAL = 1; + OUTPUT: + RETVAL + +############################################################################## +# _is_zero() + +int +_is_zero(Class, Math::BigInt::LTM x) + CODE: + RETVAL = (mp_iszero(x) == MP_YES) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _is_one() + +int +_is_one(Class, Math::BigInt::LTM x) + CODE: + RETVAL = (mp_cmp_d(x, 1) == MP_EQ) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _is_two() + +int +_is_two(Class, Math::BigInt::LTM x) + CODE: + RETVAL = (mp_cmp_d(x, 2) == MP_EQ) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _is_ten() + +int +_is_ten(Class, Math::BigInt::LTM x) + CODE: + RETVAL = (mp_cmp_d(x, 10) == MP_EQ) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _pow() - x **= y + +void +_pow(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_expt_d(x, mp_get_long(y), x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _gcd() - gcd(m,n) + +Math::BigInt::LTM +_gcd(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_gcd(x, y, RETVAL); + OUTPUT: + RETVAL + +############################################################################## +# _and() - m &= n + +void +_and(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_and(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _xor() - m =^ n + +void +_xor(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_xor(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _or() - m =| n + +void +_or(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_or(x, y, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _copy() + +Math::BigInt::LTM +_copy(Class, Math::BigInt::LTM m) + CODE: + Newz(0, RETVAL, 1, mp_int); + mp_init(RETVAL); + mp_copy(m, RETVAL); + OUTPUT: + RETVAL + +############################################################################## +# _is_odd() - test for number being odd + +int +_is_odd(Class, Math::BigInt::LTM n) + CODE: + RETVAL = (mp_isodd(n) == MP_YES) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _is_even() - test for number being even + +int +_is_even(Class, Math::BigInt::LTM n) + CODE: + RETVAL = (mp_iseven(n) == MP_YES || mp_iszero(n) == MP_YES) ? 1 : 0; + OUTPUT: + RETVAL + +############################################################################## +# _sqrt() - square root + +void +_sqrt(Class, Math::BigInt::LTM x) + PPCODE: + mp_sqrt(x, x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# _root() - integer roots + +void +_root(Class, Math::BigInt::LTM x, Math::BigInt::LTM y) + PPCODE: + mp_n_root(x, mp_get_long(y), x); + XPUSHs(ST(1)); /* x */ + +############################################################################## +# Storable hooks + +void +STORABLE_thaw(blank_obj, cloning, serialized, ...) + SV *blank_obj + SV *cloning = NO_INIT + SV *serialized + PREINIT: + SV *target, *tmp; + mp_int *mpi; + mp_int *mpitmp; + PPCODE: + if (SvROK(blank_obj) && sv_isa(blank_obj, "Math::BigInt::LTM")) { + Newz(0, mpi, 1, mp_int); + mp_init(mpi); + mp_read_radix(mpi, SvPV_nolen(serialized), 10); + target = SvRV(blank_obj); + SvIV_set(target, PTR2IV(mpi)); + SvIOK_on(target); + PUSHs(target); + XSRETURN(1); + } + else + croak("Bad object for Math::BigInt::LTM::STORABLE_thaw call"); + +SV * +STORABLE_freeze(self, cloning = NULL) + Math::BigInt::LTM self + SV *cloning = NO_INIT + PREINIT: + unsigned long len; + char *buf; + CODE: + if (mp_iszero(self) == MP_YES) { + RETVAL = newSVpv("0", 0); + } + else { + len = mp_unsigned_bin_size(self) * 3 + 2; /* decimal size ~ 3 * bin size +1 for sign +1 for NUL-byte */ + Newz(0, buf, len, char); + mp_toradix_n(self, buf, 10, len); + RETVAL = newSVpv(buf, 0); + Safefree(buf); + } +OUTPUT: + RETVAL |