Example #1
0
        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_;
        }
    }