int bn_mult_arrays(bn_st * bn_out, bn_st * bn_array1, bn_st * bn_array2, int size) { for (int i = 0; i < size; ++i) { switch (MULT_TYPE) { case 'b': // Basic bn_mul_basic(&bn_out[i], &bn_array1[i], &bn_array2[i]); break; case 'c': // Comba bn_mul_comba(&bn_out[i], &bn_array1[i], &bn_array2[i]); break; case 'k': // Karatsuba bn_mul_karat(&bn_out[i], &bn_array1[i], &bn_array2[i]); break; default: error_hdl(-1,"Multiplication type not recognized"); return 1; } } return 0; }
/** * Computes the square of a multiple precision integer using recursive Karatsuba * squaring. * * @param[out] c - the result. * @param[in] a - the multiple precision integer to square. * @param[in] level - the number of Karatsuba steps to apply. */ static void bn_sqr_karat_imp(bn_t c, const bn_t a, int level) { int h; bn_t a0, a1, a0a0, a1a1, t; const dig_t *tmpa; dig_t *t0; bn_null(a0); bn_null(a1); bn_null(a0a0); bn_null(a1a1); bn_null(t); /* Compute half the digits of a or b. */ h = a->used >> 1; TRY { /* Allocate the temp variables. */ bn_new(a0); bn_new(a1); bn_new(a0a0); bn_new(a1a1); bn_new(t); a0->used = h; a1->used = a->used - h; tmpa = a->dp; /* a = a1 || a0 */ t0 = a0->dp; for (int i = 0; i < h; i++, t0++, tmpa++) *t0 = *tmpa; t0 = a1->dp; for (int i = 0; i < a1->used; i++, t0++, tmpa++) *t0 = *tmpa; bn_trim(a0); if (level <= 1) { /* a0a0 = a0 * a0 and a1a1 = a1 * a1 */ #if BN_SQR == BASIC bn_sqr_basic(a0a0, a0); bn_sqr_basic(a1a1, a1); #elif BN_SQR == COMBA bn_sqr_comba(a0a0, a0); bn_sqr_comba(a1a1, a1); #elif BN_SQR == MULTP bn_mul_comba(a0a0, a0, a0); bn_mul_comba(a1a1, a1, a1); #endif } else { bn_sqr_karat_imp(a0a0, a0, level - 1); bn_sqr_karat_imp(a1a1, a1, level - 1); } /* t = (a1 + a0) */ bn_add(t, a1, a0); if (level <= 1) { /* t = (a1 + a0)*(a1 + a0) */ #if BN_SQR == BASIC bn_sqr_basic(t, t); #elif BN_SQR == COMBA bn_sqr_comba(t, t); #elif BN_SQR == MULTP bn_mul_comba(t, t, t); #endif } else { bn_sqr_karat_imp(t, t, level - 1); } /* t2 = (a0*a0 + a1*a1) */ bn_add(a0, a0a0, a1a1); /* t = (a1 + a0)*(b1 + b0) - (a0*a0 + a1*a1) */ bn_sub(t, t, a0); /* t = (a1 + a0)*(a1 + a0) - (a0*a0 + a1*a1) << h digits */ bn_lsh(t, t, h * BN_DIGIT); /* t2 = a1 * b1 << 2*h digits */ bn_lsh(a1a1, a1a1, 2 * h * BN_DIGIT); /* t = t + a0*a0 */ bn_add(t, t, a0a0); /* c = t + a1*a1 */ bn_add(t, t, a1a1); t->sign = BN_POS; bn_copy(c, t); } CATCH_ANY { THROW(ERR_CAUGHT); } FINALLY { bn_free(a0); bn_free(a1); bn_free(a0a0); bn_free(a1a1); bn_free(t); } }