/** * Multiply x[0:xlen-1] and y[0:ylen-1], and * write the result to dest[0:xlen+ylen-1]. * The destination has to have space for xlen+ylen words, * even if the result might be one limb smaller. * This function requires that xlen >= ylen. * The destination must be distinct from either input operands. * All operands are unsigned. * This function is basically the same gmp's mpn_mul. */ public static void mul(int[] dest, int[] x, int xlen, int[] y, int ylen) { dest[xlen] = MPN.mul_1(dest, x, xlen, y[0]); for (int i = 1; i < ylen; i++) { long yword = (long)y[i] & 0xffffffffL; long carry = 0; for (int j = 0; j < xlen; j++) { carry += ((long)x[j] & 0xffffffffL) * yword + ((long)dest[i + j] & 0xffffffffL); dest[i + j] = (int)carry; carry = (long)(((ulong)carry) >> 32); } dest[i + xlen] = (int)carry; } }
public static int set_str(int[] dest, byte[] str, int str_len, int _base) { int size = 0; if ((_base & (_base - 1)) == 0) { // The base is a power of 2. Read the input string from // least to most significant character/digit. */ int next_bitpos = 0; int bits_per_indigit = 0; for (int i = _base; (i >>= 1) != 0;) { bits_per_indigit++; } int res_digit = 0; for (int i = str_len; --i >= 0;) { int inp_digit = str[i]; res_digit |= inp_digit << next_bitpos; next_bitpos += bits_per_indigit; if (next_bitpos >= 32) { dest[size++] = res_digit; next_bitpos -= 32; res_digit = inp_digit >> (bits_per_indigit - next_bitpos); } } if (res_digit != 0) { dest[size++] = res_digit; } } else { // General case. The base is not a power of 2. int indigits_per_limb = MPN.chars_per_word(_base); int str_pos = 0; while (str_pos < str_len) { int chunk = str_len - str_pos; if (chunk > indigits_per_limb) { chunk = indigits_per_limb; } int res_digit = str[str_pos++]; int big_base = _base; while (--chunk > 0) { res_digit = res_digit * _base + str[str_pos++]; big_base *= _base; } int cy_limb; if (size == 0) { cy_limb = res_digit; } else { cy_limb = MPN.mul_1(dest, dest, size, big_base); cy_limb += MPN.add_1(dest, dest, size, res_digit); } if (cy_limb != 0) { dest[size++] = cy_limb; } } } return(size); }