From 76d6e6518bc2f84486ff366e93556280df09075a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Sun, 17 Nov 1996 03:17:02 +0100 Subject: [PATCH] * modules/gmpmod/mpz_glue.c (mpzmod_digits): new function (mpzmod_create): Can now be called with two args, one string of digits and an integer base. (mpzmod_sqrtrem): new function (mpzmod_gcdext): new function (mpzmod_gcdext2): new function (init_gmpmod_programs): Registered new functions. Fixed powm bug. Rev: src/modules/gmpmod/mpz_glue.c:1.8 --- src/modules/gmpmod/mpz_glue.c | 239 +++++++++++++++++++++++++++++----- 1 file changed, 203 insertions(+), 36 deletions(-) diff --git a/src/modules/gmpmod/mpz_glue.c b/src/modules/gmpmod/mpz_glue.c index 6d7490acad..e5402e6c93 100644 --- a/src/modules/gmpmod/mpz_glue.c +++ b/src/modules/gmpmod/mpz_glue.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mpz_glue.c,v 1.7 1996/11/14 01:36:34 hubbe Exp $"); +RCSID("$Id: mpz_glue.c,v 1.8 1996/11/17 02:17:02 nisse Exp $"); #include "gmp_machine.h" #include "types.h" @@ -25,48 +25,100 @@ RCSID("$Id: mpz_glue.c,v 1.7 1996/11/14 01:36:34 hubbe Exp $"); #include "pike_types.h" #include <gmp.h> - +#include <assert.h> #define THIS ((MP_INT *)(fp->current_storage)) #define OBTOMPZ(o) ((MP_INT *)(o->storage)) static struct program *mpzmod_program; -static void get_new_mpz(MP_INT *tmp, struct svalue *s) +static void get_mpz_from_digits(MP_INT *tmp, + struct svalue *s, struct svalue *b) { - switch(s->type) - { - case T_INT: - mpz_set_si(tmp, (signed long int) s->u.integer); - break; - - case T_FLOAT: - mpz_set_d(tmp, (double) s->u.float_number); - break; - - case T_STRING: - mpz_set_str(tmp, s->u.string->str, 0); - break; + INT32 base; + struct pike_string *digits; - case T_OBJECT: - if(s->u.object->prog != mpzmod_program) - error("Wrong type of object, cannot convert to mpz.\n"); + if ((s->type != T_STRING) || (b->type != T_INT)) + error("wrong types, cannot convert to mpz"); - mpz_set(tmp, OBTOMPZ(s->u.object)); - break; + digits = s->u.string; + base = b->u.integer; + + if ((base >= 2) && (base <= 36)) + { + if (mpz_set_str(tmp, digits->str, base)) + error("invalid digits, cannot convert to mpz"); + } + else if (base == 256) + { + + INT8 i; + mpz_t digit; + + mpz_init(digit); + mpz_set_ui(tmp, 0); + for (i = 0; i < digits->len; i++) + { + mpz_set_ui(digit, EXTRACT_UCHAR(digits->str + i)); + mpz_mul_2exp(digit, digit, (digits->len - i - 1) * 8); + mpz_ior(tmp, tmp, digit); + } + } + else + error("invalid base.\n"); +} + +static void get_new_mpz(MP_INT *tmp, struct svalue *s) +{ + switch(s->type) + { + case T_INT: + mpz_set_si(tmp, (signed long int) s->u.integer); + break; - default: - error("Bad argument 1 to mpz->create()\n"); - } + case T_FLOAT: + mpz_set_d(tmp, (double) s->u.float_number); + break; + + case T_OBJECT: + if(s->u.object->prog != mpzmod_program) + error("Wrong type of object, cannot convert to mpz.\n"); + + mpz_set(tmp, OBTOMPZ(s->u.object)); + break; +#if 0 + case T_STRING: + mpz_set_str(tmp, s->u.string->str, 0); + break; + + case T_ARRAY: /* Experimental */ + if ( (s->u.array->size != 2) + || (ITEM(s->u.array)[0].type != T_STRING) + || (ITEM(s->u.array)[1].type != T_INT)) + error("cannot convert array to mpz.\n"); + get_mpz_from_digits(tmp, ITEM(s->u.array)[0].u.string, + ITEM(s->u.array)[1]); + break; +#endif + default: + error("cannot convert argument to mpz.\n"); + } } static void mpzmod_create(INT32 args) { - if(args) - { - get_new_mpz(THIS, sp-args); - pop_n_elems(args); - } + switch(args) + { + case 1: + get_new_mpz(THIS, sp-args); + break; + case 2: /* Args are string of digits and integer base */ + if ((sp-args)->type != T_STRING) + error("wrong type, invalid string of digits"); + get_mpz_from_digits(THIS, sp-args, sp-args+1); + break; + } + pop_n_elems(args); } static void mpzmod_get_int(INT32 args) @@ -102,6 +154,51 @@ static void mpzmod_get_string(INT32 args) push_string(s); } +static void mpzmod_digits(INT32 args) +{ + int base; + struct pike_string *s; + INT32 len; + + base = sp[-args].u.integer; + if ( (base >= 2) && (base <= 36)) + { + len = mpz_sizeinbase(THIS, base) + 2; + s = begin_shared_string(len); + mpz_get_str(s->str, base, THIS); + /* Find NULL character */ + len-=4; + if (len < 0) len = 0; + while(s->str[len]) len++; + s->len=len; + s=end_shared_string(s); + } + else if (base == 256) + { + INT8 i; + mpz_t tmp; + + if (mpz_sgn(THIS) < 0) + error("only non-negative numbers can be converted to base 256.\n"); + len = (mpz_sizeinbase(THIS, 2) + 7) / 8; + s = begin_shared_string(len); + mpz_init_set(tmp, THIS); + for (i = len - 1; i>= 0; i-- ) + { + s->str[i] = mpz_get_ui(tmp) & 0xff; + mpz_tdiv_q_2exp(tmp, tmp, 8); + } + assert(mpz_sgn(tmp) == 0); + mpz_clear(tmp); + s = end_shared_string(s); + } + else + error("invalid base.\n"); + + pop_n_elems(args); + push_string(s); +} + static void mpzmod_cast(INT32 args) { if(args < 1) @@ -167,7 +264,10 @@ static MP_INT *get_mpz(struct svalue *s) case T_INT: case T_FLOAT: +#if 0 case T_STRING: + case T_ARRAY: +#endif o=clone(mpzmod_program,0); get_new_mpz(OBTOMPZ(o), s); free_svalue(s); @@ -269,6 +369,38 @@ static void mpzmod_mod(INT32 args) return_temporary(args); } +static void mpzmod_gcdext(INT32 args) +{ + struct object *g, *s, *t; + MP_INT *a; + + a = get_mpz(sp-args); + + g = clone(mpzmod_program, 0); + s = clone(mpzmod_program, 0); + t = clone(mpzmod_program, 0); + + mpz_gcdext(OBTOMPZ(g), OBTOMPZ(s), OBTOMPZ(t), THIS, a); + pop_n_elems(args); + push_object(g); push_object(s); push_object(t); + f_aggregate(3); +} + +static void mpzmod_gcdext2(INT32 args) +{ + struct object *g, *s; + MP_INT *a; + + a = get_mpz(sp-args); + + g = clone(mpzmod_program, 0); + s = clone(mpzmod_program, 0); + + mpz_gcdext(OBTOMPZ(g), OBTOMPZ(s), NULL, THIS, a); + pop_n_elems(args); + push_object(g); push_object(s); + f_aggregate(2); +} BINFUN(mpzmod_and,mpz_and) BINFUN(mpzmod_or,mpz_ior) @@ -325,6 +457,21 @@ static void mpzmod_sqrt(INT32 args) mpz_sqrt(OBTOMPZ(o), THIS); } +static void mpzmod_sqrtrem(INT32 args) +{ + struct object *root, *rem; + + pop_n_elems(args); + if(mpz_sgn(THIS)<0) + error("mpz->sqrtrem() on negative number.\n"); + + root = clone(mpzmod_program,0); + rem = clone(mpzmod_program,0); + mpz_sqrtrem(OBTOMPZ(root), OBTOMPZ(rem), THIS); + push_object(root); push_object(rem); + f_aggregate(2); +} + static void mpzmod_lsh(INT32 args) { MP_INT *tmp; @@ -396,9 +543,12 @@ void init_gmpmod_programs(void) start_new_program(); add_storage(sizeof(MP_INT)); - add_function("create",mpzmod_create,"function(void|string|int|float|object:void)",0); + add_function("create", mpzmod_create, + "function(void|string|int|float|object:void)" + "|function(string,int:void)", 0); -#define MPZ_BINOP_TYPE "function(string|int|float|object...:object)" +#define MPZ_ARG_TYPE "int|float|object" +#define MPZ_BINOP_TYPE ("function(" MPZ_ARG_TYPE "...:object)") add_function("`+",mpzmod_add,MPZ_BINOP_TYPE,0); add_function("`-",mpzmod_sub,MPZ_BINOP_TYPE,0); @@ -408,11 +558,11 @@ void init_gmpmod_programs(void) add_function("`&",mpzmod_and,MPZ_BINOP_TYPE,0); add_function("`|",mpzmod_or,MPZ_BINOP_TYPE,0); -#define MPZ_SHIFT_TYPE "function(object|int|float|object:object)" +#define MPZ_SHIFT_TYPE "function(int|float|object:object)" add_function("`<<",mpzmod_lsh,MPZ_SHIFT_TYPE,0); add_function("`>>",mpzmod_rsh,MPZ_SHIFT_TYPE,0); -#define MPZ_CMPOP_TYPE "function(string|int|float|object:int)" +#define MPZ_CMPOP_TYPE ("function(" MPZ_ARG_TYPE ":int)") add_function("`>", mpzmod_gt,MPZ_CMPOP_TYPE,0); add_function("`<", mpzmod_lt,MPZ_CMPOP_TYPE,0); @@ -427,16 +577,33 @@ void init_gmpmod_programs(void) add_function("__hash",mpzmod_get_int,"function(:int)",0); add_function("cast",mpzmod_cast,"function(string:mixed)",0); + add_function("digits", mpzmod_digits, "function(int:string)", 0); add_function("cast_to_int",mpzmod_get_int,"function(:int)",0); add_function("cast_to_string",mpzmod_get_string,"function(:string)",0); add_function("cast_to_float",mpzmod_get_float,"function(:float)",0); add_function("probably_prime_p",mpzmod_probably_prime_p,"function(:int)",0); - add_function("gcd",mpzmod_gcd,"function(object|string|int|float...:object)",0); + add_function("gcd",mpzmod_gcd, MPZ_BINOP_TYPE, 0); + add_function("gcdext", mpzmod_gcdext, + "function(" MPZ_ARG_TYPE "," MPZ_ARG_TYPE ":array(object))", 0); + add_function("gcdext2", mpzmod_gcdext2, + "function(" MPZ_ARG_TYPE "," MPZ_ARG_TYPE ":array(object))", 0); add_function("sqrt",mpzmod_gcd,"function(:object)",0); + add_function("sqrtrem", mpzmod_sqrtrem, "function(:array(object))", 0); add_function("`~",mpzmod_gcd,"function(:object)",0); - add_function("powm",mpzmod_powm,"function(object|string|int|float,object|string|int|float:object)",0); - + add_function("powm",mpzmod_powm, + "function(" MPZ_ARG_TYPE "," MPZ_ARG_TYPE ":object)", 0); +#if 0 + /* These are not implemented yet */ + add_function("squarep", mpzmod_squarep, "function(:int)", 0); + add_function("divmod", mpzmod_divmod, "function(" MPZ_ARG_TYPE ":array(object))", 0); + add_function("pow", mpzmod_pow, "function(int:object)", 0); + add_function("divm", mpzmod_divm, "function(string|int|float|object, string|int|float|object:object)", 0); + add_function("invert", mpzmod_invert, "function(:object)", 0); + add_function("size_in_base", mpz_size, "function(:int)", 0); + add_efun("mpz_pow", mpz_pow, "function(int, int)", 0); + add_efun("mpz_fac", mpz_fac, "function(int|object:object)", 0); +#endif set_init_callback(init_mpz_glue); set_exit_callback(exit_mpz_glue); -- GitLab