/* * compute X = (a * X + c) MOD m where c = a */ void m_apm_get_random(M_APM mrnd) { if (M_firsttime2) /* use the system time as the initial seed value */ { M_firsttime2 = FALSE; M_rnd_aa = m_apm_init(); M_rnd_XX = m_apm_init(); M_rnd_mm = m_apm_init(); M_rtmp0 = m_apm_init(); M_rtmp1 = m_apm_init(); /* set the multiplier M_rnd_aa and M_rnd_mm */ m_apm_set_string(M_rnd_aa, "716805947629621"); m_apm_set_string(M_rnd_mm, "1.0E15"); M_get_rnd_seed(M_rnd_XX); } m_apm_multiply(M_rtmp0, M_rnd_XX, M_rnd_aa); m_apm_add(M_rtmp1, M_rtmp0, M_rnd_aa); m_apm_integer_div_rem(M_rtmp0, M_rnd_XX, M_rtmp1, M_rnd_mm); m_apm_copy(mrnd, M_rnd_XX); mrnd->m_apm_exponent -= 15; }
/* * From Knuth, The Art of Computer Programming: * * To compute GCD(u,v) * * A1: * if (v == 0) return (u) * A2: * t = u mod v * u = v * v = t * goto A1 */ void m_apm_gcd_traditional(M_APM r, M_APM u, M_APM v) { M_APM tmpD, tmpN, tmpU, tmpV; tmpD = M_get_stack_var(); tmpN = M_get_stack_var(); tmpU = M_get_stack_var(); tmpV = M_get_stack_var(); m_apm_absolute_value(tmpU, u); m_apm_absolute_value(tmpV, v); while (TRUE) { if (tmpV->m_apm_sign == 0) break; m_apm_integer_div_rem(tmpD, tmpN, tmpU, tmpV); m_apm_copy(tmpU, tmpV); m_apm_copy(tmpV, tmpN); } m_apm_copy(r, tmpU); M_restore_stack(4); }
static int Bidiv(lua_State *L) /** idiv(x,y) */ { M_APM a=Bget(L,1); M_APM b=Bget(L,2); M_APM q=Bnew(L); M_APM r=Bnew(L); m_apm_integer_div_rem(q,r,a,b); return 2; }
/* * functions returns TRUE if the M_APM input number is prime * FALSE if it is not */ int is_number_prime(M_APM input) { int ii, ret, index; char sbuf[32]; /* * for reference: * * table size of 2 to filter multiples of 2 and 3 * table size of 8 to filter multiples of 2, 3 and 5 * table size of 480 to filter multiples of 2,3,5,7, and 11 * * this increment table will filter out all numbers * that are multiples of 2,3,5 and 7. */ static char incr_table[48] = { 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2, 10, 2, 10 }; /* * since the real algorithm starts at 11 (to syncronize * with the increment table), we will cheat for numbers < 10. */ if (m_apm_compare(input, MM_Ten) <= 0) { m_apm_to_integer_string(sbuf, input); ii = atoi(sbuf); if (ii == 2 || ii == 3 || ii == 5 || ii == 7) return(TRUE); else return(FALSE); } ret = FALSE; index = 0; /* * see if the input number is a * multiple of 3, 5, or 7. */ m_apm_integer_div_rem(M_quot, M_rem, input, MM_Three); if (m_apm_sign(M_rem) == 0) /* remainder == 0 */ return(ret); m_apm_integer_div_rem(M_quot, M_rem, input, MM_Five); if (m_apm_sign(M_rem) == 0) return(ret); m_apm_set_long(M_digit, 7L); m_apm_integer_div_rem(M_quot, M_rem, input, M_digit); if (m_apm_sign(M_rem) == 0) return(ret); ii = m_apm_exponent(input) + 16; m_apm_sqrt(M_tmp1, ii, input); m_apm_add(M_limit, MM_Two, M_tmp1); m_apm_set_long(M_digit, 11L); /* now start at '11' to check */ while (TRUE) { if (m_apm_compare(M_digit, M_limit) >= 0) { ret = TRUE; break; } m_apm_integer_div_rem(M_quot, M_rem, input, M_digit); if (m_apm_sign(M_rem) == 0) /* remainder == 0 */ break; m_apm_set_long(M_tmp1, (long)incr_table[index]); m_apm_add(M_tmp0, M_digit, M_tmp1); m_apm_copy(M_digit, M_tmp0); if (++index == 48) index = 0; } return(ret); }
void m_apm_integer_div_rem_mt(M_APM qq, M_APM rr, M_APM aa, M_APM bb) { m_apm_enter(); m_apm_integer_div_rem(qq,rr,aa,bb); m_apm_leave(); }