void fft_radix2(mp_limb_t ** ii, mp_size_t n, mp_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2) { mp_size_t i; mp_size_t limbs = (w*n)/GMP_LIMB_BITS; if (n == 1) { fft_butterfly(*t1, *t2, ii[0], ii[1], 0, limbs, w); SWAP_PTRS(ii[0], *t1); SWAP_PTRS(ii[1], *t2); return; } for (i = 0; i < n; i++) { fft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); } fft_radix2(ii, n/2, 2*w, t1, t2); fft_radix2(ii + n, n/2, 2*w, t1, t2); }
void fmpz_add(fmpz_t coeffs_out, const fmpz_t in1, const fmpz_t in2) { fmpz_t coeffs1 = in1; fmpz_t coeffs2 = in2; long carry; unsigned long size1 = ABS(coeffs1[0]); unsigned long size2 = ABS(coeffs2[0]); if (size1 < size2) { SWAP_PTRS(coeffs1, coeffs2); size1 = ABS(coeffs1[0]); size2 = ABS(coeffs2[0]); } if (!size1) { if (!size2) coeffs_out[0] = 0L; else { if (coeffs_out != coeffs2) F_mpn_copy(coeffs_out, coeffs2, size2+1); } } else if (!size2) { if (coeffs_out != coeffs1) F_mpn_copy(coeffs_out, coeffs1, size1+1); } else if ((long) (coeffs1[0] ^ coeffs2[0]) >= 0L) { coeffs_out[0] = coeffs1[0]; carry = mpn_add(coeffs_out+1, coeffs1+1, size1, coeffs2+1, size2); if (carry) { coeffs_out[size1+1] = carry; if ((long) coeffs_out[0] < 0L) coeffs_out[0]--; else coeffs_out[0]++; } } else { carry = 0; if (size1 != size2) carry = 1; else carry = mpn_cmp(coeffs1+1, coeffs2+1, size1); if (carry == 0) coeffs_out[0] = 0L; else if (carry > 0) { mpn_sub(coeffs_out+1, coeffs1+1, size1, coeffs2+1, size2); coeffs_out[0] = coeffs1[0]; NORM(coeffs_out); } else { mpn_sub_n(coeffs_out+1, coeffs2+1, coeffs1+1, size1); coeffs_out[0] = -coeffs1[0]; NORM(coeffs_out); } } }
void ifft_negacyclic(mp_limb_t ** ii, mp_size_t n, mp_bitcnt_t w, mp_limb_t ** t1, mp_limb_t ** t2, mp_limb_t ** temp) { mp_size_t i; mp_size_t limbs = (w*n)/FLINT_BITS; ifft_radix2(ii, n/2, 2*w, t1, t2); ifft_radix2(ii+n, n/2, 2*w, t1, t2); if (w & 1) { for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust(*t1, ii[i], n - i/2, limbs, w); mpn_neg_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n - (n+i)/2, limbs, w); mpn_neg_n(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); i++; ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust_sqrt2(*t1, ii[i], 2*n-i, limbs, w, *temp); mpn_neg_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust_sqrt2(*t2, ii[n+i], n-i, limbs, w, *temp); mpn_neg_n(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); } } else { for (i = 0; i < n; i++) { ifft_butterfly(*t1, *t2, ii[i], ii[n+i], i, limbs, w); SWAP_PTRS(ii[i], *t1); SWAP_PTRS(ii[n+i], *t2); fft_adjust(*t1, ii[i], 2*n-i, limbs, w/2); mpn_neg_n(*t1, *t1, limbs + 1); SWAP_PTRS(ii[i], *t1); fft_adjust(*t2, ii[n+i], n-i, limbs, w/2); mpn_neg_n(*t2, *t2, limbs + 1); SWAP_PTRS(ii[n+i], *t2); } } }