Modulus::Modulus(const std::uint64_t *modulus, int uint64_count, MemoryPool &pool) : modulus_(modulus), uint64_count_(uint64_count) { #ifdef SEAL_DEBUG if (modulus == nullptr) { throw invalid_argument("modulus"); } if (uint64_count <= 0) { throw invalid_argument("uint64_count"); } if (is_zero_uint(modulus, uint64_count)) { throw invalid_argument("modulus"); } #endif significant_bit_count_ = get_significant_bit_count_uint(modulus, uint64_count); power_of_two_minus_one_ = get_power_of_two_minus_one_uint(modulus, uint64_count); if (is_inverse_small(modulus, significant_bit_count_)) { // Calculate inverse modulus (clipped to modulus_bits). inverse_modulus_ = allocate_uint(uint64_count, pool); negate_uint(modulus, uint64_count, inverse_modulus_.get()); filter_highbits_uint(inverse_modulus_.get(), uint64_count, significant_bit_count_ - 1); inverse_significant_bit_count_ = get_significant_bit_count_uint(inverse_modulus_.get(), uint64_count); } }
void Evaluator::relinearize(const uint64_t *encrypted, uint64_t *destination) { // Extract encryption parameters. int coeff_count = poly_modulus_.coeff_count(); int coeff_bit_count = poly_modulus_.coeff_bit_count(); int coeff_uint64_count = divide_round_up(coeff_bit_count, bits_per_uint64); // Clear destatintion. set_zero_poly(coeff_count, coeff_uint64_count, destination); // Create polynomial to store decomposed polynomial (one at a time). Pointer decomp_poly(allocate_poly(coeff_count, coeff_uint64_count, pool_)); Pointer decomp_eval_poly(allocate_poly(coeff_count, coeff_uint64_count, pool_)); int shift = 0; for (int decomp_index = 0; decomp_index < evaluation_keys_.count(); ++decomp_index) { // Isolate decomposition_bit_count_ bits for each coefficient. for (int coeff_index = 0; coeff_index < coeff_count; ++coeff_index) { const uint64_t *productmoded_coeff = get_poly_coeff(encrypted, coeff_index, coeff_uint64_count); uint64_t *decomp_coeff = get_poly_coeff(decomp_poly.get(), coeff_index, coeff_uint64_count); right_shift_uint(productmoded_coeff, shift, coeff_uint64_count, decomp_coeff); filter_highbits_uint(decomp_coeff, coeff_uint64_count, decomposition_bit_count_); } // Multiply decomposed poly by evaluation key and accumulate to result. const BigPoly &evaluation_key = evaluation_keys_[decomp_index]; multiply_poly_poly_polymod_coeffmod(decomp_poly.get(), evaluation_key.pointer(), polymod_, mod_, decomp_eval_poly.get(), pool_); add_poly_poly_coeffmod(decomp_eval_poly.get(), destination, coeff_count, coeff_modulus_.pointer(), coeff_uint64_count, destination); // Increase shift by decomposition_bit_count_ for next iteration. shift += decomposition_bit_count_; } }