inline void poly_pointwise(poly* r, const poly* a, const poly* b) { for(size_t i = 0; i < PARAM_N; i++) { const uint16_t t = montgomery_reduce(3186*b->coeffs[i]); /* t is now in Montgomery domain */ r->coeffs[i] = montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ } }
void mul_coefficients(IntWrapper<uint16_t>* poly, uint16_t* factors) { unsigned int i; for(i = 0; i < PARAM_N; i++) poly[i] = montgomery_reduce((poly[i] * factors[i]).toInt()); }
/* GS_bo_to_no; omegas need to be in Montgomery domain */ void ntt(IntWrapper<uint16_t> * a, const uint16_t* omega) { int i, start, j, jTwiddle, distance; IntWrapper<uint16_t> temp; uint16_t W; for(i=0;i<10;i+=2) { // Even level distance = (1<<i); for(start = 0; start < distance;start++) { jTwiddle = 0; for(j=start;j<PARAM_N-1;j+=2*distance) { W = omega[jTwiddle++]; temp = a[j]; a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) a[j + distance] = montgomery_reduce((W * (IntWrapper<uint32_t>(temp) + 3*PARAM_Q - IntWrapper<uint32_t>(a[j + distance]))).toInt()); } } // Odd level distance <<= 1; for(start = 0; start < distance;start++) { jTwiddle = 0; for(j=start;j<PARAM_N-1;j+=2*distance) { W = omega[jTwiddle++]; temp = a[j]; a[j] = barrett_reduce((temp + a[j + distance]).toInt()); a[j + distance] = montgomery_reduce((W * (IntWrapper<uint32_t>(temp) + 3*PARAM_Q - IntWrapper<uint32_t>(a[j + distance]))).toInt()); } } } }