// Mod operator: use divide or mp_mod_d? mp_digit operator%(Mpi &a, mp_digit i){ mp_digit j=0; // Here, to detect a divide error, the program should check the // "err" member variable in the object "a". a.err=mp_div_d(&(a.mpi_n),i,NULL,&j); return j; }
/* returns size of ASCII reprensentation */ int mp_radix_size (mp_int * a, int radix, int *size) { int res, digs; mp_int t; mp_digit d; *size = 0; /* special case for binary */ if (radix == 2) { *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; return MP_OKAY; } /* make sure the radix is in range */ if (radix < 2 || radix > 64) { return MP_VAL; } if (mp_iszero(a) == MP_YES) { *size = 2; return MP_OKAY; } /* digs is the digit count */ digs = 0; /* if it's negative add one for the sign */ if (a->sign == MP_NEG) { ++digs; } /* init a copy of the input */ if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } /* force temp to positive */ t.sign = MP_ZPOS; /* fetch out all of the digits */ while (mp_iszero (&t) == MP_NO) { if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear (&t); return res; } ++digs; } mp_clear (&t); /* return digs + 1, the 1 is for the NULL byte that would be required. */ *size = digs + 1; return MP_OKAY; }
/* stores a bignum as a ASCII string in a given radix (2..64) */ int mp_toradix(mp_int * a, char *str, int radix) { int res, digs; mp_int t; mp_digit d; char *_s = str; if (radix < 2 || radix > 64) { return MP_VAL; } /* quick out if its zero */ if (mp_iszero(a) == 1) { *str++ = '0'; *str = '\0'; return MP_OKAY; } if ((res = mp_init_copy(&t, a)) != MP_OKAY) { return res; } /* if it is negative output a - */ if (t.sign == MP_NEG) { ++_s; *str++ = '-'; t.sign = MP_ZPOS; } digs = 0; while (mp_iszero(&t) == 0) { if ((res = mp_div_d(&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear(&t); return res; } *str++ = mp_s_rmap[d]; ++digs; } /* reverse the digits of the string. In this case _s points * to the first digit [exluding the sign] of the number] */ bn_reverse((unsigned char *) _s, digs); /* append a NULL so the string is properly terminated */ *str++ = '\0'; mp_clear(&t); return MP_OKAY; }
int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) { return mp_div_d(a, b, NULL, c); }
/* stores a bignum as a ASCII string in a given radix (2..64) * * Stores upto maxlen-1 chars and always a NULL byte */ int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen) { int res, digs; mp_int t; mp_digit d; char *_s = str; /* check range of the maxlen, radix */ if (maxlen < 2 || radix < 2 || radix > 64) { return MP_VAL; } /* quick out if its zero */ if (mp_iszero(a) == MP_YES) { *str++ = '0'; *str = '\0'; return MP_OKAY; } if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } /* if it is negative output a - */ if (t.sign == MP_NEG) { /* we have to reverse our digits later... but not the - sign!! */ ++_s; /* store the flag and mark the number as positive */ *str++ = '-'; t.sign = MP_ZPOS; /* subtract a char */ --maxlen; } digs = 0; while (mp_iszero (&t) == 0) { if (--maxlen < 1) { /* no more room */ break; } if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear (&t); return res; } *str++ = mp_s_rmap[d]; ++digs; } /* reverse the digits of the string. In this case _s points * to the first digit [exluding the sign] of the number */ bn_reverse ((unsigned char *)_s, digs); /* append a NULL so the string is properly terminated */ *str = '\0'; mp_clear (&t); return MP_OKAY; }
static int TestbignumobjCmd( ClientData clientData, /* unused */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Argument count */ Tcl_Obj *const objv[]) /* Argument vector */ { const char *const subcmds[] = { "set", "get", "mult10", "div10", NULL }; enum options { BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10 }; int index, varIndex; const char *string; mp_int bignumValue, newValue; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } string = Tcl_GetString(objv[2]); if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) { return TCL_ERROR; } switch (index) { case BIGNUM_SET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "var value"); return TCL_ERROR; } string = Tcl_GetString(objv[3]); if (mp_init(&bignumValue) != MP_OKAY) { Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_init", -1)); return TCL_ERROR; } if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) { mp_clear(&bignumValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_read_radix", -1)); return TCL_ERROR; } /* * If the object currently bound to the variable with index varIndex * has ref count 1 (i.e. the object is unshared) we can modify that * object directly. Otherwise, if RC>1 (i.e. the object is shared), * we must create a new object to modify/set and decrement the old * formerly-shared object's ref count. This is "copy on write". */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); } else { SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue)); } break; case BIGNUM_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } break; case BIGNUM_MULT10: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } if (mp_init(&newValue) != MP_OKAY || (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) { mp_clear(&bignumValue); mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_mul_d", -1)); return TCL_ERROR; } mp_clear(&bignumValue); if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); } break; case BIGNUM_DIV10: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); return TCL_ERROR; } if (CheckIfVarUnset(interp, varIndex)) { return TCL_ERROR; } if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], &bignumValue) != TCL_OK) { return TCL_ERROR; } if (mp_init(&newValue) != MP_OKAY || (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) { mp_clear(&bignumValue); mp_clear(&newValue); Tcl_SetObjResult(interp, Tcl_NewStringObj("error in mp_div_d", -1)); return TCL_ERROR; } mp_clear(&bignumValue); if (!Tcl_IsShared(varPtr[varIndex])) { Tcl_SetBignumObj(varPtr[varIndex], &newValue); } else { SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); } } Tcl_SetObjResult(interp, varPtr[varIndex]); return TCL_OK; }
int mp_toom_cook_5_mul(mp_int *a, mp_int *b, mp_int *c) { mp_int w1, w2, w3, w4, w5, w6, w7, w8, w9; mp_int tmp1, tmp2; mp_int a0, a1, a2, a3, a4; mp_int b0, b1, b2, b3, b4; int e = MP_OKAY; int B, count, sign; B = (MAX(a->used, b->used)) / 5; sign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS; if (MIN(a->used, b->used) < TOOM_COOK_5_MUL_CO) { if ((e = mp_mul(a, b, c)) != MP_OKAY) { return e; } c->sign = sign; return MP_OKAY; } if ((e = mp_init_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2, //&a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4, NULL)) != MP_OKAY) { goto ERR0; //goto ERR; } if ((e = mp_init_size(&a0, B)) != MP_OKAY) { goto ERRa0; } if ((e = mp_init_size(&a1, B)) != MP_OKAY) { goto ERRa1; } if ((e = mp_init_size(&a2, B)) != MP_OKAY) { goto ERRa2; } if ((e = mp_init_size(&a3, B)) != MP_OKAY) { goto ERRa3; } if ((e = mp_init_size(&a4, B)) != MP_OKAY) { goto ERRa4; } if ((e = mp_init_size(&b0, B)) != MP_OKAY) { goto ERRb0; } if ((e = mp_init_size(&b1, B)) != MP_OKAY) { goto ERRb1; } if ((e = mp_init_size(&b2, B)) != MP_OKAY) { goto ERRb2; } if ((e = mp_init_size(&b3, B)) != MP_OKAY) { goto ERRb3; } if ((e = mp_init_size(&b4, B)) != MP_OKAY) { goto ERRb4; } // A = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0 for (count = 0; count < a->used; count++) { switch (count / B) { case 0: a0.dp[count] = a->dp[count]; a0.used++; break; case 1: a1.dp[count - B] = a->dp[count]; a1.used++; break; case 2: a2.dp[count - 2 * B] = a->dp[count]; a2.used++; break; case 3: a3.dp[count - 3 * B] = a->dp[count]; a3.used++; break; case 4: a4.dp[count - 4 * B] = a->dp[count]; a4.used++; break; default: a4.dp[count - 4 * B] = a->dp[count]; a4.used++; break; } } mp_clamp(&a0); mp_clamp(&a1); mp_clamp(&a2); mp_clamp(&a3); mp_clamp(&a4); // B = b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0 for (count = 0; count < b->used; count++) { switch (count / B) { case 0: b0.dp[count] = b->dp[count]; b0.used++; break; case 1: b1.dp[count - B] = b->dp[count]; b1.used++; break; case 2: b2.dp[count - 2 * B] = b->dp[count]; b2.used++; break; case 3: b3.dp[count - 3 * B] = b->dp[count]; b3.used++; break; case 4: b4.dp[count - 4 * B] = b->dp[count]; b4.used++; break; default: b4.dp[count - 4 * B] = b->dp[count]; b4.used++; break; } } mp_clamp(&b0); mp_clamp(&b1); mp_clamp(&b2); mp_clamp(&b3); mp_clamp(&b4); /* if ((e = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { goto ERR; } if ((e = mp_copy(a, &a1)) != MP_OKAY) { goto ERR; } mp_rshd(&a1, B); mp_mod_2d(&a1, DIGIT_BIT * B, &a1); if ((e = mp_copy(a, &a2)) != MP_OKAY) { goto ERR; } mp_rshd(&a2, B * 2); mp_mod_2d(&a2, DIGIT_BIT * B, &a2); if ((e = mp_copy(a, &a3)) != MP_OKAY) { goto ERR; } mp_rshd(&a3, B * 3); mp_mod_2d(&a3, DIGIT_BIT * B, &a3); if ((e = mp_copy(a, &a4)) != MP_OKAY) { goto ERR; } mp_rshd(&a4, B * 4); if ((e = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { goto ERR; } if ((e = mp_copy(a, &b1)) != MP_OKAY) { goto ERR; } mp_rshd(&b1, B); mp_mod_2d(&b1, DIGIT_BIT * B, &b1); if ((e = mp_copy(b, &b2)) != MP_OKAY) { goto ERR; } mp_rshd(&b2, B * 2); mp_mod_2d(&b2, DIGIT_BIT * B, &b2); if ((e = mp_copy(b, &b3)) != MP_OKAY) { goto ERR; } mp_rshd(&b3, B * 3); mp_mod_2d(&b3, DIGIT_BIT * B, &b3); if ((e = mp_copy(b, &b4)) != MP_OKAY) { goto ERR; } mp_rshd(&b4, B * 4); */ // S1 = a4*b4 if ((e = mp_mul(&a4, &b4, &w1)) != MP_OKAY) { goto ERR; } // S9 = a0*b0 if ((e = mp_mul(&a0, &b0, &w9)) != MP_OKAY) { goto ERR; } // S2 = (a0- 2*a1 +4*a2 -8*a3 +16*a4) if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) { goto ERR; } // 2*a1 = tmp1 if ((e = mp_sub(&a0, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 = a0 - tmp1 = w2 if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } // 4*a2 = tmp1 if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 = w2 + tmp1 = w2 if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) { goto ERR; } // 8*a3 = tmp1 if ((e = mp_sub(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 -8*a3 = w2 - tmp1 = w2 if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) { goto ERR; } // 16*a4 = tmp1 if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) { goto ERR; } // a0- 2*a1 +4*a2 -8*a3 +16*a4 = w2 + tmp1 = w2 // * (b0- 2*b1 +4*b2 -8*b3 +16*b4) if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w2, &w2)) != MP_OKAY) { goto ERR; } // S5 = (a0+ 2*a1+ 4*a2+ 8*a3+ 16*a4) if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a0, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // *(b0+ 2*b1+ 4*b2+ 8*b3+ 16*b4) if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w5, &w5)) != MP_OKAY) { goto ERR; } // S3 = (a4+ 2*a3+ 4*a2+ 8*a1+ 16*a0) if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a4, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } // * (b4+ 2*b3+ 4*b2+ 8*b1+ 16*b0) if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b4, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w3, &w3)) != MP_OKAY) { goto ERR; } // S8 = (a4- 2*a3+ 4*a2- 8*a1+ 16*a0) if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&a4, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } //* (b4- 2*b3+ 4*b2- 8*b1+ 16*b0) if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&b4, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w8, &w8)) != MP_OKAY) { goto ERR; } // S4 = (a0+ 4*a1+ 16*a2+ 64*a3+ 256*a4) if ((e = mp_mul_2d(&a1, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&a0, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a2, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a3, 6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&a4, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } //* (b0+ 4*b1+ 16*b2+ 64*b3+ 256*b4) if ((e = mp_mul_2d(&b1, 2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b2, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b3, 6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul_2d(&b4, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp2, &w4, &w4)) != MP_OKAY) { goto ERR; } // S6 = (a0- a1+ a2- a3 +a4) if ((e = mp_sub(&a0, &a1, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w6, &a2, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w6, &a3, &w6)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w6, &a4, &w6)) != MP_OKAY) { goto ERR; } // * (b0- b1+ b2- b3+ b4) if ((e = mp_sub(&b0, &b1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&tmp1, &b3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp1, &w6, &w6)) != MP_OKAY) { goto ERR; } // S7 = (a0+ a1+ a2+ a3+ a4) if ((e = mp_add(&a0, &a1, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a2, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a3, &w7)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w7, &a4, &w7)) != MP_OKAY) { goto ERR; } // * (b0+ b1+ b2+ b3+ b4) if ((e = mp_add(&b0, &b1, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_mul(&tmp1, &w7, &w7)) != MP_OKAY) { goto ERR; } // S6 -= S7 if ((e = mp_sub(&w6, &w7, &w6)) != MP_OKAY) { goto ERR; } // S2 -= S5 if ((e = mp_sub(&w2, &w5, &w2)) != MP_OKAY) { goto ERR; } // S4 -= S9 if ((e = mp_sub(&w4, &w9, &w4)) != MP_OKAY) { goto ERR; } // S4 -= (2^16*S1) if ((e = mp_mul_2d(&w1, 16, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S8 -= S3 if ((e = mp_sub(&w8, &w3, &w8)) != MP_OKAY) { goto ERR; } // S6 /= 2 if ((e = mp_div_2d(&w6, 1, &w6, NULL)) != MP_OKAY) { goto ERR; } // S5 *= 2 if ((e = mp_mul_2d(&w5, 1, &w5)) != MP_OKAY) { goto ERR; } // S5 += S2 if ((e = mp_add(&w5, &w2, &w5)) != MP_OKAY) { goto ERR; } // S2 = -S2 if ((e = mp_neg(&w2, &w2)) != MP_OKAY) { goto ERR; } // S8 = -S8 if ((e = mp_neg(&w8, &w8)) != MP_OKAY) { goto ERR; } // S7 += S6 if ((e = mp_add(&w7, &w6, &w7)) != MP_OKAY) { goto ERR; } // S6 = -S6 if ((e = mp_neg(&w6, &w6)) != MP_OKAY) { goto ERR; } // S3 -= S7 if ((e = mp_sub(&w3, &w7, &w3)) != MP_OKAY) { goto ERR; } // S5 -= (512*S7) if ((e = mp_mul_2d(&w7, 9, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // S3 *= 2 if ((e = mp_mul_2d(&w3, 1, &w3)) != MP_OKAY) { goto ERR; } // S3 -= S8 if ((e = mp_sub(&w3, &w8, &w3)) != MP_OKAY) { goto ERR; } // S7 -= S1 if ((e = mp_sub(&w7, &w1, &w7)) != MP_OKAY) { goto ERR; } // S7 -= S9 if ((e = mp_sub(&w7, &w9, &w7)) != MP_OKAY) { goto ERR; } // S8 += S2 if ((e = mp_add(&w8, &w2, &w8)) != MP_OKAY) { goto ERR; } // S5 += S3 if ((e = mp_add(&w5, &w3, &w5)) != MP_OKAY) { goto ERR; } // S8 -= (80*S6) if ((e = mp_mul_d(&w6, 80, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) { goto ERR; } // S3 -= (510*S9) if ((e = mp_mul_d(&w9, 510, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { goto ERR; } // S4 -= S2 if ((e = mp_sub(&w4, &w2, &w4)) != MP_OKAY) { goto ERR; } // S3 *= 3 if ((e = mp_mul_d(&w3, 3, &w3)) != MP_OKAY) { goto ERR; } // S3 += S5 if ((e = mp_add(&w3, &w5, &w3)) != MP_OKAY) { goto ERR; } // S8 /= 180 \\ division by 180 if ((e = mp_div_d(&w8, 180, &w8, NULL)) != MP_OKAY) { goto ERR; } // S5 += (378*S7) if ((e = mp_mul_d(&w7, 378, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) { goto ERR; } // S2 /= 4 if ((e = mp_div_2d(&w2, 2, &w2, NULL)) != MP_OKAY) { goto ERR; } // S6 -= S2 if ((e = mp_sub(&w6, &w2, &w6)) != MP_OKAY) { goto ERR; } // S5 /= (-72) \\ division by -72 if ((e = mp_div_d(&w5, 72, &w5, NULL)) != MP_OKAY) { goto ERR; } if (&w5.sign == MP_ZPOS) (&w5)->sign = MP_NEG; (&w5)->sign = MP_ZPOS; // S3 /= (-360) \\ division by -360 if ((e = mp_div_d(&w3, 360, &w3, NULL)) != MP_OKAY) { goto ERR; } if (&w3.sign == MP_ZPOS) (&w3)->sign = MP_NEG; (&w3)->sign = MP_ZPOS; // S2 -= S8 if ((e = mp_sub(&w2, &w8, &w2)) != MP_OKAY) { goto ERR; } // S7 -= S3 if ((e = mp_sub(&w7, &w3, &w7)) != MP_OKAY) { goto ERR; } // S4 -= (256*S5) if ((e = mp_mul_2d(&w5, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S3 -= S5 if ((e = mp_sub(&w3, &w5, &w3)) != MP_OKAY) { goto ERR; } // S4 -= (4096*S3) if ((e = mp_mul_2d(&w3, 12, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 -= (16*S7) if ((e = mp_mul_2d(&w7, 4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 += (256*S6) if ((e = mp_mul_2d(&w6, 8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S6 += S2 if ((e = mp_add(&w6, &w2, &w6)) != MP_OKAY) { goto ERR; } // S2 *= 180 if ((e = mp_mul_d(&w2, 180, &w2)) != MP_OKAY) { goto ERR; } // S2 += S4 if ((e = mp_add(&w2, &w4, &w2)) != MP_OKAY) { goto ERR; } // S2 /= 11340 \\ division by 11340 if ((e = mp_div_d(&w2, 11340, &w2, NULL)) != MP_OKAY) { goto ERR; } // S4 += (720*S6) if ((e = mp_mul_d(&w6, 720, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) { goto ERR; } // S4 /= (-2160) \\ division by -2160 if ((e = mp_div_d(&w4, 2160, &w4, NULL)) != MP_OKAY) { goto ERR; } if (&w4.sign == MP_ZPOS) (&w4)->sign = MP_NEG; (&w4)->sign = MP_ZPOS; // S6 -= S4 if ((e = mp_sub(&w6, &w4, &w6)) != MP_OKAY) { goto ERR; } // S8 -= S2 if ((e = mp_sub(&w8, &w2, &w8)) != MP_OKAY) { goto ERR; } // P = S1*x^8 + S2*x^7 + S3*x^6 + S4*x^5 + S5*x^4 + S6*x^3 + S7*x^2 + S8*x + S9 if ((e = mp_copy(&w9, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w8, B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w8, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w7, 2 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w7, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w6, 3 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w6, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w5, 4 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w5, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w4, 5 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w4, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w3, 6 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w3, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w2, 7 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w2, &tmp1)) != MP_OKAY) { goto ERR; } if ((e = mp_lshd(&w1, 8 * B)) != MP_OKAY) { goto ERR; } if ((e = mp_add(&tmp1, &w1, c)) != MP_OKAY) { goto ERR; } // P - A*B \\ == zero c->sign = sign; ERR: ERRb4: mp_clear(&b4); ERRb3: mp_clear(&b3); ERRb2: mp_clear(&b2); ERRb1: mp_clear(&b1); ERRb0: mp_clear(&b0); ERRa4: mp_clear(&a4); ERRa3: mp_clear(&a3); ERRa2: mp_clear(&a2); ERRa1: mp_clear(&a1); ERRa0: mp_clear(&a0); ERR0: mp_clear_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2, // &a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4, NULL); return e; }
int main(int argc, char *argv[]) { int ix; mp_int a, b, c, d; mp_digit r; mp_err res; if(argc < 3) { fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]); return 1; } printf("Test 3: Multiplication and division\n\n"); srand(time(NULL)); mp_init(&a); mp_init(&b); mp_read_radix(&a, argv[1], 10); mp_read_radix(&b, argv[2], 10); printf("a = "); mp_print(&a, stdout); fputc('\n', stdout); printf("b = "); mp_print(&b, stdout); fputc('\n', stdout); mp_init(&c); printf("\nc = a * b\n"); mp_mul(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("\nc = b * 32523\n"); mp_mul_d(&b, 32523, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_init(&d); printf("\nc = a / b, d = a mod b\n"); mp_div(&a, &b, &c, &d); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("d = "); mp_print(&d, stdout); fputc('\n', stdout); ix = rand() % 256; printf("\nc = a / %d, r = a mod %d\n", ix, ix); mp_div_d(&a, (mp_digit)ix, &c, &r); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); printf("r = %04X\n", r); #if EXPT printf("\nc = a ** b\n"); mp_expt(&a, &b, &c); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #endif ix = rand() % 256; printf("\nc = 2^%d\n", ix); mp_2expt(&c, ix); printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); #if SQRT printf("\nc = sqrt(a)\n"); if((res = mp_sqrt(&a, &c)) != MP_OKAY) { printf("mp_sqrt: %s\n", mp_strerror(res)); } else { printf("c = "); mp_print(&c, stdout); fputc('\n', stdout); mp_sqr(&c, &c); printf("c^2 = "); mp_print(&c, stdout); fputc('\n', stdout); } #endif mp_clear(&d); mp_clear(&c); mp_clear(&b); mp_clear(&a); return 0; }
Mpi operator/(Mpi &a, mp_digit i){ Mpi z; if (z.err==MP_OKAY) z.err=mp_div_d(&(a.mpi_n),i,&(z.mpi_n),NULL); return z; }