fda0de1999-10-08Fredrik Noring #include "global.h" #ifdef AUTO_BIGNUM #include "interpret.h" #include "program.h" #include "object.h" #include "svalue.h" #include "error.h"
e37a3e1999-10-09Fredrik Hübinette (Hubbe) struct svalue auto_bignum_program = { T_INT };
e28b471999-10-25Fredrik Hübinette (Hubbe) int gmp_library_loaded=0;
3905cf1999-11-11Fredrik Hübinette (Hubbe) int gmp_library_resolving=0;
e28b471999-10-25Fredrik Hübinette (Hubbe) 
e37a3e1999-10-09Fredrik Hübinette (Hubbe) static void resolve_auto_bignum_program(void)
fda0de1999-10-08Fredrik Noring {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  if(auto_bignum_program.type == T_INT) {
3905cf1999-11-11Fredrik Hübinette (Hubbe)  gmp_library_resolving=1;
0957531999-10-25Fredrik Hübinette (Hubbe)  push_text("Gmp.bignum");
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  SAFE_APPLY_MASTER("resolv", 1); if(sp[-1].type != T_FUNCTION) error("Failed to resolv Gmp.mpz!\n"); auto_bignum_program=sp[-1]; sp--;
e801bb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
3905cf1999-11-11Fredrik Hübinette (Hubbe)  gmp_library_resolving=0;
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  } }
fda0de1999-10-08Fredrik Noring 
8852cb1999-10-25Fredrik Hübinette (Hubbe) struct program *get_auto_bignum_program(void) { resolve_auto_bignum_program(); return program_from_function(&auto_bignum_program); } struct program *get_auto_bignum_program_or_zero(void) {
3905cf1999-11-11Fredrik Hübinette (Hubbe)  if(!gmp_library_loaded || gmp_library_resolving) return 0;
8852cb1999-10-25Fredrik Hübinette (Hubbe)  resolve_auto_bignum_program(); return program_from_function(&auto_bignum_program); }
e37a3e1999-10-09Fredrik Hübinette (Hubbe) void exit_auto_bignum(void) { free_svalue(&auto_bignum_program); auto_bignum_program.type=T_INT;
fda0de1999-10-08Fredrik Noring }
e37a3e1999-10-09Fredrik Hübinette (Hubbe) void convert_stack_top_to_bignum(void) { resolve_auto_bignum_program(); apply_svalue(&auto_bignum_program, 1);
fda0de1999-10-08Fredrik Noring 
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  if(sp[-1].type != T_OBJECT) error("Gmp.mpz conversion failed.\n"); }
fda0de1999-10-08Fredrik Noring 
31ea271999-10-22Fredrik Noring void convert_stack_top_with_base_to_bignum(void) { resolve_auto_bignum_program(); apply_svalue(&auto_bignum_program, 2); if(sp[-1].type != T_OBJECT) error("Gmp.mpz conversion failed.\n"); }
39ac731999-10-20Fredrik Noring int is_bignum_object(struct object *o) {
e28b471999-10-25Fredrik Hübinette (Hubbe)  /* Note: * This function should *NOT* try to resolv Gmp.mpz unless * it is already loaded into memory. * /Hubbe */
3905cf1999-11-11Fredrik Hübinette (Hubbe)  if(!gmp_library_loaded || gmp_library_resolving) return 0; /* not possible */
e28b471999-10-25Fredrik Hübinette (Hubbe) 
39ac731999-10-20Fredrik Noring  resolve_auto_bignum_program(); return o->prog == program_from_function(&auto_bignum_program); } int is_bignum_object_in_svalue(struct svalue *sv) { return sv->type == T_OBJECT && is_bignum_object(sv->u.object); }
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  struct object *make_bignum_object(void)
fda0de1999-10-08Fredrik Noring {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  convert_stack_top_to_bignum();
39ac731999-10-20Fredrik Noring  return (--sp)->u.object;
e37a3e1999-10-09Fredrik Hübinette (Hubbe) } struct object *bignum_from_svalue(struct svalue *s) { push_svalue(s); convert_stack_top_to_bignum();
39ac731999-10-20Fredrik Noring  return (--sp)->u.object;
fda0de1999-10-08Fredrik Noring }
ff0d461999-10-15Fredrik Noring struct pike_string *string_from_bignum(struct object *o, int base) { push_int(base); safe_apply(o, "digits", 1); if(sp[-1].type != T_STRING) error("Gmp.mpz string conversion failed.\n"); return (--sp)->u.string; }
e37a3e1999-10-09Fredrik Hübinette (Hubbe) void convert_svalue_to_bignum(struct svalue *s)
fda0de1999-10-08Fredrik Noring {
e37a3e1999-10-09Fredrik Hübinette (Hubbe)  push_svalue(s); convert_stack_top_to_bignum(); free_svalue(s); *s=sp[-1];
fda0de1999-10-08Fredrik Noring  sp--;
e801bb1999-10-24Henrik Grubbström (Grubba)  dmalloc_touch_svalue(sp);
fda0de1999-10-08Fredrik Noring }
bd35ec1999-10-30Fredrik Noring #ifdef INT64 /* These routines can be made much more optimized. */
2fe5651999-10-29Fredrik Noring #define BIGNUM_INT64_MASK 0xffff #define BIGNUM_INT64_SHIFT 16 void push_int64(INT64 i) { if(i == (INT_TYPE)i) { push_int((INT_TYPE)i); } else { int neg, pos, lshfun, orfun; neg = (i < 0); if(neg) i = ~i; push_int(i & BIGNUM_INT64_MASK); i >>= BIGNUM_INT64_SHIFT; convert_stack_top_to_bignum(); lshfun = FIND_LFUN(sp[-1].u.object->prog, LFUN_LSH); orfun = FIND_LFUN(sp[-1].u.object->prog, LFUN_OR); for(pos = BIGNUM_INT64_SHIFT; i; pos += BIGNUM_INT64_SHIFT) { push_int(i & BIGNUM_INT64_MASK); i >>= BIGNUM_INT64_SHIFT; convert_stack_top_to_bignum(); push_int(pos); apply_low(sp[-2].u.object, lshfun, 1); stack_swap(); pop_stack(); apply_low(sp[-2].u.object, orfun, 1); stack_swap(); pop_stack();
bd35ec1999-10-30Fredrik Noring  if(sp[-1].type == T_INT) convert_stack_top_to_bignum();
2fe5651999-10-29Fredrik Noring  } if(neg) apply_low(sp[-1].u.object,FIND_LFUN(sp[-1].u.object->prog,LFUN_COMPL),0); } } int int64_from_bignum(INT64 *i, struct object *bignum) { int neg, pos, rshfun, andfun; *i = 0; push_int(0); apply_low(bignum, FIND_LFUN(bignum->prog, LFUN_LT), 1); if(sp[-1].type != T_INT) error("Result from Gmp.bignum->`< not an integer.\n"); neg = (--sp)->u.integer; if(neg) apply_low(bignum, FIND_LFUN(bignum->prog, LFUN_COMPL), 0); rshfun = FIND_LFUN(bignum->prog, LFUN_RSH); andfun = FIND_LFUN(bignum->prog, LFUN_AND); ref_push_object(bignum); for(pos = 0; sp[-1].type != T_INT; ) { push_int(BIGNUM_INT64_MASK); apply_low(sp[-2].u.object, andfun, 1); if(sp[-1].type != T_INT) error("Result from Gmp.bignum->`& not an integer.\n"); *i |= (INT64)(--sp)->u.integer << (INT64)pos; pos += BIGNUM_INT64_SHIFT; push_int(BIGNUM_INT64_SHIFT); apply_low(sp[-2].u.object, rshfun, 1); stack_swap(); pop_stack(); } *i |= (INT64)(--sp)->u.integer << (INT64)pos; if(neg) *i = ~*i;
bd35ec1999-10-30Fredrik Noring 
2fe5651999-10-29Fredrik Noring  return 1; /* We may someday return 0 if the conversion fails. */ }
856cff1999-10-29Fredrik Noring #endif /* INT64 */
2fe5651999-10-29Fredrik Noring 
fda0de1999-10-08Fredrik Noring #endif /* AUTO_BIGNUM */