// truncated multiplication for fmpz void fmpz_mul_trunc(fmpz_t res, fmpz_t a, fmpz_t b, unsigned long trunc) { unsigned long sizea = FLINT_MIN(fmpz_size(a), trunc); unsigned long sizeb = FLINT_MIN(fmpz_size(b), trunc); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; if ((sizea == 0) || (sizeb == 0)) { res[0] = 0; return; } if (trunc >= sizea + sizeb) { mp_limb_t mslimb; if (sizea >= sizeb) mslimb = F_mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea + sizeb - (mslimb == 0); } else { mp_limb_t mslimb; fmpz_t temp = flint_stack_alloc(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = F_mpn_mul_trunc(temp+1, a+1, sizea, b+1, sizeb, trunc); else mslimb = F_mpn_mul_trunc(temp+1, b+1, sizeb, a+1, sizea, trunc); temp[0] = trunc; if (UNLIKELY(!mslimb)) __fmpz_normalise(temp); // normalise if most significant limb == 0 fmpz_set(res, temp); flint_stack_release(); } if ((long) (a[0] ^ b[0]) < 0L) res[0] = -res[0]; }
void fmpz_addmul(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; fmpz_t temp; mp_limb_t mslimb; if (sizea && sizeb) { if (sizea + sizeb < 100) { temp = (fmpz_t) flint_stack_alloc_small(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) temp[0] = -temp[0]; fmpz_add(res, res, temp); flint_stack_release_small(); } else { temp = (fmpz_t) flint_stack_alloc(sizea + sizeb + 1); if (sizea >= sizeb) mslimb = F_mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) temp[0] = -temp[0]; fmpz_add(res, res, temp); flint_stack_release(); } } }
void __fmpz_mul(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp; if ((sizea == 0) || (sizeb == 0)) { res[0] = 0; } else if (sizea + sizeb < 100) { if (sizea >= sizeb) mslimb = mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea + sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) res[0] = -res[0]; } else { if (sizea >= sizeb) mslimb = F_mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea+sizeb - (mslimb == 0); if ((long) (a[0] ^ b[0]) < 0) res[0] = -res[0]; } }
void fmpz_mul(fmpz_t res, const fmpz_t a, const fmpz_t b) { long a0 = a[0]; long b0 = b[0]; unsigned long sizea = FLINT_ABS(a0); unsigned long sizeb = FLINT_ABS(b0); while ((!a[sizea]) && (sizea)) sizea--; while ((!b[sizeb]) && (sizeb)) sizeb--; mp_limb_t mslimb; fmpz_t temp; if ((sizea == 0) || (sizeb == 0)) { res[0] = 0; } else if (sizea + sizeb < 100) { temp = (fmpz_t) flint_stack_alloc_small(sizea + sizeb + 1); if (sizea > sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else if (sizea == sizeb) { mpn_mul_n(temp+1, a+1, b+1, sizeb); mslimb = temp[2*sizeb]; } else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); F_mpn_copy(res, temp, temp[0]+1); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; flint_stack_release_small(); } else if (sizea + sizeb < 2*FLINT_FFT_LIMBS_CROSSOVER) { temp = (fmpz_t) flint_stack_alloc(sizea + sizeb + 1); if (sizea > sizeb) mslimb = mpn_mul(temp+1, a+1, sizea, b+1, sizeb); else if (sizea == sizeb) { mpn_mul_n(temp+1, a+1, b+1, sizeb); mslimb = temp[2*sizeb]; } else mslimb = mpn_mul(temp+1, b+1, sizeb, a+1, sizea); temp[0] = sizea + sizeb - (mslimb == 0); F_mpn_copy(res, temp, temp[0]+1); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; flint_stack_release(); } else { if (sizea >= sizeb) mslimb = F_mpn_mul(res+1, a+1, sizea, b+1, sizeb); else mslimb = F_mpn_mul(res+1, b+1, sizeb, a+1, sizea); res[0] = sizea+sizeb - (mslimb == 0); if ((long) (a0 ^ b0) < 0) res[0] = -res[0]; } }
int test_F_mpn_mul() { mp_limb_t * int1, * int2, * product, * product2; mp_limb_t msl, msl2; int result = 1; unsigned long count; for (count = 0; (count < 30) && (result == 1); count++) { unsigned long limbs2 = randint(2*FLINT_FFT_LIMBS_CROSSOVER)+1; unsigned long limbs1 = limbs2 + randint(1000); int1 = (mp_limb_t *) malloc(sizeof(mp_limb_t)*limbs1); mpn_random2(int1, limbs1); unsigned long count2; for (count2 = 0; (count2 < 30) && (result == 1); count2++) { #if DEBUG printf("%ld, %ld\n",limbs1, limbs2); #endif int2 = (mp_limb_t *) malloc(sizeof(mp_limb_t)*limbs2); product = (mp_limb_t *) malloc(sizeof(mp_limb_t)*(limbs1+limbs2)); product2 = (mp_limb_t *) malloc(sizeof(mp_limb_t)*(limbs1+limbs2)); F_mpn_clear(int2, limbs2); mpn_random2(int2, randint(limbs2-1)+1); msl = F_mpn_mul(product, int1, limbs1, int2, limbs2); msl2 = mpn_mul(product2, int1, limbs1, int2, limbs2); unsigned long j; for (j = 0; j < limbs1+limbs2 - (msl == 0); j++) { if (product[j] != product2[j]) result = 0; } result &= (msl == msl2); free(product2); free(product); free(int2); } free(int1); } return result; }