// 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]; }
int test_F_mpn_mul_trunc() { mp_limb_t * int1, * int2, * product, * product2; mp_limb_t msl; 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 unsigned long trunc = randint(limbs1 + limbs2 - 1)+1; 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, limbs2); F_mpn_mul_trunc(product, int1, limbs1, int2, limbs2, trunc); mpn_mul(product2, int1, limbs1, int2, limbs2); unsigned long j; for (j = 0; j < trunc; j++) { if (product[j] != product2[j]) result = 0; } free(product2); free(product); free(int2); } free(int1); } return result; }
int test_F_mpn_mul_precache_trunc() { mp_limb_t * int1, * int2, * product, * product2; F_mpn_precache_t precache; mp_limb_t msl; 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 = randint(2*FLINT_FFT_LIMBS_CROSSOVER)+1; int1 = (mp_limb_t *) malloc(sizeof(mp_limb_t)*limbs1); mpn_random2(int1, limbs1); F_mpn_mul_precache_init(precache, int1, limbs1, limbs2); unsigned long count2; for (count2 = 0; (count2 < 30) && (result == 1); count2++) { unsigned long limbs3 = randint(limbs2)+1; unsigned long trunc = randint(2*(limbs1+limbs3)); #if DEBUG printf("limbs1 = %ld, limbs3 = %ld, trunc = %ld\n", limbs1, limbs3, trunc); #endif int2 = (mp_limb_t *) malloc(sizeof(mp_limb_t)*limbs3); 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, limbs3); mpn_random2(int2, limbs3); if (limbs1 > limbs3) F_mpn_mul_trunc(product2, int1, limbs1, int2, limbs3, trunc); else F_mpn_mul_trunc(product2, int2, limbs3, int1, limbs1, trunc); F_mpn_mul_precache_trunc(product, int2, limbs3, precache, trunc); unsigned long j; for (j = 0; j < FLINT_MIN(trunc, limbs1+limbs3); j++) { if (product[j] != product2[j]) { printf("Failure at %ld\n", j); result = 0; } } free(product2); free(product); free(int2); } F_mpn_mul_precache_clear(precache); free(int1); } return result; }