Commit c6c9d2f5 authored by Hoang Gia NGUYEN's avatar Hoang Gia NGUYEN
Browse files

first commit

parent fe2d6195
Pipeline #60 failed with stages
in 0 seconds

Too many changes to show.

To preserve performance only 275 of 275+ files are displayed.
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT license.
# Source files in this directory
target_sources(seal_obj PRIVATE
${CMAKE_CURRENT_LIST_DIR}/batchencoder.cpp
${CMAKE_CURRENT_LIST_DIR}/biguint.cpp
${CMAKE_CURRENT_LIST_DIR}/ciphertext.cpp
${CMAKE_CURRENT_LIST_DIR}/ckks.cpp
${CMAKE_CURRENT_LIST_DIR}/context.cpp
${CMAKE_CURRENT_LIST_DIR}/decryptor.cpp
${CMAKE_CURRENT_LIST_DIR}/intencoder.cpp
${CMAKE_CURRENT_LIST_DIR}/encryptionparams.cpp
${CMAKE_CURRENT_LIST_DIR}/encryptor.cpp
${CMAKE_CURRENT_LIST_DIR}/evaluator.cpp
${CMAKE_CURRENT_LIST_DIR}/keygenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.cpp
${CMAKE_CURRENT_LIST_DIR}/memorymanager.cpp
${CMAKE_CURRENT_LIST_DIR}/modulus.cpp
${CMAKE_CURRENT_LIST_DIR}/plaintext.cpp
${CMAKE_CURRENT_LIST_DIR}/randomgen.cpp
${CMAKE_CURRENT_LIST_DIR}/serialization.cpp
${CMAKE_CURRENT_LIST_DIR}/valcheck.cpp
)
# Add header files for installation
install(
FILES
${CMAKE_CURRENT_LIST_DIR}/batchencoder.h
${CMAKE_CURRENT_LIST_DIR}/biguint.h
${CMAKE_CURRENT_LIST_DIR}/ciphertext.h
${CMAKE_CURRENT_LIST_DIR}/ckks.h
${CMAKE_CURRENT_LIST_DIR}/modulus.h
${CMAKE_CURRENT_LIST_DIR}/context.h
${CMAKE_CURRENT_LIST_DIR}/decryptor.h
${CMAKE_CURRENT_LIST_DIR}/intencoder.h
${CMAKE_CURRENT_LIST_DIR}/encryptionparams.h
${CMAKE_CURRENT_LIST_DIR}/encryptor.h
${CMAKE_CURRENT_LIST_DIR}/evaluator.h
${CMAKE_CURRENT_LIST_DIR}/galoiskeys.h
${CMAKE_CURRENT_LIST_DIR}/intarray.h
${CMAKE_CURRENT_LIST_DIR}/keygenerator.h
${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.h
${CMAKE_CURRENT_LIST_DIR}/memorymanager.h
${CMAKE_CURRENT_LIST_DIR}/plaintext.h
${CMAKE_CURRENT_LIST_DIR}/publickey.h
${CMAKE_CURRENT_LIST_DIR}/randomgen.h
${CMAKE_CURRENT_LIST_DIR}/randomtostd.h
${CMAKE_CURRENT_LIST_DIR}/relinkeys.h
${CMAKE_CURRENT_LIST_DIR}/seal.h
${CMAKE_CURRENT_LIST_DIR}/secretkey.h
${CMAKE_CURRENT_LIST_DIR}/serializable.h
${CMAKE_CURRENT_LIST_DIR}/serialization.h
${CMAKE_CURRENT_LIST_DIR}/valcheck.h
DESTINATION
${SEAL_INCLUDES_INSTALL_DIR}/seal
)
add_subdirectory(util)
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include "seal/batchencoder.h"
#include "seal/valcheck.h"
#include "seal/util/common.h"
#include "seal/util/polycore.h"
#include <cstdlib>
#include <limits>
#include <random>
#include <stdexcept>
using namespace std;
using namespace seal::util;
namespace seal
{
BatchEncoder::BatchEncoder(shared_ptr<SEALContext> context) : context_(move(context))
{
// Verify parameters
if (!context_)
{
throw invalid_argument("invalid context");
}
if (!context_->parameters_set())
{
throw invalid_argument("encryption parameters are not set correctly");
}
auto &context_data = *context_->first_context_data();
if (context_data.parms().scheme() != scheme_type::BFV)
{
throw invalid_argument("unsupported scheme");
}
if (!context_data.qualifiers().using_batching)
{
throw invalid_argument("encryption parameters are not valid for batching");
}
// Set the slot count
slots_ = context_data.parms().poly_modulus_degree();
// Reserve space for all of the primitive roots
roots_of_unity_ = allocate_uint(slots_, pool_);
// Fill the vector of roots of unity with all distinct odd powers of generator.
// These are all the primitive (2*slots_)-th roots of unity in integers modulo
// parms.plain_modulus().
populate_roots_of_unity_vector(context_data);
// Populate matrix representation index map
populate_matrix_reps_index_map();
}
void BatchEncoder::populate_roots_of_unity_vector(const SEALContext::ContextData &context_data)
{
uint64_t root = context_data.plain_ntt_tables()->get_root();
auto &modulus = context_data.parms().plain_modulus();
uint64_t generator_sq = multiply_uint_uint_mod(root, root, modulus);
roots_of_unity_[0] = root;
for (size_t i = 1; i < slots_; i++)
{
roots_of_unity_[i] = multiply_uint_uint_mod(roots_of_unity_[i - 1], generator_sq, modulus);
}
}
void BatchEncoder::populate_matrix_reps_index_map()
{
int logn = get_power_of_two(slots_);
matrix_reps_index_map_ = allocate<size_t>(slots_, pool_);
// Copy from the matrix to the value vectors
size_t row_size = slots_ >> 1;
size_t m = slots_ << 1;
uint64_t gen = 3;
uint64_t pos = 1;
for (size_t i = 0; i < row_size; i++)
{
// Position in normal bit order
uint64_t index1 = (pos - 1) >> 1;
uint64_t index2 = (m - pos - 1) >> 1;
// Set the bit-reversed locations
matrix_reps_index_map_[i] = safe_cast<size_t>(util::reverse_bits(index1, logn));
matrix_reps_index_map_[row_size | i] = safe_cast<size_t>(util::reverse_bits(index2, logn));
// Next primitive root
pos *= gen;
pos &= (m - 1);
}
}
void BatchEncoder::reverse_bits(uint64_t *input)
{
#ifdef SEAL_DEBUG
if (input == nullptr)
{
throw invalid_argument("input cannot be null");
}
#endif
size_t coeff_count = context_->first_context_data()->parms().poly_modulus_degree();
int logn = get_power_of_two(coeff_count);
for (size_t i = 0; i < coeff_count; i++)
{
uint64_t reversed_i = util::reverse_bits(i, logn);
if (i < reversed_i)
{
swap(input[i], input[reversed_i]);
}
}
}
void BatchEncoder::encode(const vector<uint64_t> &values_matrix, Plaintext &destination)
{
auto &context_data = *context_->first_context_data();
// Validate input parameters
size_t values_matrix_size = values_matrix.size();
if (values_matrix_size > slots_)
{
throw logic_error("values_matrix size is too large");
}
#ifdef SEAL_DEBUG
uint64_t modulus = context_data.parms().plain_modulus().value();
for (auto v : values_matrix)
{
// Validate the i-th input
if (v >= modulus)
{
throw invalid_argument("input value is larger than plain_modulus");
}
}
#endif
// Set destination to full size
destination.resize(slots_);
destination.parms_id() = parms_id_zero;
// First write the values to destination coefficients.
// Read in top row, then bottom row.
for (size_t i = 0; i < values_matrix_size; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = values_matrix[i];
}
for (size_t i = values_matrix_size; i < slots_; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = 0;
}
// Transform destination using inverse of negacyclic NTT
// Note: We already performed bit-reversal when reading in the matrix
inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables());
}
void BatchEncoder::encode(const vector<int64_t> &values_matrix, Plaintext &destination)
{
auto &context_data = *context_->first_context_data();
uint64_t modulus = context_data.parms().plain_modulus().value();
// Validate input parameters
size_t values_matrix_size = values_matrix.size();
if (values_matrix_size > slots_)
{
throw logic_error("values_matrix size is too large");
}
#ifdef SEAL_DEBUG
uint64_t plain_modulus_div_two = modulus >> 1;
for (auto v : values_matrix)
{
// Validate the i-th input
if (unsigned_gt(llabs(v), plain_modulus_div_two))
{
throw invalid_argument("input value is larger than plain_modulus");
}
}
#endif
// Set destination to full size
destination.resize(slots_);
destination.parms_id() = parms_id_zero;
// First write the values to destination coefficients.
// Read in top row, then bottom row.
for (size_t i = 0; i < values_matrix_size; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) =
(values_matrix[i] < 0) ? (modulus + static_cast<uint64_t>(values_matrix[i]))
: static_cast<uint64_t>(values_matrix[i]);
}
for (size_t i = values_matrix_size; i < slots_; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = 0;
}
// Transform destination using inverse of negacyclic NTT
// Note: We already performed bit-reversal when reading in the matrix
inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables());
}
#ifdef SEAL_USE_MSGSL
void BatchEncoder::encode(gsl::span<const uint64_t> values_matrix, Plaintext &destination)
{
auto &context_data = *context_->first_context_data();
// Validate input parameters
size_t values_matrix_size = static_cast<size_t>(values_matrix.size());
if (values_matrix_size > slots_)
{
throw logic_error("values_matrix size is too large");
}
#ifdef SEAL_DEBUG
uint64_t modulus = context_data.parms().plain_modulus().value();
for (auto v : values_matrix)
{
// Validate the i-th input
if (v >= modulus)
{
throw invalid_argument("input value is larger than plain_modulus");
}
}
#endif
// Set destination to full size
destination.resize(slots_);
destination.parms_id() = parms_id_zero;
// First write the values to destination coefficients. Read
// in top row, then bottom row.
using index_type = decltype(values_matrix)::size_type;
for (size_t i = 0; i < values_matrix_size; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = values_matrix[static_cast<index_type>(i)];
}
for (size_t i = values_matrix_size; i < slots_; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = 0;
}
// Transform destination using inverse of negacyclic NTT
// Note: We already performed bit-reversal when reading in the matrix
inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables());
}
void BatchEncoder::encode(gsl::span<const int64_t> values_matrix, Plaintext &destination)
{
auto &context_data = *context_->first_context_data();
uint64_t modulus = context_data.parms().plain_modulus().value();
// Validate input parameters
size_t values_matrix_size = static_cast<size_t>(values_matrix.size());
if (values_matrix_size > slots_)
{
throw logic_error("values_matrix size is too large");
}
#ifdef SEAL_DEBUG
uint64_t plain_modulus_div_two = modulus >> 1;
for (auto v : values_matrix)
{
// Validate the i-th input
if (unsigned_gt(llabs(v), plain_modulus_div_two))
{
throw invalid_argument("input value is larger than plain_modulus");
}
}
#endif
// Set destination to full size
destination.resize(slots_);
destination.parms_id() = parms_id_zero;
// First write the values to destination coefficients. Read
// in top row, then bottom row.
using index_type = decltype(values_matrix)::size_type;
for (size_t i = 0; i < values_matrix_size; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) =
(values_matrix[static_cast<index_type>(i)] < 0)
? (modulus + static_cast<uint64_t>(values_matrix[static_cast<index_type>(i)]))
: static_cast<uint64_t>(values_matrix[static_cast<index_type>(i)]);
}
for (size_t i = values_matrix_size; i < slots_; i++)
{
*(destination.data() + matrix_reps_index_map_[i]) = 0;
}
// Transform destination using inverse of negacyclic NTT
// Note: We already performed bit-reversal when reading in the matrix
inverse_ntt_negacyclic_harvey(destination.data(), *context_data.plain_ntt_tables());
}
#endif
void BatchEncoder::encode(Plaintext &plain, MemoryPoolHandle pool)
{
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
// Validate input parameters
if (plain.coeff_count() > context_data.parms().poly_modulus_degree())
{
throw invalid_argument("plain is not valid for encryption parameters");
}
#ifdef SEAL_DEBUG
if (!are_poly_coefficients_less_than(
plain.data(), plain.coeff_count(), context_data.parms().plain_modulus().value()))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
#endif
// We need to permute the coefficients of plain. To do this, we allocate
// temporary space.
size_t input_plain_coeff_count = min(plain.coeff_count(), slots_);
auto temp(allocate_uint(input_plain_coeff_count, pool));
set_uint_uint(plain.data(), input_plain_coeff_count, temp.get());
// Set plain to full slot count size.
plain.resize(slots_);
plain.parms_id() = parms_id_zero;
// First write the values to destination coefficients. Read
// in top row, then bottom row.
for (size_t i = 0; i < input_plain_coeff_count; i++)
{
*(plain.data() + matrix_reps_index_map_[i]) = temp[i];
}
for (size_t i = input_plain_coeff_count; i < slots_; i++)
{
*(plain.data() + matrix_reps_index_map_[i]) = 0;
}
// Transform destination using inverse of negacyclic NTT
// Note: We already performed bit-reversal when reading in the matrix
inverse_ntt_negacyclic_harvey(plain.data(), *context_data.plain_ntt_tables());
}
void BatchEncoder::decode(const Plaintext &plain, vector<uint64_t> &destination, MemoryPoolHandle pool)
{
if (!is_valid_for(plain, context_))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
// Set destination size
destination.resize(slots_);
// Never include the leading zero coefficient (if present)
size_t plain_coeff_count = min(plain.coeff_count(), slots_);
auto temp_dest(allocate_uint(slots_, pool));
// Make a copy of poly
set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get());
set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count);
// Transform destination using negacyclic NTT.
ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables());
// Read top row
for (size_t i = 0; i < slots_; i++)
{
destination[i] = temp_dest[matrix_reps_index_map_[i]];
}
}
void BatchEncoder::decode(const Plaintext &plain, vector<int64_t> &destination, MemoryPoolHandle pool)
{
if (!is_valid_for(plain, context_))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
uint64_t modulus = context_data.parms().plain_modulus().value();
// Set destination size
destination.resize(slots_);
// Never include the leading zero coefficient (if present)
size_t plain_coeff_count = min(plain.coeff_count(), slots_);
auto temp_dest(allocate_uint(slots_, pool));
// Make a copy of poly
set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get());
set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count);
// Transform destination using negacyclic NTT.
ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables());
// Read top row, then bottom row
uint64_t plain_modulus_div_two = modulus >> 1;
for (size_t i = 0; i < slots_; i++)
{
uint64_t curr_value = temp_dest[matrix_reps_index_map_[i]];
destination[i] = (curr_value > plain_modulus_div_two)
? (static_cast<int64_t>(curr_value) - static_cast<int64_t>(modulus))
: static_cast<int64_t>(curr_value);
}
}
#ifdef SEAL_USE_MSGSL
void BatchEncoder::decode(const Plaintext &plain, gsl::span<uint64_t> destination, MemoryPoolHandle pool)
{
if (!is_valid_for(plain, context_))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
using index_type = decltype(destination)::size_type;
if (unsigned_gt(destination.size(), numeric_limits<int>::max()) || unsigned_neq(destination.size(), slots_))
{
throw invalid_argument("destination has incorrect size");
}
// Never include the leading zero coefficient (if present)
size_t plain_coeff_count = min(plain.coeff_count(), slots_);
auto temp_dest(allocate_uint(slots_, pool));
// Make a copy of poly
set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get());
set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count);
// Transform destination using negacyclic NTT.
ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables());
// Read top row
for (size_t i = 0; i < slots_; i++)
{
destination[static_cast<index_type>(i)] = temp_dest[matrix_reps_index_map_[i]];
}
}
void BatchEncoder::decode(const Plaintext &plain, gsl::span<int64_t> destination, MemoryPoolHandle pool)
{
if (!is_valid_for(plain, context_))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
uint64_t modulus = context_data.parms().plain_modulus().value();
using index_type = decltype(destination)::size_type;
if (unsigned_gt(destination.size(), numeric_limits<int>::max()) || unsigned_neq(destination.size(), slots_))
{
throw invalid_argument("destination has incorrect size");
}
// Never include the leading zero coefficient (if present)
size_t plain_coeff_count = min(plain.coeff_count(), slots_);
auto temp_dest(allocate_uint(slots_, pool));
// Make a copy of poly
set_uint_uint(plain.data(), plain_coeff_count, temp_dest.get());
set_zero_uint(slots_ - plain_coeff_count, temp_dest.get() + plain_coeff_count);
// Transform destination using negacyclic NTT.
ntt_negacyclic_harvey(temp_dest.get(), *context_data.plain_ntt_tables());
// Read top row, then bottom row
uint64_t plain_modulus_div_two = modulus >> 1;
for (size_t i = 0; i < slots_; i++)
{
uint64_t curr_value = temp_dest[matrix_reps_index_map_[i]];
destination[static_cast<index_type>(i)] =
(curr_value > plain_modulus_div_two)
? (static_cast<int64_t>(curr_value) - static_cast<int64_t>(modulus))
: static_cast<int64_t>(curr_value);
}
}
#endif
void BatchEncoder::decode(Plaintext &plain, MemoryPoolHandle pool)
{
if (!is_valid_for(plain, context_))
{
throw invalid_argument("plain is not valid for encryption parameters");
}
if (plain.is_ntt_form())
{
throw invalid_argument("plain cannot be in NTT form");
}
if (!pool)
{
throw invalid_argument("pool is uninitialized");
}
auto &context_data = *context_->first_context_data();
// Never include the leading zero coefficient (if present)
size_t plain_coeff_count = min(plain.coeff_count(), slots_);
// Allocate temporary space to store a wide copy of plain
auto temp(allocate_uint(slots_, pool));
// Make a copy of poly
set_uint_uint(plain.data(), plain_coeff_count, temp.get());
set_zero_uint(slots_ - plain_coeff_count, temp.get() + plain_coeff_count);
// Transform destination using negacyclic NTT.
ntt_negacyclic_harvey(temp.get(), *context_data.plain_ntt_tables());
// Set plain to full slot count size (note that all new coefficients are
// set to zero).
plain.resize(slots_);
// Read top row, then bottom row
for (size_t i = 0; i < slots_; i++)
{
*(plain.data() + i) = temp[matrix_reps_index_map_[i]];
}
}
} // namespace seal
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
#include "seal/context.h"
#include "seal/plaintext.h"
#include "seal/util/common.h"
#include "seal/util/defines.h"
#include "seal/util/uintarithsmallmod.h"
#include "seal/util/uintcore.h"
#include <limits>
#include <vector>
#ifdef SEAL_USE_MSGSL
#include <gsl/span>
#endif
namespace seal
{
/**
Provides functionality for CRT batching. If the polynomial modulus degree is N, and
the plaintext modulus is a prime number T such that T is congruent to 1 modulo 2N,
then BatchEncoder allows the plaintext elements to be viewed as 2-by-(N/2)
matrices of integers modulo T. Homomorphic operations performed on such encrypted
matrices are applied coefficient (slot) wise, enabling powerful SIMD functionality
for computations that are vectorizable. This functionality is often called "batching"
in the homomorphic encryption literature.
@par Mathematical Background
Mathematically speaking, if the polynomial modulus is X^N+1, N is a power of two, and
plain_modulus is a prime number T such that 2N divides T-1, then integers modulo T
contain a primitive 2N-th root of unity and the polynomial X^N+1 splits into n distinct
linear factors as X^N+1 = (X-a_1)*...*(X-a_N) mod T, where the constants a_1, ..., a_n
are all the distinct primitive 2N-th roots of unity in integers modulo T. The Chinese
Remainder Theorem (CRT) states that the plaintext space Z_T[X]/(X^N+1) in this case is
isomorphic (as an algebra) to the N-fold direct product of fields Z_T. The isomorphism
is easy to compute explicitly in both directions, which is what this class does.
Furthermore, the Galois group of the extension is (Z/2NZ)* ~= Z/2Z x Z/(N/2) whose
action on the primitive roots of unity is easy to describe. Since the batching slots
correspond 1-to-1 to the primitive roots of unity, applying Galois automorphisms on the
plaintext act by permuting the slots. By applying generators of the two cyclic
subgroups of the Galois group, we can effectively view the plaintext as a 2-by-(N/2)
matrix, and enable cyclic row rotations, and column rotations (row swaps).
@par Valid Parameters
Whether batching can be used depends on whether the plaintext modulus has been chosen
appropriately. Thus, to construct a BatchEncoder the user must provide an instance
of SEALContext such that its associated EncryptionParameterQualifiers object has the
flags parameters_set and enable_batching set to true.
@see EncryptionParameters for more information about encryption parameters.
@see EncryptionParameterQualifiers for more information about parameter qualifiers.
@see Evaluator for rotating rows and columns of encrypted matrices.
*/
class BatchEncoder
{
public:
/**
Creates a BatchEncoder. It is necessary that the encryption parameters
given through the SEALContext object support batching.
@param[in] context The SEALContext
@throws std::invalid_argument if the context is not set or encryption
parameters are not valid for batching
@throws std::invalid_argument if scheme is not scheme_type::BFV
*/
BatchEncoder(std::shared_ptr<SEALContext> context);
/**
Creates a plaintext from a given matrix. This function "batches" a given matrix
of integers modulo the plaintext modulus into a plaintext element, and stores
the result in the destination parameter. The input vector must have size at most equal
to the degree of the polynomial modulus. The first half of the elements represent the
first row of the matrix, and the second half represent the second row. The numbers
in the matrix can be at most equal to the plaintext modulus for it to represent
a valid plaintext.
If the destination plaintext overlaps the input values in memory, the behavior of
this function is undefined.
@param[in] values The matrix of integers modulo plaintext modulus to batch
@param[out] destination The plaintext polynomial to overwrite with the result
@throws std::invalid_argument if values is too large
*/
void encode(const std::vector<std::uint64_t> &values, Plaintext &destination);
/**
Creates a plaintext from a given matrix. This function "batches" a given matrix
of integers modulo the plaintext modulus into a plaintext element, and stores
the result in the destination parameter. The input vector must have size at most equal
to the degree of the polynomial modulus. The first half of the elements represent the
first row of the matrix, and the second half represent the second row. The numbers
in the matrix can be at most equal to the plaintext modulus for it to represent
a valid plaintext.
If the destination plaintext overlaps the input values in memory, the behavior of
this function is undefined.
@param[in] values The matrix of integers modulo plaintext modulus to batch
@param[out] destination The plaintext polynomial to overwrite with the result
@throws std::invalid_argument if values is too large
*/
void encode(const std::vector<std::int64_t> &values, Plaintext &destination);
#ifdef SEAL_USE_MSGSL
/**
Creates a plaintext from a given matrix. This function "batches" a given matrix
of integers modulo the plaintext modulus into a plaintext element, and stores
the result in the destination parameter. The input must have size at most equal
to the degree of the polynomial modulus. The first half of the elements represent the
first row of the matrix, and the second half represent the second row. The numbers
in the matrix can be at most equal to the plaintext modulus for it to represent
a valid plaintext.
If the destination plaintext overlaps the input values in memory, the behavior of
this function is undefined.
@param[in] values The matrix of integers modulo plaintext modulus to batch
@param[out] destination The plaintext polynomial to overwrite with the result
@throws std::invalid_argument if values is too large
*/
void encode(gsl::span<const std::uint64_t> values, Plaintext &destination);
/**
Creates a plaintext from a given matrix. This function "batches" a given matrix
of integers modulo the plaintext modulus into a plaintext element, and stores
the result in the destination parameter. The input must have size at most equal
to the degree of the polynomial modulus. The first half of the elements represent the
first row of the matrix, and the second half represent the second row. The numbers
in the matrix can be at most equal to the plaintext modulus for it to represent
a valid plaintext.
If the destination plaintext overlaps the input values in memory, the behavior of
this function is undefined.
@param[in] values The matrix of integers modulo plaintext modulus to batch
@param[out] destination The plaintext polynomial to overwrite with the result
@throws std::invalid_argument if values is too large
*/
void encode(gsl::span<const std::int64_t> values, Plaintext &destination);
#endif
/**
Creates a plaintext from a given matrix. This function "batches" a given matrix
of integers modulo the plaintext modulus in-place into a plaintext ready to be
encrypted. The matrix is given as a plaintext element whose first N/2 coefficients
represent the first row of the matrix, and the second N/2 coefficients represent the
second row, where N denotes the degree of the polynomial modulus. The input plaintext
must have degress less than the polynomial modulus, and coefficients less than the
plaintext modulus, i.e. it must be a valid plaintext for the encryption parameters.
Dynamic memory allocations in the process are allocated from the memory pool pointed
to by the given MemoryPoolHandle.
@param[in] plain The matrix of integers modulo plaintext modulus to batch
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if pool is uninitialized
*/
void encode(Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool());
/**
Inverse of encode. This function "unbatches" a given plaintext into a matrix
of integers modulo the plaintext modulus, and stores the result in the destination
parameter. The input plaintext must have degress less than the polynomial modulus,
and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
for the encryption parameters. Dynamic memory allocations in the process are
allocated from the memory pool pointed to by the given MemoryPoolHandle.
@param[in] plain The plaintext polynomial to unbatch
@param[out] destination The matrix to be overwritten with the values in the slots
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if pool is uninitialized
*/
void decode(
const Plaintext &plain, std::vector<std::uint64_t> &destination,
MemoryPoolHandle pool = MemoryManager::GetPool());
/**
Inverse of encode. This function "unbatches" a given plaintext into a matrix
of integers modulo the plaintext modulus, and stores the result in the destination
parameter. The input plaintext must have degress less than the polynomial modulus,
and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
for the encryption parameters. Dynamic memory allocations in the process are
allocated from the memory pool pointed to by the given MemoryPoolHandle.
@param[in] plain The plaintext polynomial to unbatch
@param[out] destination The matrix to be overwritten with the values in the slots
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if pool is uninitialized
*/
void decode(
const Plaintext &plain, std::vector<std::int64_t> &destination,
MemoryPoolHandle pool = MemoryManager::GetPool());
#ifdef SEAL_USE_MSGSL
/**
Inverse of encode. This function "unbatches" a given plaintext into a matrix
of integers modulo the plaintext modulus, and stores the result in the destination
parameter. The input plaintext must have degress less than the polynomial modulus,
and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
for the encryption parameters. Dynamic memory allocations in the process are
allocated from the memory pool pointed to by the given MemoryPoolHandle.
@param[in] plain The plaintext polynomial to unbatch
@param[out] destination The matrix to be overwritten with the values in the slots
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if destination has incorrect size
@throws std::invalid_argument if pool is uninitialized
*/
void decode(
const Plaintext &plain, gsl::span<std::uint64_t> destination,
MemoryPoolHandle pool = MemoryManager::GetPool());
/**
Inverse of encode. This function "unbatches" a given plaintext into a matrix
of integers modulo the plaintext modulus, and stores the result in the destination
parameter. The input plaintext must have degress less than the polynomial modulus,
and coefficients less than the plaintext modulus, i.e. it must be a valid plaintext
for the encryption parameters. Dynamic memory allocations in the process are
allocated from the memory pool pointed to by the given MemoryPoolHandle.
@param[in] plain The plaintext polynomial to unbatch
@param[out] destination The matrix to be overwritten with the values in the slots
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if destination has incorrect size
@throws std::invalid_argument if pool is uninitialized
*/
void decode(
const Plaintext &plain, gsl::span<std::int64_t> destination,
MemoryPoolHandle pool = MemoryManager::GetPool());
#endif
/**
Inverse of encode. This function "unbatches" a given plaintext in-place into
a matrix of integers modulo the plaintext modulus. The input plaintext must have
degress less than the polynomial modulus, and coefficients less than the plaintext
modulus, i.e. it must be a valid plaintext for the encryption parameters. Dynamic
memory allocations in the process are allocated from the memory pool pointed to by
the given MemoryPoolHandle.
@param[in] plain The plaintext polynomial to unbatch
@param[in] pool The MemoryPoolHandle pointing to a valid memory pool
@throws std::invalid_argument if plain is not valid for the encryption parameters
@throws std::invalid_argument if plain is in NTT form
@throws std::invalid_argument if pool is uninitialized
*/
void decode(Plaintext &plain, MemoryPoolHandle pool = MemoryManager::GetPool());
/**
Returns the number of slots.
*/
SEAL_NODISCARD inline auto slot_count() const noexcept
{
return slots_;
}
private:
BatchEncoder(const BatchEncoder &copy) = delete;
BatchEncoder(BatchEncoder &&source) = delete;
BatchEncoder &operator=(const BatchEncoder &assign) = delete;
BatchEncoder &operator=(BatchEncoder &&assign) = delete;
void populate_roots_of_unity_vector(const SEALContext::ContextData &context_data);
void populate_matrix_reps_index_map();
void reverse_bits(std::uint64_t *input);
MemoryPoolHandle pool_ = MemoryManager::GetPool();
std::shared_ptr<SEALContext> context_{ nullptr };
std::size_t slots_;
util::Pointer<std::uint64_t> roots_of_unity_;
util::Pointer<std::size_t> matrix_reps_index_map_;
};
} // namespace seal
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include "seal/biguint.h"
#include "seal/util/common.h"
#include "seal/util/uintarith.h"
#include "seal/util/uintarithmod.h"
#include "seal/util/uintcore.h"
#include <algorithm>
using namespace std;
using namespace seal::util;
namespace seal
{
BigUInt::BigUInt(int bit_count)
{
resize(bit_count);
}
BigUInt::BigUInt(const string &hex_value)
{
operator=(hex_value);
}
BigUInt::BigUInt(int bit_count, const string &hex_value)
{
resize(bit_count);
operator=(hex_value);
if (bit_count != bit_count_)
{
resize(bit_count);
}
}
BigUInt::BigUInt(int bit_count, uint64_t *value) : value_(decltype(value_)::Aliasing(value)), bit_count_(bit_count)
{
if (bit_count < 0)
{
throw invalid_argument("bit_count must be non-negative");
}
if (value == nullptr && bit_count > 0)
{
throw invalid_argument("value must be non-null for non-zero bit count");
}
}
#ifdef SEAL_USE_MSGSL
BigUInt::BigUInt(gsl::span<uint64_t> value)
{
if (unsigned_gt(value.size(), numeric_limits<int>::max() / bits_per_uint64))
{
throw std::invalid_argument("value has too large size");
}
value_ = decltype(value_)::Aliasing(value.data());
bit_count_ = static_cast<int>(value.size()) * bits_per_uint64;
}
#endif
BigUInt::BigUInt(int bit_count, uint64_t value)
{
resize(bit_count);
operator=(value);
if (bit_count != bit_count_)
{
resize(bit_count);
}
}
BigUInt::BigUInt(const BigUInt &copy)
{
resize(copy.bit_count());
operator=(copy);
}
BigUInt::BigUInt(BigUInt &&source) noexcept
: pool_(move(source.pool_)), value_(move(source.value_)), bit_count_(source.bit_count_)
{
// Pointer in source has been taken over so set it to nullptr
source.bit_count_ = 0;
}
BigUInt::~BigUInt() noexcept
{
reset();
}
string BigUInt::to_string() const
{
return uint_to_hex_string(value_.get(), uint64_count());
}
string BigUInt::to_dec_string() const
{
return uint_to_dec_string(value_.get(), uint64_count(), pool_);
}
void BigUInt::resize(int bit_count)
{
if (bit_count < 0)
{
throw invalid_argument("bit_count must be non-negative");
}
if (value_.is_alias())
{
throw logic_error("Cannot resize an aliased BigUInt");
}
if (bit_count == bit_count_)
{
return;
}
// Lazy initialization of MemoryPoolHandle
if (!pool_)
{
pool_ = MemoryManager::GetPool();
}
// Fast path if allocation size doesn't change.
size_t old_uint64_count = uint64_count();
size_t new_uint64_count = safe_cast<size_t>(divide_round_up(bit_count, bits_per_uint64));
if (old_uint64_count == new_uint64_count)
{
bit_count_ = bit_count;
return;
}
// Allocate new space.
decltype(value_) new_value;
if (new_uint64_count > 0)
{
new_value = allocate_uint(new_uint64_count, pool_);
}
// Copy over old value.
if (new_uint64_count > 0)
{
set_uint_uint(value_.get(), old_uint64_count, new_uint64_count, new_value.get());
filter_highbits_uint(new_value.get(), new_uint64_count, bit_count);
}
// Deallocate any owned pointers.
reset();
// Update class.
swap(value_, new_value);
bit_count_ = bit_count;
}
BigUInt &BigUInt::operator=(const BigUInt &assign)
{
// Do nothing if same thing.
if (&assign == this)
{
return *this;
}
// Verify assigned value will fit within bit count.
int assign_sig_bit_count = assign.significant_bit_count();
if (assign_sig_bit_count > bit_count_)
{
// Size is too large to currently fit, so resize.
resize(assign_sig_bit_count);
}
// Copy over value.
size_t assign_uint64_count = safe_cast<size_t>(divide_round_up(assign_sig_bit_count, bits_per_uint64));
if (uint64_count() > 0)
{
set_uint_uint(assign.value_.get(), assign_uint64_count, uint64_count(), value_.get());
}
return *this;
}
BigUInt &BigUInt::operator=(const string &hex_value)
{
int hex_value_length = safe_cast<int>(hex_value.size());
int assign_bit_count = get_hex_string_bit_count(hex_value.data(), hex_value_length);
if (assign_bit_count > bit_count_)
{
// Size is too large to currently fit, so resize.
resize(assign_bit_count);
}
if (bit_count_ > 0)
{
// Copy over value.
hex_string_to_uint(hex_value.data(), hex_value_length, uint64_count(), value_.get());
}
return *this;
}
BigUInt BigUInt::operator/(const BigUInt &operand2) const
{
int result_bits = significant_bit_count();
int operand2_bits = operand2.significant_bit_count();
if (operand2_bits == 0)
{
throw invalid_argument("operand2 must be positive");
}
if (operand2_bits > result_bits)
{
BigUInt zero(result_bits);
return zero;
}
BigUInt result(result_bits);
BigUInt remainder(result_bits);
size_t result_uint64_count = result.uint64_count();
if (result_uint64_count > operand2.uint64_count())
{
BigUInt operand2resized(result_bits);
operand2resized = operand2;
divide_uint_uint(
value_.get(), operand2resized.data(), result_uint64_count, result.data(), remainder.data(), pool_);
}
else
{
divide_uint_uint(
value_.get(), operand2.data(), result_uint64_count, result.data(), remainder.data(), pool_);
}
return result;
}
BigUInt BigUInt::divrem(const BigUInt &operand2, BigUInt &remainder) const
{
int result_bits = significant_bit_count();
remainder = *this;
int operand2_bits = operand2.significant_bit_count();
if (operand2_bits > result_bits)
{
BigUInt zero;
return zero;
}
BigUInt quotient(result_bits);
size_t uint64_count = remainder.uint64_count();
if (uint64_count > operand2.uint64_count())
{
BigUInt operand2resized(result_bits);
operand2resized = operand2;
divide_uint_uint_inplace(remainder.data(), operand2resized.data(), uint64_count, quotient.data(), pool_);
}
else
{
divide_uint_uint_inplace(remainder.data(), operand2.data(), uint64_count, quotient.data(), pool_);
}
return quotient;
}
void BigUInt::save_members(ostream &stream) const
{
auto old_except_mask = stream.exceptions();
try
{
// Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
stream.exceptions(ios_base::badbit | ios_base::failbit);
int32_t bit_count32 = safe_cast<int32_t>(bit_count_);
streamsize data_size = safe_cast<streamsize>(mul_safe(uint64_count(), sizeof(uint64_t)));
stream.write(reinterpret_cast<const char *>(&bit_count32), sizeof(int32_t));
if (data_size)
{
stream.write(reinterpret_cast<const char *>(value_.get()), data_size);
}
}
catch (const ios_base::failure &)
{
stream.exceptions(old_except_mask);
throw runtime_error("I/O error");
}
catch (...)
{
stream.exceptions(old_except_mask);
throw;
}
stream.exceptions(old_except_mask);
}
void BigUInt::load_members(istream &stream)
{
auto old_except_mask = stream.exceptions();
try
{
// Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
stream.exceptions(ios_base::badbit | ios_base::failbit);
int32_t read_bit_count = 0;
stream.read(reinterpret_cast<char *>(&read_bit_count), sizeof(int32_t));
if (read_bit_count > bit_count_)
{
// Size is too large to currently fit, so resize.
resize(read_bit_count);
}
size_t read_uint64_count = safe_cast<size_t>(divide_round_up(read_bit_count, bits_per_uint64));
streamsize data_size = safe_cast<streamsize>(mul_safe(read_uint64_count, sizeof(uint64_t)));
if (data_size)
{
stream.read(reinterpret_cast<char *>(value_.get()), data_size);
}
// Zero any extra space.
if (uint64_count() > read_uint64_count)
{
set_zero_uint(uint64_count() - read_uint64_count, value_.get() + read_uint64_count);
}
}
catch (const ios_base::failure &)
{
stream.exceptions(old_except_mask);
throw runtime_error("I/O error");
}
catch (...)
{
stream.exceptions(old_except_mask);
throw;
}
stream.exceptions(old_except_mask);
}
} // namespace seal
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
#include "seal/memorymanager.h"
#include "seal/serialization.h"
#include "seal/util/common.h"
#include "seal/util/defines.h"
#include "seal/util/pointer.h"
#include "seal/util/uintarith.h"
#include "seal/util/uintarithmod.h"
#include "seal/util/uintcore.h"
#include "seal/util/ztools.h"
#include <cstdint>
#include <iostream>
#include <string>
#ifdef SEAL_USE_MSGSL
#include <gsl/span>
#endif
namespace seal
{
/**
Represents an unsigned integer with a specified bit width. Non-const
BigUInts are mutable and able to be resized. The bit count for a BigUInt
(which can be read with bit_count()) is set initially by the constructor
and can be resized either explicitly with the resize() function or
implicitly with an assignment operation (e.g., operator=(), operator+=(),
etc.). A rich set of unsigned integer operations are provided by the
BigUInt class, including comparison, traditional arithmetic (addition,
subtraction, multiplication, division), and modular arithmetic functions.
@par Backing Array
The backing array for a BigUInt stores its unsigned integer value as
a contiguous std::uint64_t array. Each std::uint64_t in the array
sequentially represents 64-bits of the integer value, with the least
significant quad-word storing the lower 64-bits and the order of the bits
for each quad word dependent on the architecture's std::uint64_t
representation. The size of the array equals the bit count of the BigUInt
(which can be read with bit_count()) rounded up to the next std::uint64_t
boundary (i.e., rounded up to the next 64-bit boundary). The uint64_count()
function returns the number of std::uint64_t in the backing array. The
data() function returns a pointer to the first std::uint64_t in the array.
Additionally, the operator [] function allows accessing the individual
bytes of the integer value in a platform-independent way - for example,
reading the third byte will always return bits 16-24 of the BigUInt value
regardless of the platform being little-endian or big-endian.
@par Implicit Resizing
Both the copy constructor and operator=() allocate more memory for the
backing array when needed, i.e. when the source BigUInt has a larger
backing array than the destination. Conversely, when the destination
backing array is already large enough, the data is only copied and the
unnecessary higher order bits are set to zero. When new memory has to be
allocated, only the significant bits of the source BigUInt are taken
into account. This is is important, because it avoids unnecessary zero
bits to be included in the destination, which in some cases could
accumulate and result in very large unnecessary allocations. However,
sometimes it is necessary to preserve the original size, even if some
of the leading bits are zero. For this purpose BigUInt contains functions
duplicate_from and duplicate_to, which create an exact copy of the source
BigUInt.
@par Alias BigUInts
An aliased BigUInt (which can be determined with is_alias()) is a special
type of BigUInt that does not manage its underlying std::uint64_t pointer
used to store the value. An aliased BigUInt supports most of the same
operations as a non-aliased BigUInt, including reading and writing the
value, however an aliased BigUInt does not internally allocate or
deallocate its backing array and, therefore, does not support resizing.
Any attempt, either explicitly or implicitly, to resize the BigUInt will
result in an exception being thrown. An aliased BigUInt can be created
with the BigUInt(int, std::uint64_t*) constructor or the alias() function.
Note that the pointer specified to be aliased must be deallocated
externally after the BigUInt is no longer in use. Aliasing is useful in
cases where it is desirable to not have each BigUInt manage its own memory
allocation and/or to prevent unnecessary copying.
@par Thread Safety
In general, reading a BigUInt is thread-safe while mutating is not.
Specifically, the backing array may be freed whenever a resize occurs,
the BigUInt is destroyed, or alias() is called, which would invalidate
the address returned by data() and the byte references returned by
operator []. When it is known that a resize will not occur, concurrent
reading and mutating will not inherently fail but it is possible for
a read to see a partially updated value from a concurrent write.
A non-aliased BigUInt allocates its backing array from the global
(thread-safe) memory pool. Consequently, creating or resizing a large
number of BigUInt can result in a performance loss due to thread
contention.
*/
class BigUInt
{
public:
/**
Creates an empty BigUInt with zero bit width. No memory is allocated
by this constructor.
*/
BigUInt() = default;
/**
Creates a zero-initialized BigUInt of the specified bit width.
@param[in] bit_count The bit width
@throws std::invalid_argument if bit_count is negative
*/
BigUInt(int bit_count);
/**
Creates a BigUInt initialized and minimally sized to fit the unsigned
hexadecimal integer specified by the string. The string matches the format
returned by to_string() and must consist of only the characters 0-9, A-F,
or a-f, most-significant nibble first.
@param[in] hex_value The hexadecimal integer string specifying the initial
value
@throws std::invalid_argument if hex_value does not adhere to the expected
format
*/
BigUInt(const std::string &hex_value);
/**
Creates a BigUInt of the specified bit width and initializes it with the
unsigned hexadecimal integer specified by the string. The string must match
the format returned by to_string() and must consist of only the characters
0-9, A-F, or a-f, most-significant nibble first.
@param[in] bit_count The bit width
@param[in] hex_value The hexadecimal integer string specifying the initial
value
@throws std::invalid_argument if bit_count is negative
@throws std::invalid_argument if hex_value does not adhere to the expected
format
*/
BigUInt(int bit_count, const std::string &hex_value);
/**
Creates an aliased BigUInt with the specified bit width and backing array.
An aliased BigUInt does not internally allocate or deallocate the backing
array, and instead uses the specified backing array for all read/write
operations. Note that resizing is not supported by an aliased BigUInt and
any required deallocation of the specified backing array must occur
externally after the aliased BigUInt is no longer in use.
@param[in] bit_count The bit width
@param[in] value The backing array to use
@throws std::invalid_argument if bit_count is negative or value is null
and bit_count is positive
*/
BigUInt(int bit_count, std::uint64_t *value);
#ifdef SEAL_USE_MSGSL
/**
Creates an aliased BigUInt with given backing array and bit width set to
the size of the backing array. An aliased BigUInt does not internally
allocate or deallocate the backing array, and instead uses the specified
backing array for all read/write operations. Note that resizing is not
supported by an aliased BigUInt and any required deallocation of the
specified backing array must occur externally after the aliased BigUInt
is no longer in use.
@param[in] value The backing array to use
@throws std::invalid_argument if value has too large size
*/
BigUInt(gsl::span<std::uint64_t> value);
#endif
/**
Creates a BigUInt of the specified bit width and initializes it to the
specified unsigned integer value.
@param[in] bit_count The bit width
@param[in] value The initial value to set the BigUInt
@throws std::invalid_argument if bit_count is negative
*/
BigUInt(int bit_count, std::uint64_t value);
/**
Creates a deep copy of a BigUInt. The created BigUInt will have the same
bit count and value as the original.
@param[in] copy The BigUInt to copy from
*/
BigUInt(const BigUInt &copy);
/**
Creates a new BigUInt by moving an old one.
@param[in] source The BigUInt to move from
*/
BigUInt(BigUInt &&source) noexcept;
/**
Destroys the BigUInt and deallocates the backing array if it is not
an aliased BigUInt.
*/
~BigUInt() noexcept;
/**
Returns whether or not the BigUInt is an alias.
*/
SEAL_NODISCARD inline bool is_alias() const noexcept
{
return value_.is_alias();
}
/**
Returns the bit count for the BigUInt.
*/
SEAL_NODISCARD inline int bit_count() const noexcept
{
return bit_count_;
}
/**
Returns a pointer to the backing array storing the BigUInt value.
The pointer points to the beginning of the backing array at the
least-significant quad word.
@warning The pointer is valid only until the backing array is freed,
which occurs when the BigUInt is resized, destroyed, or the alias()
function is called.
*/
SEAL_NODISCARD inline std::uint64_t *data()
{
return value_.get();
}
/**
Returns a const pointer to the backing array storing the BigUInt value.
The pointer points to the beginning of the backing array at the
least-significant quad word.
@warning The pointer is valid only until the backing array is freed, which
occurs when the BigUInt is resized, destroyed, or the alias() function is
called.
*/
SEAL_NODISCARD inline const std::uint64_t *data() const noexcept
{
return value_.get();
}
#ifdef SEAL_USE_MSGSL
/**
Returns the backing array storing the BigUInt value.
@warning The span is valid only until the backing array is freed, which
occurs when the BigUInt is resized, destroyed, or the alias() function is
called.
*/
SEAL_NODISCARD inline gsl::span<std::uint64_t> data_span()
{
return gsl::span<std::uint64_t>(value_.get(), uint64_count());
}
/**
Returns the backing array storing the BigUInt value.
@warning The span is valid only until the backing array is freed, which
occurs when the BigUInt is resized, destroyed, or the alias() function is
called.
*/
SEAL_NODISCARD inline gsl::span<const std::uint64_t> data_span() const
{
return gsl::span<const std::uint64_t>(value_.get(), uint64_count());
}
#endif
/**
Returns the number of bytes in the backing array used to store the BigUInt
value.
*/
SEAL_NODISCARD inline std::size_t byte_count() const
{
return static_cast<std::size_t>(util::divide_round_up(bit_count_, util::bits_per_byte));
}
/**
Returns the number of std::uint64_t in the backing array used to store
the BigUInt value.
*/
SEAL_NODISCARD inline std::size_t uint64_count() const
{
return static_cast<std::size_t>(util::divide_round_up(bit_count_, util::bits_per_uint64));
}
/**
Returns the number of significant bits for the BigUInt.
*/
SEAL_NODISCARD inline int significant_bit_count() const
{
if (bit_count_ == 0)
{
return 0;
}
return util::get_significant_bit_count_uint(value_.get(), uint64_count());
}
/**
Returns the BigUInt value as a double. Note that precision may be lost during
the conversion.
*/
SEAL_NODISCARD double to_double() const noexcept
{
const double TwoToThe64 = 18446744073709551616.0;
double result = 0;
for (std::size_t i = uint64_count(); i--;)
{
result *= TwoToThe64;
result += static_cast<double>(value_[i]);
}
return result;
}
/**
Returns the BigUInt value as a hexadecimal string.
*/
SEAL_NODISCARD std::string to_string() const;
/**
Returns the BigUInt value as a decimal string.
*/
SEAL_NODISCARD std::string to_dec_string() const;
/**
Returns whether or not the BigUInt has the value zero.
*/
SEAL_NODISCARD inline bool is_zero() const
{
if (bit_count_ == 0)
{
return true;
}
return util::is_zero_uint(value_.get(), uint64_count());
}
/**
Returns the byte at the corresponding byte index of the BigUInt's integer
value. The bytes of the BigUInt are indexed least-significant byte first.
@param[in] index The index of the byte to read
@throws std::out_of_range if index is not within [0, byte_count())
*/
SEAL_NODISCARD inline const SEAL_BYTE &operator[](std::size_t index) const
{
if (index >= byte_count())
{
throw std::out_of_range("index must be within [0, byte count)");
}
return *util::get_uint64_byte(value_.get(), index);
}
/**
Returns an byte reference that can read/write the byte at the corresponding
byte index of the BigUInt's integer value. The bytes of the BigUInt are
indexed least-significant byte first.
@warning The returned byte is an reference backed by the BigUInt's backing
array. As such, it is only valid until the BigUInt is resized, destroyed,
or alias() is called.
@param[in] index The index of the byte to read
@throws std::out_of_range if index is not within [0, byte_count())
*/
SEAL_NODISCARD inline SEAL_BYTE &operator[](std::size_t index)
{
if (index >= byte_count())
{
throw std::out_of_range("index must be within [0, byte count)");
}
return *util::get_uint64_byte(value_.get(), index);
}
/**
Sets the BigUInt value to zero. This does not resize the BigUInt.
*/
inline void set_zero()
{
if (bit_count_)
{
return util::set_zero_uint(uint64_count(), value_.get());
}
}
/**
Resizes the BigUInt to the specified bit width, copying over the old value
as much as will fit.
@param[in] bit_count The bit width
@throws std::invalid_argument if bit_count is negative
@throws std::logic_error if the BigUInt is an alias
*/
void resize(int bit_count);
/**
Makes the BigUInt an aliased BigUInt with the specified bit width and
backing array. An aliased BigUInt does not internally allocate or
deallocate the backing array, and instead uses the specified backing array
for all read/write operations. Note that resizing is not supported by
an aliased BigUInt and any required deallocation of the specified backing
array must occur externally after the aliased BigUInt is no longer in use.
@param[in] bit_count The bit width
@param[in] value The backing array to use
@throws std::invalid_argument if bit_count is negative or value is null
*/
inline void alias(int bit_count, std::uint64_t *value)
{
if (bit_count < 0)
{
throw std::invalid_argument("bit_count must be non-negative");
}
if (value == nullptr && bit_count > 0)
{
throw std::invalid_argument("value must be non-null for non-zero bit count");
}
// Deallocate any owned pointers.
reset();
// Update class.
value_ = util::Pointer<std::uint64_t>::Aliasing(value);
bit_count_ = bit_count;
}
#ifdef SEAL_USE_MSGSL
/**
Makes the BigUInt an aliased BigUInt with the given backing array
and bit width set equal to the size of the backing array. An aliased
BigUInt does not internally allocate or deallocate the backing array,
and instead uses the specified backing array for all read/write
operations. Note that resizing is not supported by an aliased BigUInt
and any required deallocation of the specified backing array must
occur externally after the aliased BigUInt is no longer in use.
@param[in] value The backing array to use
@throws std::invalid_argument if value has too large size
*/
inline void alias(gsl::span<std::uint64_t> value)
{
if (util::unsigned_gt(value.size(), std::numeric_limits<int>::max()))
{
throw std::invalid_argument("value has too large size");
}
// Deallocate any owned pointers.
reset();
// Update class.
value_ = util::Pointer<std::uint64_t>::Aliasing(value.data());
bit_count_ = static_cast<int>(value.size());
;
}
#endif
/**
Resets an aliased BigUInt into an empty non-alias BigUInt with bit count
of zero.
@throws std::logic_error if BigUInt is not an alias
*/
inline void unalias()
{
if (!value_.is_alias())
{
throw std::logic_error("BigUInt is not an alias");
}
// Reset class.
reset();
}
/**
Overwrites the BigUInt with the value of the specified BigUInt, enlarging
if needed to fit the assigned value. Only significant bits are used to
size the BigUInt.
@param[in] assign The BigUInt whose value should be assigned to the
current BigUInt
@throws std::logic_error if BigUInt is an alias and the assigned BigUInt is
too large to fit the current bit width
*/
BigUInt &operator=(const BigUInt &assign);
/**
Overwrites the BigUInt with the unsigned hexadecimal value specified by
the string, enlarging if needed to fit the assigned value. The string must
match the format returned by to_string() and must consist of only the
characters 0-9, A-F, or a-f, most-significant nibble first.
@param[in] hex_value The hexadecimal integer string specifying the value
to assign
@throws std::invalid_argument if hex_value does not adhere to the
expected format
@throws std::logic_error if BigUInt is an alias and the assigned value
is too large to fit the current bit width
*/
BigUInt &operator=(const std::string &hex_value);
/**
Overwrites the BigUInt with the specified integer value, enlarging if
needed to fit the value.
@param[in] value The value to assign
@throws std::logic_error if BigUInt is an alias and the significant bit
count of value is too large to fit the
current bit width
*/
inline BigUInt &operator=(std::uint64_t value)
{
int assign_bit_count = util::get_significant_bit_count(value);
if (assign_bit_count > bit_count_)
{
// Size is too large to currently fit, so resize.
resize(assign_bit_count);
}
if (bit_count_ > 0)
{
util::set_uint(value, uint64_count(), value_.get());
}
return *this;
}
/**
Returns a copy of the BigUInt value resized to the significant bit count.
*/
SEAL_NODISCARD inline BigUInt operator+() const
{
BigUInt result;
result = *this;
return result;
}
/**
Returns a negated copy of the BigUInt value. The bit count does not change.
*/
SEAL_NODISCARD inline BigUInt operator-() const
{
BigUInt result(bit_count_);
util::negate_uint(value_.get(), result.uint64_count(), result.data());
util::filter_highbits_uint(result.data(), result.uint64_count(), result.bit_count());
return result;
}
/**
Returns an inverted copy of the BigUInt value. The bit count does not change.
*/
SEAL_NODISCARD inline BigUInt operator~() const
{
BigUInt result(bit_count_);
util::not_uint(value_.get(), result.uint64_count(), result.data());
util::filter_highbits_uint(result.data(), result.uint64_count(), result.bit_count());
return result;
}
/**
Increments the BigUInt and returns the incremented value. The BigUInt will
increment the bit count if needed to fit the carry.
@throws std::logic_error if BigUInt is an alias and a carry occurs requiring
the BigUInt to be resized
*/
inline BigUInt &operator++()
{
if (util::increment_uint(value_.get(), uint64_count(), value_.get()))
{
resize(util::add_safe(bit_count_, 1));
util::set_bit_uint(value_.get(), uint64_count(), bit_count_);
}
bit_count_ = std::max(bit_count_, significant_bit_count());
return *this;
}
/**
Decrements the BigUInt and returns the decremented value. The bit count
does not change.
*/
inline BigUInt &operator--()
{
util::decrement_uint(value_.get(), uint64_count(), value_.get());
util::filter_highbits_uint(value_.get(), uint64_count(), bit_count_);
return *this;
}
#ifndef SEAL_USE_MAYBE_UNUSED
#if (SEAL_COMPILER == SEAL_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#endif
/**
Increments the BigUInt but returns its old value. The BigUInt will increment
the bit count if needed to fit the carry.
*/
inline BigUInt operator++(int postfix SEAL_MAYBE_UNUSED)
{
BigUInt result;
result = *this;
if (util::increment_uint(value_.get(), uint64_count(), value_.get()))
{
resize(util::add_safe(bit_count_, 1));
util::set_bit_uint(value_.get(), uint64_count(), bit_count_);
}
bit_count_ = std::max(bit_count_, significant_bit_count());
return result;
}
/**
Decrements the BigUInt but returns its old value. The bit count does not change.
*/
inline BigUInt operator--(int postfix SEAL_MAYBE_UNUSED)
{
BigUInt result;
result = *this;
util::decrement_uint(value_.get(), uint64_count(), value_.get());
util::filter_highbits_uint(value_.get(), uint64_count(), bit_count_);
return result;
}
#ifndef SEAL_USE_MAYBE_UNUSED
#if (SEAL_COMPILER == SEAL_COMPILER_GCC)
#pragma GCC diagnostic pop
#elif (SEAL_COMPILER == SEAL_COMPILER_CLANG)
#pragma clang diagnostic pop
#endif
#endif
/**
Adds two BigUInts and returns the sum. The input operands are not modified.
The bit count of the sum is set to be one greater than the significant bit
count of the larger of the two input operands.
@param[in] operand2 The second operand to add
*/
SEAL_NODISCARD inline BigUInt operator+(const BigUInt &operand2) const
{
int result_bits = util::add_safe(std::max(significant_bit_count(), operand2.significant_bit_count()), 1);
BigUInt result(result_bits);
util::add_uint_uint(
value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, result.uint64_count(),
result.data());
return result;
}
/**
Adds a BigUInt and an unsigned integer and returns the sum. The input
operands are not modified. The bit count of the sum is set to be one greater
than the significant bit count of the larger of the two operands.
@param[in] operand2 The second operand to add
*/
SEAL_NODISCARD inline BigUInt operator+(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this + operand2uint;
}
/**
Subtracts two BigUInts and returns the difference. The input operands are
not modified. The bit count of the difference is set to be the significant
bit count of the larger of the two input operands.
@param[in] operand2 The second operand to subtract
*/
SEAL_NODISCARD inline BigUInt operator-(const BigUInt &operand2) const
{
int result_bits = std::max(bit_count_, operand2.bit_count());
BigUInt result(result_bits);
util::sub_uint_uint(
value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, result.uint64_count(),
result.data());
util::filter_highbits_uint(result.data(), result.uint64_count(), result_bits);
return result;
}
/**
Subtracts a BigUInt and an unsigned integer and returns the difference.
The input operands are not modified. The bit count of the difference is set
to be the significant bit count of the larger of the two operands.
@param[in] operand2 The second operand to subtract
*/
SEAL_NODISCARD inline BigUInt operator-(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this - operand2uint;
}
/**
Multiplies two BigUInts and returns the product. The input operands are
not modified. The bit count of the product is set to be the sum of the
significant bit counts of the two input operands.
@param[in] operand2 The second operand to multiply
*/
SEAL_NODISCARD inline BigUInt operator*(const BigUInt &operand2) const
{
int result_bits = util::add_safe(significant_bit_count(), operand2.significant_bit_count());
BigUInt result(result_bits);
util::multiply_uint_uint(
value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), result.uint64_count(),
result.data());
return result;
}
/**
Multiplies a BigUInt and an unsigned integer and returns the product.
The input operands are not modified. The bit count of the product is set
to be the sum of the significant bit counts of the two input operands.
@param[in] operand2 The second operand to multiply
*/
SEAL_NODISCARD inline BigUInt operator*(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this * operand2uint;
}
/**
Divides two BigUInts and returns the quotient. The input operands are
not modified. The bit count of the quotient is set to be the significant
bit count of the first input operand.
@param[in] operand2 The second operand to divide
@throws std::invalid_argument if operand2 is zero
*/
SEAL_NODISCARD BigUInt operator/(const BigUInt &operand2) const;
/**
Divides a BigUInt and an unsigned integer and returns the quotient. The
input operands are not modified. The bit count of the quotient is set
to be the significant bit count of the first input operand.
@param[in] operand2 The second operand to divide
@throws std::invalid_argument if operand2 is zero
*/
SEAL_NODISCARD inline BigUInt operator/(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this / operand2uint;
}
/**
Performs a bit-wise XOR operation between two BigUInts and returns the
result. The input operands are not modified. The bit count of the result
is set to the maximum of the two input operand bit counts.
@param[in] operand2 The second operand to XOR
*/
SEAL_NODISCARD inline BigUInt operator^(const BigUInt &operand2) const
{
int result_bits = std::max(bit_count_, operand2.bit_count());
BigUInt result(result_bits);
std::size_t uint64_count = result.uint64_count();
if (uint64_count != this->uint64_count())
{
result = *this;
util::xor_uint_uint(result.data(), operand2.data(), uint64_count, result.data());
}
else if (uint64_count != operand2.uint64_count())
{
result = operand2;
util::xor_uint_uint(result.data(), value_.get(), uint64_count, result.data());
}
else
{
util::xor_uint_uint(value_.get(), operand2.data(), uint64_count, result.data());
}
return result;
}
/**
Performs a bit-wise XOR operation between a BigUInt and an unsigned
integer and returns the result. The input operands are not modified.
The bit count of the result is set to the maximum of the two input
operand bit counts.
@param[in] operand2 The second operand to XOR
*/
SEAL_NODISCARD inline BigUInt operator^(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this ^ operand2uint;
}
/**
Performs a bit-wise AND operation between two BigUInts and returns the
result. The input operands are not modified. The bit count of the result
is set to the maximum of the two input operand bit counts.
@param[in] operand2 The second operand to AND
*/
SEAL_NODISCARD inline BigUInt operator&(const BigUInt &operand2) const
{
int result_bits = std::max(bit_count_, operand2.bit_count());
BigUInt result(result_bits);
std::size_t uint64_count = result.uint64_count();
if (uint64_count != this->uint64_count())
{
result = *this;
util::and_uint_uint(result.data(), operand2.data(), uint64_count, result.data());
}
else if (uint64_count != operand2.uint64_count())
{
result = operand2;
util::and_uint_uint(result.data(), value_.get(), uint64_count, result.data());
}
else
{
util::and_uint_uint(value_.get(), operand2.data(), uint64_count, result.data());
}
return result;
}
/**
Performs a bit-wise AND operation between a BigUInt and an unsigned
integer and returns the result. The input operands are not modified.
The bit count of the result is set to the maximum of the two input
operand bit counts.
@param[in] operand2 The second operand to AND
*/
SEAL_NODISCARD inline BigUInt operator&(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this & operand2uint;
}
/**
Performs a bit-wise OR operation between two BigUInts and returns the
result. The input operands are not modified. The bit count of the result
is set to the maximum of the two input operand bit counts.
@param[in] operand2 The second operand to OR
*/
SEAL_NODISCARD inline BigUInt operator|(const BigUInt &operand2) const
{
int result_bits = std::max(bit_count_, operand2.bit_count());
BigUInt result(result_bits);
std::size_t uint64_count = result.uint64_count();
if (uint64_count != this->uint64_count())
{
result = *this;
util::or_uint_uint(result.data(), operand2.data(), uint64_count, result.data());
}
else if (uint64_count != operand2.uint64_count())
{
result = operand2;
util::or_uint_uint(result.data(), value_.get(), uint64_count, result.data());
}
else
{
util::or_uint_uint(value_.get(), operand2.data(), uint64_count, result.data());
}
return result;
}
/**
Performs a bit-wise OR operation between a BigUInt and an unsigned
integer and returns the result. The input operands are not modified.
The bit count of the result is set to the maximum of the two input
operand bit counts.
@param[in] operand2 The second operand to OR
*/
SEAL_NODISCARD inline BigUInt operator|(std::uint64_t operand2) const
{
BigUInt operand2uint;
operand2uint = operand2;
return *this | operand2uint;
}
/**
Compares two BigUInts and returns -1, 0, or 1 if the BigUInt is
less-than, equal-to, or greater-than the second operand respectively.
The input operands are not modified.
@param[in] compare The value to compare against
*/
SEAL_NODISCARD inline int compareto(const BigUInt &compare) const
{
return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count());
}
/**
Compares a BigUInt and an unsigned integer and returns -1, 0, or 1 if
the BigUInt is less-than, equal-to, or greater-than the second operand
respectively. The input operands are not modified.
@param[in] compare The value to compare against
*/
SEAL_NODISCARD inline int compareto(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return compareto(compareuint);
}
/**
Returns whether or not a BigUInt is less-than a second BigUInt. The
input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator<(const BigUInt &compare) const
{
return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) <
0;
}
/**
Returns whether or not a BigUInt is less-than an unsigned integer.
The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator<(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this < compareuint;
}
/**
Returns whether or not a BigUInt is greater-than a second BigUInt.
The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator>(const BigUInt &compare) const
{
return util::compare_uint_uint(value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) >
0;
}
/**
Returns whether or not a BigUInt is greater-than an unsigned integer.
The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator>(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this > compareuint;
}
/**
Returns whether or not a BigUInt is less-than or equal to a second
BigUInt. The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator<=(const BigUInt &compare) const
{
return util::compare_uint_uint(
value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) <= 0;
}
/**
Returns whether or not a BigUInt is less-than or equal to an unsigned
integer. The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator<=(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this <= compareuint;
}
/**
Returns whether or not a BigUInt is greater-than or equal to a second
BigUInt. The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator>=(const BigUInt &compare) const
{
return util::compare_uint_uint(
value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) >= 0;
}
/**
Returns whether or not a BigUInt is greater-than or equal to an unsigned
integer. The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator>=(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this >= compareuint;
}
/**
Returns whether or not a BigUInt is equal to a second BigUInt.
The input operands are not modified.
@param[in] compare The value to compare against
*/
SEAL_NODISCARD inline bool operator==(const BigUInt &compare) const
{
return util::compare_uint_uint(
value_.get(), uint64_count(), compare.value_.get(), compare.uint64_count()) == 0;
}
/**
Returns whether or not a BigUInt is equal to an unsigned integer.
The input operands are not modified.
@param[in] compare The value to compare against
*/
SEAL_NODISCARD inline bool operator==(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this == compareuint;
}
/**
Returns whether or not a BigUInt is not equal to a second BigUInt.
The input operands are not modified.
@param[in] compare The value to compare against
*/
SEAL_NODISCARD inline bool operator!=(const BigUInt &compare) const
{
return !(operator==(compare));
}
/**
Returns whether or not a BigUInt is not equal to an unsigned integer.
The input operands are not modified.
@param[in] operand2 The value to compare against
*/
SEAL_NODISCARD inline bool operator!=(std::uint64_t compare) const
{
BigUInt compareuint;
compareuint = compare;
return *this != compareuint;
}
/**
Returns a left-shifted copy of the BigUInt. The bit count of the
returned value is the sum of the original significant bit count and
the shift amount.
@param[in] shift The number of bits to shift by
@throws std::invalid_argument if shift is negative
*/
SEAL_NODISCARD inline BigUInt operator<<(int shift) const
{
if (shift < 0)
{
throw std::invalid_argument("shift must be non-negative");
}
int result_bits = util::add_safe(significant_bit_count(), shift);
BigUInt result(result_bits);
result = *this;
util::left_shift_uint(result.data(), shift, result.uint64_count(), result.data());
return result;
}
/**
Returns a right-shifted copy of the BigUInt. The bit count of the
returned value is the original significant bit count subtracted by
the shift amount (clipped to zero if negative).
@param[in] shift The number of bits to shift by
@throws std::invalid_argument if shift is negative
*/
SEAL_NODISCARD inline BigUInt operator>>(int shift) const
{
if (shift < 0)
{
throw std::invalid_argument("shift must be non-negative");
}
int result_bits = util::sub_safe(significant_bit_count(), shift);
if (result_bits <= 0)
{
BigUInt zero;
return zero;
}
BigUInt result(result_bits);
result = *this;
util::right_shift_uint(result.data(), shift, result.uint64_count(), result.data());
return result;
}
/**
Adds two BigUInts saving the sum to the first operand, returning
a reference of the first operand. The second input operand is not
modified. The first operand is resized if and only if its bit count
is smaller than one greater than the significant bit count of the
larger of the two input operands.
@param[in] operand2 The second operand to add
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator+=(const BigUInt &operand2)
{
int result_bits = util::add_safe(std::max(significant_bit_count(), operand2.significant_bit_count()), 1);
if (bit_count_ < result_bits)
{
resize(result_bits);
}
util::add_uint_uint(
value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, uint64_count(),
value_.get());
return *this;
}
/**
Adds a BigUInt and an unsigned integer saving the sum to the first operand,
returning a reference of the first operand. The second input operand is not
modified. The first operand is resized if and only if its bit count is
smaller than one greater than the significant bit count of the larger of
the two input operands.
@param[in] operand2 The second operand to add
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator+=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator+=(operand2uint);
}
/**
Subtracts two BigUInts saving the difference to the first operand,
returning a reference of the first operand. The second input operand is
not modified. The first operand is resized if and only if its bit count
is smaller than the significant bit count of the second operand.
@param[in] operand2 The second operand to subtract
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator-=(const BigUInt &operand2)
{
int result_bits = std::max(bit_count_, operand2.bit_count());
if (bit_count_ < result_bits)
{
resize(result_bits);
}
util::sub_uint_uint(
value_.get(), uint64_count(), operand2.data(), operand2.uint64_count(), false, uint64_count(),
value_.get());
util::filter_highbits_uint(value_.get(), uint64_count(), result_bits);
return *this;
}
/**
Subtracts a BigUInt and an unsigned integer saving the difference to
the first operand, returning a reference of the first operand. The second
input operand is not modified. The first operand is resized if and only
if its bit count is smaller than the significant bit count of the second
operand.
@param[in] operand2 The second operand to subtract
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator-=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator-=(operand2uint);
}
/**
Multiplies two BigUInts saving the product to the first operand,
returning a reference of the first operand. The second input operand
is not modified. The first operand is resized if and only if its bit
count is smaller than the sum of the significant bit counts of the two
input operands.
@param[in] operand2 The second operand to multiply
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator*=(const BigUInt &operand2)
{
*this = *this * operand2;
return *this;
}
/**
Multiplies a BigUInt and an unsigned integer saving the product to
the first operand, returning a reference of the first operand. The
second input operand is not modified. The first operand is resized if
and only if its bit count is smaller than the sum of the significant
bit counts of the two input operands.
@param[in] operand2 The second operand to multiply
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator*=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator*=(operand2uint);
}
/**
Divides two BigUInts saving the quotient to the first operand,
returning a reference of the first operand. The second input operand
is not modified. The first operand is never resized.
@param[in] operand2 The second operand to divide
@throws std::invalid_argument if operand2 is zero
*/
inline BigUInt &operator/=(const BigUInt &operand2)
{
*this = *this / operand2;
return *this;
}
/**
Divides a BigUInt and an unsigned integer saving the quotient to
the first operand, returning a reference of the first operand. The
second input operand is not modified. The first operand is never resized.
@param[in] operand2 The second operand to divide
@throws std::invalid_argument if operand2 is zero
*/
inline BigUInt &operator/=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator/=(operand2uint);
}
/**
Performs a bit-wise XOR operation between two BigUInts saving the result
to the first operand, returning a reference of the first operand. The
second input operand is not modified. The first operand is resized if
and only if its bit count is smaller than the significant bit count of
the second operand.
@param[in] operand2 The second operand to XOR
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator^=(const BigUInt &operand2)
{
int result_bits = std::max(bit_count_, operand2.bit_count());
if (bit_count_ != result_bits)
{
resize(result_bits);
}
util::xor_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get());
return *this;
}
/**
Performs a bit-wise XOR operation between a BigUInt and an unsigned integer
saving the result to the first operand, returning a reference of the first
operand. The second input operand is not modified. The first operand is
resized if and only if its bit count is smaller than the significant bit
count of the second operand.
@param[in] operand2 The second operand to XOR
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator^=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator^=(operand2uint);
}
/**
Performs a bit-wise AND operation between two BigUInts saving the result
to the first operand, returning a reference of the first operand. The
second input operand is not modified. The first operand is resized if
and only if its bit count is smaller than the significant bit count of
the second operand.
@param[in] operand2 The second operand to AND
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator&=(const BigUInt &operand2)
{
int result_bits = std::max(bit_count_, operand2.bit_count());
if (bit_count_ != result_bits)
{
resize(result_bits);
}
util::and_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get());
return *this;
}
/**
Performs a bit-wise AND operation between a BigUInt and an unsigned integer
saving the result to the first operand, returning a reference of the first
operand. The second input operand is not modified. The first operand is
resized if and only if its bit count is smaller than the significant bit
count of the second operand.
@param[in] operand2 The second operand to AND
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator&=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator&=(operand2uint);
}
/**
Performs a bit-wise OR operation between two BigUInts saving the result to
the first operand, returning a reference of the first operand. The second
input operand is not modified. The first operand is resized if and only if
its bit count is smaller than the significant bit count of the second
operand.
@param[in] operand2 The second operand to OR
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator|=(const BigUInt &operand2)
{
int result_bits = std::max(bit_count_, operand2.bit_count());
if (bit_count_ != result_bits)
{
resize(result_bits);
}
util::or_uint_uint(value_.get(), operand2.data(), operand2.uint64_count(), value_.get());
return *this;
}
/**
Performs a bit-wise OR operation between a BigUInt and an unsigned integer
saving the result to the first operand, returning a reference of the first
operand. The second input operand is not modified. The first operand is
resized if and only if its bit count is smaller than the significant bit
count of the second operand.
@param[in] operand2 The second operand to OR
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator|=(std::uint64_t operand2)
{
BigUInt operand2uint;
operand2uint = operand2;
return operator|=(operand2uint);
}
/**
Left-shifts a BigUInt by the specified amount. The BigUInt is resized if
and only if its bit count is smaller than the sum of its significant bit
count and the shift amount.
@param[in] shift The number of bits to shift by
@throws std::invalid_argument if shift is negative
@throws std::logic_error if the BigUInt is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
inline BigUInt &operator<<=(int shift)
{
if (shift < 0)
{
throw std::invalid_argument("shift must be non-negative");
}
int result_bits = util::add_safe(significant_bit_count(), shift);
if (bit_count_ < result_bits)
{
resize(result_bits);
}
util::left_shift_uint(value_.get(), shift, uint64_count(), value_.get());
return *this;
}
/**
Right-shifts a BigUInt by the specified amount. The BigUInt is never
resized.
@param[in] shift The number of bits to shift by
@throws std::invalid_argument if shift is negative
*/
inline BigUInt &operator>>=(int shift)
{
if (shift < 0)
{
throw std::invalid_argument("shift must be non-negative");
}
if (shift > bit_count_)
{
set_zero();
return *this;
}
util::right_shift_uint(value_.get(), shift, uint64_count(), value_.get());
return *this;
}
/**
Divides two BigUInts and returns the quotient and sets the remainder
parameter to the remainder. The bit count of the quotient is set to be
the significant bit count of the BigUInt. The remainder is resized if
and only if it is smaller than the bit count of the BigUInt.
@param[in] operand2 The second operand to divide
@param[out] remainder The BigUInt to store the remainder
@throws std::invalid_argument if operand2 is zero
@throws std::logic_error if the remainder is an alias and the operator
attempts to enlarge the BigUInt to fit the result
*/
BigUInt divrem(const BigUInt &operand2, BigUInt &remainder) const;
/**
Divides a BigUInt and an unsigned integer and returns the quotient and
sets the remainder parameter to the remainder. The bit count of the
quotient is set to be the significant bit count of the BigUInt. The
remainder is resized if and only if it is smaller than the bit count
of the BigUInt.
@param[in] operand2 The second operand to divide
@param[out] remainder The BigUInt to store the remainder
@throws std::invalid_argument if operand2 is zero
@throws std::logic_error if the remainder is an alias which the
function attempts to enlarge to fit the result
*/
inline BigUInt divrem(std::uint64_t operand2, BigUInt &remainder) const
{
BigUInt operand2uint;
operand2uint = operand2;
return divrem(operand2uint, remainder);
}
/**
Returns the inverse of a BigUInt with respect to the specified modulus.
The original BigUInt is not modified. The bit count of the inverse is
set to be the significant bit count of the modulus.
@param[in] modulus The modulus to calculate the inverse with respect to
@throws std::invalid_argument if modulus is zero
@throws std::invalid_argument if modulus is not greater than the BigUInt value
@throws std::invalid_argument if the BigUInt value and modulus are not co-prime
@throws std::logic_error if the BigUInt value is zero
*/
SEAL_NODISCARD inline BigUInt modinv(const BigUInt &modulus) const
{
if (modulus.is_zero())
{
throw std::invalid_argument("modulus must be positive");
}
if (is_zero())
{
throw std::logic_error("BigUInt value cannot be zero");
}
int result_bits = modulus.significant_bit_count();
if (*this >= modulus)
{
throw std::invalid_argument("modulus must be greater than BigUInt");
}
BigUInt result(result_bits);
result = *this;
if (!util::try_invert_uint_mod(result.data(), modulus.data(), result.uint64_count(), result.data(), pool_))
{
throw std::invalid_argument("BigUInt and modulus are not co-prime");
}
return result;
}
/**
Returns the inverse of a BigUInt with respect to the specified modulus.
The original BigUInt is not modified. The bit count of the inverse is set
to be the significant bit count of the modulus.
@param[in] modulus The modulus to calculate the inverse with respect to
@throws std::invalid_argument if modulus is zero
@throws std::invalid_argument if modulus is not greater than the BigUInt value
@throws std::invalid_argument if the BigUInt value and modulus are not co-prime
@throws std::logic_error if the BigUInt value is zero
*/
SEAL_NODISCARD inline BigUInt modinv(std::uint64_t modulus) const
{
BigUInt modulusuint;
modulusuint = modulus;
return modinv(modulusuint);
}
/**
Attempts to calculate the inverse of a BigUInt with respect to the
specified modulus, returning whether or not the inverse was successful
and setting the inverse parameter to the inverse. The original BigUInt
is not modified. The inverse parameter is resized if and only if its bit
count is smaller than the significant bit count of the modulus.
@param[in] modulus The modulus to calculate the inverse with respect to
@param[out] inverse Stores the inverse if the inverse operation was
successful
@throws std::invalid_argument if modulus is zero
@throws std::invalid_argument if modulus is not greater than the BigUInt
value
@throws std::logic_error if the inverse is an alias which the function
attempts to enlarge to fit the result
*/
inline bool trymodinv(const BigUInt &modulus, BigUInt &inverse) const
{
if (modulus.is_zero())
{
throw std::invalid_argument("modulus must be positive");
}
if (is_zero())
{
return false;
}
int result_bits = modulus.significant_bit_count();
if (*this >= modulus)
{
throw std::invalid_argument("modulus must be greater than BigUInt");
}
if (inverse.bit_count() < result_bits)
{
inverse.resize(result_bits);
}
inverse = *this;
return util::try_invert_uint_mod(
inverse.data(), modulus.data(), inverse.uint64_count(), inverse.data(), pool_);
}
/**
Attempts to calculate the inverse of a BigUInt with respect to the
specified modulus, returning whether or not the inverse was successful
and setting the inverse parameter to the inverse. The original BigUInt
is not modified. The inverse parameter is resized if and only if its
bit count is smaller than the significant bit count of the modulus.
@param[in] modulus The modulus to calculate the inverse with respect to
@param[out] inverse Stores the inverse if the inverse operation was
successful
@throws std::invalid_argument if modulus is zero
@throws std::invalid_argument if modulus is not greater than the BigUInt
value
@throws std::logic_error if the inverse is an alias which the function
attempts to enlarge to fit the result
*/
inline bool trymodinv(std::uint64_t modulus, BigUInt &inverse) const
{
BigUInt modulusuint;
modulusuint = modulus;
return trymodinv(modulusuint, inverse);
}
/**
Returns an upper bound on the size of the BigUInt, as if it was written
to an output stream.
@param[in] compr_mode The compression mode
@throws std::invalid_argument if the compression mode is not supported
@throws std::logic_error if the size does not fit in the return type
*/
SEAL_NODISCARD inline std::streamoff save_size(
compr_mode_type compr_mode = Serialization::compr_mode_default) const
{
std::size_t members_size = Serialization::ComprSizeEstimate(
util::add_safe(
util::mul_safe(uint64_count(), sizeof(std::uint64_t)), // value_
sizeof(std::int32_t)), // bit_count_
compr_mode);
return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size));
}
/**
Saves the BigUInt to an output stream. The full state of the BigUInt is
serialized, including insignificant bits. The output is in binary format
and not human-readable. The output stream must have the "binary" flag set.
@param[out] stream The stream to save the BigUInt to
@param[in] compr_mode The desired compression mode
@throws std::invalid_argument if the compression mode is not supported
@throws std::logic_error if the data to be saved is invalid, or if
compression failed
@throws std::runtime_error if I/O operations failed
*/
inline std::streamoff save(
std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const
{
using namespace std::placeholders;
return Serialization::Save(
std::bind(&BigUInt::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode);
}
/**
Loads a BigUInt from an input stream overwriting the current BigUInt.
@param[in] stream The stream to load the BigUInt from
@throws std::logic_error if the data cannot be loaded by this version of
Microsoft SEAL, if the loaded data is invalid, if decompression failed,
or if the loaded BigUInt is too large for an aliased BigUInt
@throws std::runtime_error if I/O operations failed
*/
inline std::streamoff load(std::istream &stream)
{
using namespace std::placeholders;
return Serialization::Load(std::bind(&BigUInt::load_members, this, _1), stream);
}
/**
Saves the BigUInt to a given memory location. The full state of the
BigUInt is serialized, including insignificant bits. The output is in
binary format and not human-readable.
@param[out] out The memory location to write the BigUInt to
@param[in] size The number of bytes available in the given memory location
@param[in] compr_mode The desired compression mode
@throws std::invalid_argument if out is null or if size is too small to
contain a SEALHeader, or if the compression mode is not supported
@throws std::logic_error if the data to be saved is invalid, or if
compression failed
@throws std::runtime_error if I/O operations failed
*/
inline std::streamoff save(
SEAL_BYTE *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const
{
using namespace std::placeholders;
return Serialization::Save(
std::bind(&BigUInt::save_members, this, _1), save_size(compr_mode_type::none), out, size, compr_mode);
}
/**
Loads a BigUInt from a memory location overwriting the current BigUInt.
@param[in] in The memory location to load the BigUInt from
@param[in] size The number of bytes available in the given memory location
@throws std::invalid_argument if in is null or if size is too small to
contain a SEALHeader
@throws std::logic_error if the data cannot be loaded by this version of
Microsoft SEAL, if the loaded data is invalid, if decompression failed,
or if the loaded BigUInt is too large for an aliased BigUInt
@throws std::runtime_error if I/O operations failed
*/
inline std::streamoff load(const SEAL_BYTE *in, std::size_t size)
{
using namespace std::placeholders;
return Serialization::Load(std::bind(&BigUInt::load_members, this, _1), in, size);
}
/**
Creates a minimally sized BigUInt initialized to the specified unsigned
integer value.
@param[in] value The value to initialized the BigUInt to
*/
SEAL_NODISCARD inline static BigUInt of(std::uint64_t value)
{
BigUInt result;
result = value;
return result;
}
/**
Duplicates the current BigUInt. The bit count and the value of the
given BigUInt are set to be exactly the same as in the current one.
@param[out] destination The BigUInt to overwrite with the duplicate
@throws std::logic_error if the destination BigUInt is an alias
*/
inline void duplicate_to(BigUInt &destination) const
{
destination.resize(this->bit_count_);
destination = *this;
}
/**
Duplicates a given BigUInt. The bit count and the value of the current
BigUInt are set to be exactly the same as in the given one.
@param[in] value The BigUInt to duplicate
@throws std::logic_error if the current BigUInt is an alias
*/
inline void duplicate_from(const BigUInt &value)
{
this->resize(value.bit_count_);
*this = value;
}
private:
MemoryPoolHandle pool_;
/**
Resets the entire state of the BigUInt to an empty, zero-sized state,
freeing any memory it internally allocated. If the BigUInt was an alias,
the backing array is not freed but the alias is no longer referenced.
*/
inline void reset() noexcept
{
value_.release();
bit_count_ = 0;
}
void save_members(std::ostream &stream) const;
void load_members(std::istream &stream);
/**
Points to the backing array for the BigUInt. This pointer will be set
to nullptr if and only if the bit count is zero. This pointer is
automatically allocated and freed by the BigUInt if and only if
the BigUInt is not an alias. If the BigUInt is an alias, then the
pointer was passed-in to a constructor or alias() call, and will not be
deallocated by the BigUInt.
*/
util::Pointer<std::uint64_t> value_;
/**
The bit count for the BigUInt.
*/
int bit_count_ = 0;
};
} // namespace seal
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT license.
# Source files in this directory
target_sources(sealc PRIVATE
${CMAKE_CURRENT_LIST_DIR}/batchencoder.cpp
${CMAKE_CURRENT_LIST_DIR}/biguint.cpp
${CMAKE_CURRENT_LIST_DIR}/ciphertext.cpp
${CMAKE_CURRENT_LIST_DIR}/ckksencoder.cpp
${CMAKE_CURRENT_LIST_DIR}/contextdata.cpp
${CMAKE_CURRENT_LIST_DIR}/decryptor.cpp
# ${CMAKE_CURRENT_LIST_DIR}/dllmain.cpp
${CMAKE_CURRENT_LIST_DIR}/encryptionparameterqualifiers.cpp
${CMAKE_CURRENT_LIST_DIR}/encryptionparameters.cpp
${CMAKE_CURRENT_LIST_DIR}/encryptor.cpp
${CMAKE_CURRENT_LIST_DIR}/evaluator.cpp
${CMAKE_CURRENT_LIST_DIR}/galoiskeys.cpp
${CMAKE_CURRENT_LIST_DIR}/intencoder.cpp
${CMAKE_CURRENT_LIST_DIR}/keygenerator.cpp
${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.cpp
${CMAKE_CURRENT_LIST_DIR}/memorymanager.cpp
${CMAKE_CURRENT_LIST_DIR}/memorypoolhandle.cpp
${CMAKE_CURRENT_LIST_DIR}/modulus.cpp
${CMAKE_CURRENT_LIST_DIR}/plaintext.cpp
${CMAKE_CURRENT_LIST_DIR}/publickey.cpp
${CMAKE_CURRENT_LIST_DIR}/relinkeys.cpp
${CMAKE_CURRENT_LIST_DIR}/sealcontext.cpp
${CMAKE_CURRENT_LIST_DIR}/secretkey.cpp
${CMAKE_CURRENT_LIST_DIR}/serialization.cpp
${CMAKE_CURRENT_LIST_DIR}/utilities.cpp
${CMAKE_CURRENT_LIST_DIR}/valcheck.cpp
${CMAKE_CURRENT_LIST_DIR}/version.cpp
)
# Add header files for installation
install(
FILES
${CMAKE_CURRENT_LIST_DIR}/batchencoder.h
${CMAKE_CURRENT_LIST_DIR}/biguint.h
${CMAKE_CURRENT_LIST_DIR}/ciphertext.h
${CMAKE_CURRENT_LIST_DIR}/ckksencoder.h
${CMAKE_CURRENT_LIST_DIR}/contextdata.h
${CMAKE_CURRENT_LIST_DIR}/decryptor.h
${CMAKE_CURRENT_LIST_DIR}/defines.h
${CMAKE_CURRENT_LIST_DIR}/encryptionparameterqualifiers.h
${CMAKE_CURRENT_LIST_DIR}/encryptionparameters.h
${CMAKE_CURRENT_LIST_DIR}/encryptor.h
${CMAKE_CURRENT_LIST_DIR}/evaluator.h
${CMAKE_CURRENT_LIST_DIR}/galoiskeys.h
${CMAKE_CURRENT_LIST_DIR}/intencoder.h
${CMAKE_CURRENT_LIST_DIR}/keygenerator.h
${CMAKE_CURRENT_LIST_DIR}/kswitchkeys.h
${CMAKE_CURRENT_LIST_DIR}/memorymanager.h
${CMAKE_CURRENT_LIST_DIR}/memorypoolhandle.h
${CMAKE_CURRENT_LIST_DIR}/modulus.h
${CMAKE_CURRENT_LIST_DIR}/plaintext.h
${CMAKE_CURRENT_LIST_DIR}/publickey.h
${CMAKE_CURRENT_LIST_DIR}/relinkeys.h
${CMAKE_CURRENT_LIST_DIR}/sealcontext.h
${CMAKE_CURRENT_LIST_DIR}/secretkey.h
${CMAKE_CURRENT_LIST_DIR}/serialization.h
${CMAKE_CURRENT_LIST_DIR}/stdafx.h
${CMAKE_CURRENT_LIST_DIR}/targetver.h
${CMAKE_CURRENT_LIST_DIR}/utilities.h
${CMAKE_CURRENT_LIST_DIR}/valcheck.h
${CMAKE_CURRENT_LIST_DIR}/version.h
DESTINATION
${SEAL_INCLUDES_INSTALL_DIR}/seal/c
)
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// STD
#include <vector>
// SEALNet
#include "seal/c/batchencoder.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/batchencoder.h"
using namespace std;
using namespace seal;
using namespace seal::c;
SEAL_C_FUNC BatchEncoder_Create(void *context, void **batch_encoder)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx, E_POINTER);
IfNullRet(batch_encoder, E_POINTER);
try
{
BatchEncoder *encoder = new BatchEncoder(sharedctx);
*batch_encoder = encoder;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BatchEncoder_Destroy(void *thisptr)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
delete encoder;
return S_OK;
}
SEAL_C_FUNC BatchEncoder_Encode1(void *thisptr, uint64_t count, uint64_t *values, void *destination)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(values, E_POINTER);
Plaintext *plain = FromVoid<Plaintext>(destination);
IfNullRet(plain, E_POINTER);
vector<uint64_t> valvec(count);
for (uint64_t i = 0; i < count; i++)
{
valvec[i] = values[i];
}
try
{
encoder->encode(valvec, *plain);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BatchEncoder_Encode2(void *thisptr, uint64_t count, int64_t *values, void *destination)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(values, E_POINTER);
Plaintext *plain = FromVoid<Plaintext>(destination);
IfNullRet(plain, E_POINTER);
vector<int64_t> valvec(count);
for (uint64_t i = 0; i < count; i++)
{
valvec[i] = values[i];
}
try
{
encoder->encode(valvec, *plain);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BatchEncoder_Encode3(void *thisptr, void *plain, void *pool)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
try
{
encoder->encode(*plainptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BatchEncoder_Decode1(void *thisptr, void *plain, uint64_t *count, uint64_t *destination, void *pool)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(count, E_POINTER);
IfNullRet(destination, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
vector<uint64_t> result;
try
{
encoder->decode(*plainptr, result, *handle);
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
// Copy to actual destination
*count = result.size();
for (uint64_t i = 0; i < *count; i++)
{
destination[i] = result[i];
}
return S_OK;
}
SEAL_C_FUNC BatchEncoder_Decode2(void *thisptr, void *plain, uint64_t *count, int64_t *destination, void *pool)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(count, E_POINTER);
IfNullRet(destination, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
vector<int64_t> result;
try
{
encoder->decode(*plainptr, result, *handle);
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
*count = result.size();
// Copy to actual destination
for (uint64_t i = 0; i < *count; i++)
{
destination[i] = result[i];
}
return S_OK;
}
SEAL_C_FUNC BatchEncoder_Decode3(void *thisptr, void *plain, void *pool)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
try
{
encoder->decode(*plainptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BatchEncoder_GetSlotCount(void *thisptr, uint64_t *slot_count)
{
BatchEncoder *encoder = FromVoid<BatchEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(slot_count, E_POINTER);
*slot_count = encoder->slot_count();
return S_OK;
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC BatchEncoder_Create(void *context, void **batch_encoder);
SEAL_C_FUNC BatchEncoder_Destroy(void *thisptr);
SEAL_C_FUNC BatchEncoder_Encode1(void *thisptr, uint64_t count, uint64_t *values, void *destination);
SEAL_C_FUNC BatchEncoder_Encode2(void *thisptr, uint64_t count, int64_t *values, void *destination);
SEAL_C_FUNC BatchEncoder_Encode3(void *thisptr, void *plain, void *pool);
SEAL_C_FUNC BatchEncoder_Decode1(void *thisptr, void *plain, uint64_t *count, uint64_t *destination, void *pool);
SEAL_C_FUNC BatchEncoder_Decode2(void *thisptr, void *plain, uint64_t *count, int64_t *destination, void *pool);
SEAL_C_FUNC BatchEncoder_Decode3(void *thisptr, void *plain, void *pool);
SEAL_C_FUNC BatchEncoder_GetSlotCount(void *thisptr, uint64_t *slot_count);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// STD
#include <string>
// SEALNet
#include "seal/c/biguint.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/biguint.h"
using namespace std;
using namespace seal;
using namespace seal::c;
SEAL_C_FUNC BigUInt_Create1(void **bui)
{
IfNullRet(bui, E_POINTER);
BigUInt *biguint = new BigUInt();
*bui = biguint;
return S_OK;
}
SEAL_C_FUNC BigUInt_Create2(int bitCount, void **bui)
{
IfNullRet(bui, E_POINTER);
try
{
BigUInt *biguint = new BigUInt(bitCount, /* value */ static_cast<uint64_t>(0));
*bui = biguint;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_Create3(int bitCount, char *hex_string, void **bui)
{
IfNullRet(hex_string, E_POINTER);
IfNullRet(bui, E_POINTER);
string hexstring(hex_string);
BigUInt *biguint = nullptr;
try
{
biguint = new BigUInt(bitCount, hexstring);
*bui = biguint;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_Create4(int bitCount, uint64_t value, void **bui)
{
IfNullRet(bui, E_POINTER);
try
{
BigUInt *biguint = new BigUInt(bitCount, value);
*bui = biguint;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_Create5(char *hex_string, void **bui)
{
IfNullRet(hex_string, E_POINTER);
IfNullRet(bui, E_POINTER);
string hexstring(hex_string);
BigUInt *biguint = nullptr;
try
{
biguint = new BigUInt(hexstring);
*bui = biguint;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_Create6(void *copy, void **bui)
{
BigUInt *other = FromVoid<BigUInt>(copy);
IfNullRet(other, E_POINTER);
IfNullRet(bui, E_POINTER);
BigUInt *biguint = new BigUInt(*other);
*bui = biguint;
return S_OK;
}
SEAL_C_FUNC BigUInt_Destroy(void *thisptr)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(thisptr, E_POINTER);
delete biguint;
return S_OK;
}
SEAL_C_FUNC BigUInt_IsAlias(void *thisptr, bool *is_alias)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(is_alias, E_POINTER);
*is_alias = biguint->is_alias();
return S_OK;
}
SEAL_C_FUNC BigUInt_BitCount(void *thisptr, int *bit_count)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(bit_count, E_POINTER);
*bit_count = biguint->bit_count();
return S_OK;
}
SEAL_C_FUNC BigUInt_ByteCount(void *thisptr, uint64_t *byte_count)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(byte_count, E_POINTER);
*byte_count = biguint->byte_count();
return S_OK;
}
SEAL_C_FUNC BigUInt_UInt64Count(void *thisptr, uint64_t *uint64_count)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(uint64_count, E_POINTER);
*uint64_count = biguint->uint64_count();
return S_OK;
}
SEAL_C_FUNC BigUInt_IsZero(void *thisptr, bool *is_zero)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(is_zero, E_POINTER);
*is_zero = biguint->is_zero();
return S_OK;
}
SEAL_C_FUNC BigUInt_Get(void *thisptr, uint64_t index, uint8_t *value)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(value, E_POINTER)
if (index >= biguint->byte_count())
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
auto result = (*biguint)[index];
*value = static_cast<uint8_t>(result);
return S_OK;
}
SEAL_C_FUNC BigUInt_GetU64(void *thisptr, uint64_t index, uint64_t *value)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(value, E_POINTER);
if (index >= biguint->uint64_count())
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
*value = biguint->data()[index];
return S_OK;
}
SEAL_C_FUNC BigUInt_Set1(void *thisptr, uint64_t index, uint8_t value)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
if (index >= biguint->byte_count())
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
(*biguint)[index] = static_cast<SEAL_BYTE>(value);
return S_OK;
}
SEAL_C_FUNC BigUInt_GetSignificantBitCount(void *thisptr, int *significant_bit_count)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(significant_bit_count, E_POINTER);
*significant_bit_count = biguint->significant_bit_count();
return S_OK;
}
SEAL_C_FUNC BigUInt_Set2(void *thisptr, void *assign)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *other = FromVoid<BigUInt>(assign);
IfNullRet(other, E_POINTER);
*biguint = *other;
return S_OK;
}
SEAL_C_FUNC BigUInt_Set3(void *thisptr, uint64_t value)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
try
{
*biguint = value;
return S_OK;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC BigUInt_Set4(void *thisptr, char *assign)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(assign, E_POINTER);
string assign_str(assign);
try
{
*biguint = assign_str;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC BigUInt_SetZero(void *thisptr)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
biguint->set_zero();
return S_OK;
}
SEAL_C_FUNC BigUInt_Resize(void *thisptr, int bitCount)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
biguint->resize(bitCount);
return S_OK;
}
SEAL_C_FUNC BigUInt_Equals(void *thisptr, void *compare, bool *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *other = FromVoid<BigUInt>(compare);
IfNullRet(other, E_POINTER);
IfNullRet(result, E_POINTER);
*result = (*biguint) == (*other);
return S_OK;
}
SEAL_C_FUNC BigUInt_CompareTo1(void *thisptr, void *compare, int *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *other = FromVoid<BigUInt>(compare);
IfNullRet(other, E_POINTER);
IfNullRet(result, E_POINTER);
*result = biguint->compareto(*other);
return S_OK;
}
SEAL_C_FUNC BigUInt_CompareTo2(void *thisptr, uint64_t compare, int *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
*result = biguint->compareto(compare);
return S_OK;
}
SEAL_C_FUNC BigUInt_DivideRemainder1(void *thisptr, void *operand2, void *remainder, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operand2bui = FromVoid<BigUInt>(operand2);
IfNullRet(operand2bui, E_POINTER);
BigUInt *remainderbui = FromVoid<BigUInt>(remainder);
IfNullRet(remainderbui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(biguint->divrem(*operand2bui, *remainderbui));
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_DivideRemainder2(void *thisptr, uint64_t operand2, void *remainder, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *remainderbui = FromVoid<BigUInt>(remainder);
IfNullRet(remainderbui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(biguint->divrem(operand2, *remainderbui));
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_ToString(void *thisptr, char *outstr, uint64_t *length)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(length, E_POINTER);
return ToStringHelper(biguint->to_string(), outstr, length);
}
SEAL_C_FUNC BigUInt_ToDecimalString(void *thisptr, char *outstr, uint64_t *length)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(length, E_POINTER);
return ToStringHelper(biguint->to_dec_string(), outstr, length);
}
SEAL_C_FUNC BigUInt_DuplicateTo(void *thisptr, void *destination)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *destbui = FromVoid<BigUInt>(destination);
IfNullRet(destbui, E_POINTER);
biguint->duplicate_to(*destbui);
return S_OK;
}
SEAL_C_FUNC BigUInt_DuplicateFrom(void *thisptr, void *value)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *valuebui = FromVoid<BigUInt>(value);
IfNullRet(valuebui, E_POINTER);
biguint->duplicate_from(*valuebui);
return S_OK;
}
SEAL_C_FUNC BigUInt_ModuloInvert1(void *thisptr, void *modulus, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *modulusui = FromVoid<BigUInt>(modulus);
IfNullRet(modulusui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = nullptr;
try
{
resultbui = new BigUInt(biguint->modinv(*modulusui));
*result = resultbui;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC BigUInt_ModuloInvert2(void *thisptr, uint64_t modulus, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *resultbui = nullptr;
try
{
resultbui = new BigUInt(biguint->modinv(modulus));
*result = resultbui;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC BigUInt_TryModuloInvert1(void *thisptr, void *modulus, void *inverse, bool *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *modulusui = FromVoid<BigUInt>(modulus);
IfNullRet(modulusui, E_POINTER);
BigUInt *inverseui = FromVoid<BigUInt>(inverse);
IfNullRet(inverseui, E_POINTER);
IfNullRet(result, E_POINTER);
try
{
*result = biguint->trymodinv(*modulusui, *inverseui);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_TryModuloInvert2(void *thisptr, uint64_t modulus, void *inverse, bool *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *inverseui = FromVoid<BigUInt>(inverse);
IfNullRet(inverseui, E_POINTER);
IfNullRet(result, E_POINTER);
try
{
*result = biguint->trymodinv(modulus, *inverseui);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC BigUInt_OperatorNeg(void *thisptr, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(biguint->operator-());
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorTilde(void *thisptr, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(biguint->operator~());
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorPlus1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint + *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorPlus2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint + operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorMinus1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint - *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorMinus2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint - operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorMult1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint * *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorMult2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint * operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorDiv1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint / *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorDiv2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint / operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorXor1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint ^ *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorXor2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint ^ operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorAnd1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint & *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorAnd2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint & operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorOr1(void *thisptr, void *operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
BigUInt *operandui = FromVoid<BigUInt>(operand);
IfNullRet(operandui, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint | *operandui);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorOr2(void *thisptr, uint64_t operand, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint | operand);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorShiftLeft(void *thisptr, int shift, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint << shift);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_OperatorShiftRight(void *thisptr, int shift, void **result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
BigUInt *resultbui = new BigUInt(*biguint >> shift);
*result = resultbui;
return S_OK;
}
SEAL_C_FUNC BigUInt_ToDouble(void *thisptr, double *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
*result = biguint->to_double();
return S_OK;
}
SEAL_C_FUNC BigUInt_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(result, E_POINTER);
try
{
*result = static_cast<int64_t>(biguint->save_size(static_cast<compr_mode_type>(compr_mode)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC BigUInt_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(outptr, E_POINTER);
IfNullRet(out_bytes, E_POINTER);
try
{
*out_bytes = util::safe_cast<int64_t>(biguint->save(
reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size),
static_cast<compr_mode_type>(compr_mode)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
catch (const runtime_error &)
{
return COR_E_IO;
}
}
SEAL_C_FUNC BigUInt_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes)
{
BigUInt *biguint = FromVoid<BigUInt>(thisptr);
IfNullRet(biguint, E_POINTER);
IfNullRet(inptr, E_POINTER);
IfNullRet(in_bytes, E_POINTER);
try
{
*in_bytes = util::safe_cast<int64_t>(
biguint->load(reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
catch (const runtime_error &)
{
return COR_E_IO;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC BigUInt_Create1(void **bui);
SEAL_C_FUNC BigUInt_Create2(int bitCount, void **bui);
SEAL_C_FUNC BigUInt_Create3(int bitCount, char *hex_string, void **bui);
SEAL_C_FUNC BigUInt_Create4(int bitCount, uint64_t value, void **bui);
SEAL_C_FUNC BigUInt_Create5(char *hex_string, void **bui);
SEAL_C_FUNC BigUInt_Create6(void *copy, void **bui);
SEAL_C_FUNC BigUInt_Destroy(void *thispt);
SEAL_C_FUNC BigUInt_IsAlias(void *thisptr, bool *is_alias);
SEAL_C_FUNC BigUInt_BitCount(void *thisptr, int *bit_count);
SEAL_C_FUNC BigUInt_ByteCount(void *thisptr, uint64_t *byte_count);
SEAL_C_FUNC BigUInt_UInt64Count(void *thisptr, uint64_t *uint64_count);
SEAL_C_FUNC BigUInt_IsZero(void *thisptr, bool *is_zero);
SEAL_C_FUNC BigUInt_Get(void *thisptr, uint64_t index, uint8_t *value);
SEAL_C_FUNC BigUInt_GetU64(void *thisptr, uint64_t index, uint64_t *value);
SEAL_C_FUNC BigUInt_Set1(void *thisptr, uint64_t index, uint8_t value);
SEAL_C_FUNC BigUInt_GetSignificantBitCount(void *thisptr, int *significant_bit_count);
SEAL_C_FUNC BigUInt_Set2(void *thisptr, void *assign);
SEAL_C_FUNC BigUInt_Set3(void *thisptr, uint64_t value);
SEAL_C_FUNC BigUInt_Set4(void *thisptr, char *assign);
SEAL_C_FUNC BigUInt_SetZero(void *thispt);
SEAL_C_FUNC BigUInt_Resize(void *thisptr, int bitCount);
SEAL_C_FUNC BigUInt_Equals(void *thisptr, void *compare, bool *result);
SEAL_C_FUNC BigUInt_CompareTo1(void *thisptr, void *compare, int *result);
SEAL_C_FUNC BigUInt_CompareTo2(void *thisptr, uint64_t compare, int *result);
SEAL_C_FUNC BigUInt_DivideRemainder1(void *thisptr, void *operand2, void *remainder, void **result);
SEAL_C_FUNC BigUInt_DivideRemainder2(void *thisptr, uint64_t operand2, void *remainder, void **result);
SEAL_C_FUNC BigUInt_ToString(void *thisptr, char *outstr, uint64_t *length);
SEAL_C_FUNC BigUInt_ToDecimalString(void *thisptr, char *outstr, uint64_t *length);
SEAL_C_FUNC BigUInt_DuplicateTo(void *thisptr, void *destination);
SEAL_C_FUNC BigUInt_DuplicateFrom(void *thisptr, void *value);
SEAL_C_FUNC BigUInt_ModuloInvert1(void *thisptr, void *modulus, void **result);
SEAL_C_FUNC BigUInt_ModuloInvert2(void *thisptr, uint64_t modulus, void **result);
SEAL_C_FUNC BigUInt_TryModuloInvert1(void *thisptr, void *modulus, void *inverse, bool *result);
SEAL_C_FUNC BigUInt_TryModuloInvert2(void *thisptr, uint64_t modulus, void *inverse, bool *result);
SEAL_C_FUNC BigUInt_OperatorNeg(void *thisptr, void **result);
SEAL_C_FUNC BigUInt_OperatorTilde(void *thisptr, void **result);
SEAL_C_FUNC BigUInt_OperatorPlus1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorPlus2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorMinus1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorMinus2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorMult1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorMult2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorDiv1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorDiv2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorXor1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorXor2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorAnd1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorAnd2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorOr1(void *thisptr, void *operand, void **result);
SEAL_C_FUNC BigUInt_OperatorOr2(void *thisptr, uint64_t operand, void **result);
SEAL_C_FUNC BigUInt_OperatorShiftLeft(void *thisptr, int shift, void **result);
SEAL_C_FUNC BigUInt_OperatorShiftRight(void *thisptr, int shift, void **result);
SEAL_C_FUNC BigUInt_ToDouble(void *thisptr, double *result);
SEAL_C_FUNC BigUInt_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result);
SEAL_C_FUNC BigUInt_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes);
SEAL_C_FUNC BigUInt_Load(void *thisptr, uint8_t *inptr, uint64_t size, int64_t *in_bytes);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// SEALNet
#include "seal/c/ciphertext.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/ciphertext.h"
using namespace std;
using namespace seal;
using namespace seal::c;
namespace seal
{
/**
Enables access to private members of seal::Ciphertext.
*/
struct Ciphertext::CiphertextPrivateHelper
{
static void resize(Ciphertext *ciphertext, size_t size, size_t poly_modulus_degree, size_t coeff_modulus_size)
{
ciphertext->resize_internal(size, poly_modulus_degree, coeff_modulus_size);
}
static void set_ntt_form(Ciphertext *ciphertext, bool is_ntt_form)
{
ciphertext->is_ntt_form_ = is_ntt_form;
}
};
} // namespace seal
SEAL_C_FUNC Ciphertext_Create1(void *memoryPoolHandle, void **ciphertext)
{
IfNullRet(ciphertext, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(memoryPoolHandle);
try
{
Ciphertext *cipher = new Ciphertext(*handle);
*ciphertext = cipher;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Create2(void *copy, void **ciphertext)
{
Ciphertext *copyptr = FromVoid<Ciphertext>(copy);
IfNullRet(copyptr, E_POINTER);
IfNullRet(ciphertext, E_POINTER);
Ciphertext *cipher = new Ciphertext(*copyptr);
*ciphertext = cipher;
return S_OK;
}
SEAL_C_FUNC Ciphertext_Create3(void *context, void *pool, void **ciphertext)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(ciphertext, E_POINTER);
unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool);
try
{
Ciphertext *cipher = new Ciphertext(sharedctx, *pool_ptr);
*ciphertext = cipher;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Create4(void *context, uint64_t *parms_id, void *pool, void **ciphertext)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(parms_id, E_POINTER);
IfNullRet(ciphertext, E_POINTER);
unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool);
try
{
parms_id_type parmsid;
CopyParmsId(parms_id, parmsid);
Ciphertext *cipher = new Ciphertext(sharedctx, parmsid, *pool_ptr);
*ciphertext = cipher;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Create5(void *context, uint64_t *parms_id, uint64_t capacity, void *pool, void **ciphertext)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(parms_id, E_POINTER);
IfNullRet(ciphertext, E_POINTER);
unique_ptr<MemoryPoolHandle> pool_ptr = MemHandleFromVoid(pool);
try
{
parms_id_type parmsid;
CopyParmsId(parms_id, parmsid);
Ciphertext *cipher = new Ciphertext(sharedctx, parmsid, capacity, *pool_ptr);
*ciphertext = cipher;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Reserve1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size_capacity)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(parms_id, E_POINTER);
parms_id_type parms;
CopyParmsId(parms_id, parms);
try
{
cipher->reserve(sharedctx, parms, size_capacity);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Reserve2(void *thisptr, void *context, uint64_t size_capacity)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
try
{
cipher->reserve(sharedctx, size_capacity);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Reserve3(void *thisptr, uint64_t size_capacity)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
try
{
cipher->reserve(size_capacity);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Set(void *thisptr, void *assign)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
Ciphertext *assignptr = FromVoid<Ciphertext>(assign);
IfNullRet(assignptr, E_POINTER);
*cipher = *assignptr;
return S_OK;
}
SEAL_C_FUNC Ciphertext_Destroy(void *thisptr)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
delete cipher;
return S_OK;
}
SEAL_C_FUNC Ciphertext_Size(void *thisptr, uint64_t *size)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(size, E_POINTER);
*size = cipher->size();
return S_OK;
}
SEAL_C_FUNC Ciphertext_SizeCapacity(void *thisptr, uint64_t *size_capacity)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(size_capacity, E_POINTER);
*size_capacity = cipher->size_capacity();
return S_OK;
}
SEAL_C_FUNC Ciphertext_PolyModulusDegree(void *thisptr, uint64_t *poly_modulus_degree)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(poly_modulus_degree, E_POINTER);
*poly_modulus_degree = cipher->poly_modulus_degree();
return S_OK;
}
SEAL_C_FUNC Ciphertext_CoeffModulusSize(void *thisptr, uint64_t *coeff_modulus_size)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(coeff_modulus_size, E_POINTER);
*coeff_modulus_size = cipher->coeff_modulus_size();
return S_OK;
}
SEAL_C_FUNC Ciphertext_ParmsId(void *thisptr, uint64_t *parms_id)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(parms_id, E_POINTER);
CopyParmsId(cipher->parms_id(), parms_id);
return S_OK;
}
SEAL_C_FUNC Ciphertext_SetParmsId(void *thisptr, uint64_t *parms_id)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(parms_id, E_POINTER);
CopyParmsId(parms_id, cipher->parms_id());
return S_OK;
}
SEAL_C_FUNC Ciphertext_Resize1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
parms_id_type parms;
CopyParmsId(parms_id, parms);
try
{
cipher->resize(sharedctx, parms, size);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Resize2(void *thisptr, void *context, uint64_t size)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
try
{
cipher->resize(sharedctx, size);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Resize3(void *thisptr, uint64_t size)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
try
{
cipher->resize(size);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_Resize4(void *thisptr, uint64_t size, uint64_t polyModulusDegree, uint64_t coeffModCount)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
try
{
Ciphertext::CiphertextPrivateHelper::resize(cipher, size, polyModulusDegree, coeffModCount);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Ciphertext_GetDataAt1(void *thisptr, uint64_t index, uint64_t *data)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(data, E_POINTER);
try
{
*data = (*cipher)[index];
return S_OK;
}
catch (const out_of_range &)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
}
SEAL_C_FUNC Ciphertext_GetDataAt2(void *thisptr, uint64_t poly_index, uint64_t coeff_index, uint64_t *data)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(data, E_POINTER);
auto poly_uint64_count = util::mul_safe(cipher->poly_modulus_degree(), cipher->coeff_modulus_size());
// poly_index is verified by the data method, we need to verify coeff_index ourselves.
if (coeff_index >= poly_uint64_count)
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
try
{
*data = cipher->data(poly_index)[coeff_index];
return S_OK;
}
catch (const out_of_range &)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
}
SEAL_C_FUNC Ciphertext_SetDataAt(void *thisptr, uint64_t index, uint64_t value)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
try
{
(*cipher)[index] = value;
return S_OK;
}
catch (const out_of_range &)
{
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
}
}
SEAL_C_FUNC Ciphertext_IsNTTForm(void *thisptr, bool *is_ntt_form)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(is_ntt_form, E_POINTER);
*is_ntt_form = cipher->is_ntt_form();
return S_OK;
}
SEAL_C_FUNC Ciphertext_SetIsNTTForm(void *thisptr, bool is_ntt_form)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
Ciphertext::CiphertextPrivateHelper::set_ntt_form(cipher, is_ntt_form);
return S_OK;
}
SEAL_C_FUNC Ciphertext_Scale(void *thisptr, double *scale)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(scale, E_POINTER);
*scale = cipher->scale();
return S_OK;
}
SEAL_C_FUNC Ciphertext_SetScale(void *thisptr, double scale)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
cipher->scale() = scale;
return S_OK;
}
SEAL_C_FUNC Ciphertext_Release(void *thisptr)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
cipher->release();
return S_OK;
}
SEAL_C_FUNC Ciphertext_IsTransparent(void *thisptr, bool *result)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(result, E_POINTER);
*result = cipher->is_transparent();
return S_OK;
}
SEAL_C_FUNC Ciphertext_Pool(void *thisptr, void **pool)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(pool, E_POINTER);
MemoryPoolHandle *handleptr = new MemoryPoolHandle(cipher->pool());
*pool = handleptr;
return S_OK;
}
SEAL_C_FUNC Ciphertext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(result, E_POINTER);
try
{
*result = static_cast<int64_t>(cipher->save_size(static_cast<compr_mode_type>(compr_mode)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
}
SEAL_C_FUNC Ciphertext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
IfNullRet(outptr, E_POINTER);
IfNullRet(out_bytes, E_POINTER);
try
{
*out_bytes = util::safe_cast<int64_t>(cipher->save(
reinterpret_cast<SEAL_BYTE *>(outptr), util::safe_cast<size_t>(size),
static_cast<compr_mode_type>(compr_mode)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
catch (const runtime_error &)
{
return COR_E_IO;
}
}
SEAL_C_FUNC Ciphertext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(inptr, E_POINTER);
IfNullRet(in_bytes, E_POINTER);
try
{
*in_bytes = util::safe_cast<int64_t>(
cipher->unsafe_load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
catch (const runtime_error &)
{
return COR_E_IO;
}
}
SEAL_C_FUNC Ciphertext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes)
{
Ciphertext *cipher = FromVoid<Ciphertext>(thisptr);
IfNullRet(cipher, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(inptr, E_POINTER);
IfNullRet(in_bytes, E_POINTER);
try
{
*in_bytes = util::safe_cast<int64_t>(
cipher->load(sharedctx, reinterpret_cast<SEAL_BYTE *>(inptr), util::safe_cast<size_t>(size)));
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
catch (const logic_error &)
{
return COR_E_INVALIDOPERATION;
}
catch (const runtime_error &)
{
return COR_E_IO;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC Ciphertext_Create1(void *pool, void **cipher);
SEAL_C_FUNC Ciphertext_Create2(void *copy, void **cipher);
SEAL_C_FUNC Ciphertext_Create3(void *context, void *pool, void **cipher);
SEAL_C_FUNC Ciphertext_Create4(void *context, uint64_t *parms_id, void *pool, void **cipher);
SEAL_C_FUNC Ciphertext_Create5(void *context, uint64_t *parms_id, uint64_t capacity, void *pool, void **ciphertext);
SEAL_C_FUNC Ciphertext_Reserve1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size_capacity);
SEAL_C_FUNC Ciphertext_Reserve2(void *thisptr, void *context, uint64_t size_capacity);
SEAL_C_FUNC Ciphertext_Reserve3(void *thisptr, uint64_t size_capacity);
SEAL_C_FUNC Ciphertext_Set(void *thisptr, void *assign);
SEAL_C_FUNC Ciphertext_Destroy(void *thisptr);
SEAL_C_FUNC Ciphertext_Size(void *thisptr, uint64_t *size);
SEAL_C_FUNC Ciphertext_SizeCapacity(void *thisptr, uint64_t *size_capacity);
SEAL_C_FUNC Ciphertext_PolyModulusDegree(void *thisptr, uint64_t *poly_modulus_degree);
SEAL_C_FUNC Ciphertext_CoeffModulusSize(void *thisptr, uint64_t *coeff_modulus_size);
SEAL_C_FUNC Ciphertext_ParmsId(void *thisptr, uint64_t *parms_id);
SEAL_C_FUNC Ciphertext_SetParmsId(void *thisptr, uint64_t *parms_id);
SEAL_C_FUNC Ciphertext_Resize1(void *thisptr, void *context, uint64_t *parms_id, uint64_t size);
SEAL_C_FUNC Ciphertext_Resize2(void *thisptr, void *context, uint64_t size);
SEAL_C_FUNC Ciphertext_Resize3(void *thisptr, uint64_t size);
SEAL_C_FUNC Ciphertext_Resize4(void *thisptr, uint64_t size, uint64_t polyModulusDegree, uint64_t coeffModCount);
SEAL_C_FUNC Ciphertext_GetDataAt1(void *thisptr, uint64_t index, uint64_t *data);
SEAL_C_FUNC Ciphertext_GetDataAt2(void *thisptr, uint64_t poly_index, uint64_t coeff_index, uint64_t *data);
SEAL_C_FUNC Ciphertext_SetDataAt(void *thisptr, uint64_t index, uint64_t value);
SEAL_C_FUNC Ciphertext_IsNTTForm(void *thisptr, bool *is_ntt_form);
SEAL_C_FUNC Ciphertext_SetIsNTTForm(void *thisptr, bool is_ntt_form);
SEAL_C_FUNC Ciphertext_Scale(void *thisptr, double *scale);
SEAL_C_FUNC Ciphertext_SetScale(void *thisptr, double scale);
SEAL_C_FUNC Ciphertext_Release(void *thisptr);
SEAL_C_FUNC Ciphertext_IsTransparent(void *thisptr, bool *result);
SEAL_C_FUNC Ciphertext_Pool(void *thisptr, void **pool);
SEAL_C_FUNC Ciphertext_SaveSize(void *thisptr, uint8_t compr_mode, int64_t *result);
SEAL_C_FUNC Ciphertext_Save(void *thisptr, uint8_t *outptr, uint64_t size, uint8_t compr_mode, int64_t *out_bytes);
SEAL_C_FUNC Ciphertext_UnsafeLoad(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes);
SEAL_C_FUNC Ciphertext_Load(void *thisptr, void *context, uint8_t *inptr, uint64_t size, int64_t *in_bytes);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// STD
#include <vector>
// SEALNet
#include "seal/c/ckksencoder.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/ckks.h"
using namespace std;
using namespace seal;
using namespace seal::c;
SEAL_C_FUNC CKKSEncoder_Create(void *context, void **ckks_encoder)
{
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(ckks_encoder, E_POINTER);
try
{
CKKSEncoder *encoder = new CKKSEncoder(sharedctx);
*ckks_encoder = encoder;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC CKKSEncoder_Destroy(void *thisptr)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
delete encoder;
return S_OK;
}
// Array of doubles
SEAL_C_FUNC CKKSEncoder_Encode1(
void *thisptr, uint64_t value_count, double *values, uint64_t *parms_id, double scale, void *destination,
void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
IfNullRet(parms_id, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
parms_id_type parms;
CopyParmsId(parms_id, parms);
vector<double> input(value_count);
for (uint64_t i = 0; i < value_count; i++)
{
input[i] = values[i];
}
try
{
encoder->encode(input, parms, scale, *destinationptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Array of complex numbers (two doubles per value)
SEAL_C_FUNC CKKSEncoder_Encode2(
void *thisptr, uint64_t value_count, double *complex_values, uint64_t *parms_id, double scale, void *destination,
void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
IfNullRet(parms_id, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
parms_id_type parms;
CopyParmsId(parms_id, parms);
vector<complex<double>> input(value_count);
for (uint64_t i = 0; i < value_count; i++)
{
input[i] = complex<double>(complex_values[i * 2], complex_values[i * 2 + 1]);
}
try
{
encoder->encode(input, parms, scale, *destinationptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Single double value
SEAL_C_FUNC CKKSEncoder_Encode3(
void *thisptr, double value, uint64_t *parms_id, double scale, void *destination, void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
IfNullRet(parms_id, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
parms_id_type parms;
CopyParmsId(parms_id, parms);
try
{
encoder->encode(value, parms, scale, *destinationptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Single complex value
SEAL_C_FUNC CKKSEncoder_Encode4(
void *thisptr, double value_re, double value_im, uint64_t *parms_id, double scale, void *destination, void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
IfNullRet(parms_id, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
parms_id_type parms;
CopyParmsId(parms_id, parms);
complex<double> input(value_re, value_im);
try
{
encoder->encode(input, parms, scale, *destinationptr, *handle);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Single Int64 value
SEAL_C_FUNC CKKSEncoder_Encode5(void *thisptr, int64_t value, uint64_t *parms_id, void *destination)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
IfNullRet(parms_id, E_POINTER);
parms_id_type parms;
CopyParmsId(parms_id, parms);
try
{
encoder->encode(value, parms, *destinationptr);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Array of doubles
SEAL_C_FUNC CKKSEncoder_Decode1(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(value_count, E_POINTER);
IfNullRet(values, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
vector<double> destination;
try
{
encoder->decode(*plainptr, destination, *handle);
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
*value_count = destination.size();
// Copy to actual destination
for (uint64_t i = 0; i < destination.size(); i++)
{
values[i] = destination[i];
}
return S_OK;
}
// Array of complex numbers
SEAL_C_FUNC CKKSEncoder_Decode2(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(value_count, E_POINTER);
IfNullRet(values, E_POINTER);
Plaintext *plainptr = FromVoid<Plaintext>(plain);
IfNullRet(plainptr, E_POINTER);
unique_ptr<MemoryPoolHandle> handle = MemHandleFromVoid(pool);
vector<complex<double>> destination;
try
{
encoder->decode(*plainptr, destination, *handle);
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
*value_count = destination.size();
// Copy to actual destination
for (uint64_t i = 0; i < destination.size(); i++)
{
values[i * 2] = destination[i].real();
values[i * 2 + 1] = destination[i].imag();
}
return S_OK;
}
SEAL_C_FUNC CKKSEncoder_SlotCount(void *thisptr, uint64_t *slot_count)
{
CKKSEncoder *encoder = FromVoid<CKKSEncoder>(thisptr);
IfNullRet(encoder, E_POINTER);
IfNullRet(slot_count, E_POINTER);
*slot_count = encoder->slot_count();
return S_OK;
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC CKKSEncoder_Create(void *context, void **ckks_encoder);
SEAL_C_FUNC CKKSEncoder_Destroy(void *thisptr);
// Array of doubles
SEAL_C_FUNC CKKSEncoder_Encode1(
void *thisptr, uint64_t value_count, double *values, uint64_t *parms_id, double scale, void *destination,
void *pool);
// Array of complex numbers (two doubles per value)
SEAL_C_FUNC CKKSEncoder_Encode2(
void *thisptr, uint64_t value_count, double *complex_values, uint64_t *parms_id, double scale, void *destination,
void *pool);
// Single double value
SEAL_C_FUNC CKKSEncoder_Encode3(
void *thisptr, double value, uint64_t *parms_id, double scale, void *destination, void *pool);
// Single complex value
SEAL_C_FUNC CKKSEncoder_Encode4(
void *thisptr, double value_re, double value_im, uint64_t *parms_id, double scale, void *destination, void *pool);
// Single Int64 value
SEAL_C_FUNC CKKSEncoder_Encode5(void *thisptr, int64_t value, uint64_t *parms_id, void *destination);
// Array of doubles
SEAL_C_FUNC CKKSEncoder_Decode1(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool);
// Array of complex numbers
SEAL_C_FUNC CKKSEncoder_Decode2(void *thisptr, void *plain, uint64_t *value_count, double *values, void *pool);
SEAL_C_FUNC CKKSEncoder_SlotCount(void *thisptr, uint64_t *slot_count);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// SEALNet
#include "seal/c/contextdata.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/context.h"
using namespace std;
using namespace seal;
using namespace seal::c;
SEAL_C_FUNC ContextData_Destroy(void *thisptr)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
delete cont_data;
return S_OK;
}
SEAL_C_FUNC ContextData_TotalCoeffModulus(void *thisptr, uint64_t *count, uint64_t *total_coeff_modulus)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(count, E_POINTER);
*count = cont_data->parms().coeff_modulus().size();
if (nullptr == total_coeff_modulus)
{
// We only wanted the count.
return S_OK;
}
for (uint64_t i = 0; i < *count; i++)
{
total_coeff_modulus[i] = cont_data->total_coeff_modulus()[i];
}
return S_OK;
}
SEAL_C_FUNC ContextData_TotalCoeffModulusBitCount(void *thisptr, int *bit_count)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(bit_count, E_POINTER);
*bit_count = cont_data->total_coeff_modulus_bit_count();
return S_OK;
}
SEAL_C_FUNC ContextData_Parms(void *thisptr, void **parms)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
EncryptionParameters *enc_params = new EncryptionParameters(cont_data->parms());
*parms = enc_params;
return S_OK;
}
SEAL_C_FUNC ContextData_Qualifiers(void *thisptr, void **epq)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(epq, E_POINTER);
EncryptionParameterQualifiers *qualifiers = new EncryptionParameterQualifiers(cont_data->qualifiers());
*epq = qualifiers;
return S_OK;
}
SEAL_C_FUNC ContextData_CoeffDivPlainModulus(void *thisptr, uint64_t *count, uint64_t *coeff_div)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(count, E_POINTER);
*count = cont_data->parms().coeff_modulus().size();
if (nullptr == coeff_div)
{
// We only wanted the size
return S_OK;
}
for (uint64_t i = 0; i < *count; i++)
{
coeff_div[i] = cont_data->coeff_div_plain_modulus()[i];
}
return S_OK;
}
SEAL_C_FUNC ContextData_PlainUpperHalfThreshold(void *thisptr, uint64_t *puht)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(puht, E_POINTER);
*puht = cont_data->plain_upper_half_threshold();
return S_OK;
}
SEAL_C_FUNC ContextData_PlainUpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *puhi)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(count, E_POINTER);
*count = cont_data->parms().coeff_modulus().size();
if (nullptr == puhi)
{
// We only wanted the size
return S_OK;
}
for (uint64_t i = 0; i < *count; i++)
{
puhi[i] = cont_data->plain_upper_half_increment()[i];
}
return S_OK;
}
SEAL_C_FUNC ContextData_UpperHalfThreshold(void *thisptr, uint64_t *count, uint64_t *uht)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(count, E_POINTER);
// This is only available for CKKS
if (cont_data->upper_half_threshold() == nullptr)
{
*count = 0;
return S_OK;
}
*count = cont_data->parms().coeff_modulus().size();
if (nullptr == uht)
{
// We only wanted the count
return S_OK;
}
for (uint64_t i = 0; i < *count; i++)
{
uht[i] = cont_data->upper_half_threshold()[i];
}
return S_OK;
}
SEAL_C_FUNC ContextData_UpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *uhi)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(count, E_POINTER);
if (cont_data->upper_half_increment() == nullptr)
{
*count = 0;
return S_OK;
}
*count = cont_data->parms().coeff_modulus().size();
if (nullptr == uhi)
{
// We only wanted the size
return S_OK;
}
for (uint64_t i = 0; i < *count; i++)
{
uhi[i] = cont_data->upper_half_increment()[i];
}
return S_OK;
}
SEAL_C_FUNC ContextData_PrevContextData(void *thisptr, void **prev_data)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(prev_data, E_POINTER);
// The caller should not try to delete the returned pointer
*prev_data = const_cast<SEALContext::ContextData *>(cont_data->prev_context_data().get());
return S_OK;
}
SEAL_C_FUNC ContextData_NextContextData(void *thisptr, void **next_data)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(next_data, E_POINTER);
// The caller should not try to delete the returned pointer
*next_data = const_cast<SEALContext::ContextData *>(cont_data->next_context_data().get());
return S_OK;
}
SEAL_C_FUNC ContextData_ChainIndex(void *thisptr, uint64_t *index)
{
SEALContext::ContextData *cont_data = FromVoid<SEALContext::ContextData>(thisptr);
IfNullRet(cont_data, E_POINTER);
IfNullRet(index, E_POINTER);
*index = cont_data->chain_index();
return S_OK;
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC ContextData_Destroy(void *thisptr);
SEAL_C_FUNC ContextData_TotalCoeffModulus(void *thisptr, uint64_t *count, uint64_t *total_coeff_modulus);
SEAL_C_FUNC ContextData_TotalCoeffModulusBitCount(void *thisptr, int *bit_count);
SEAL_C_FUNC ContextData_Parms(void *thisptr, void **parms);
SEAL_C_FUNC ContextData_Qualifiers(void *thisptr, void **epq);
SEAL_C_FUNC ContextData_CoeffDivPlainModulus(void *thisptr, uint64_t *count, uint64_t *coeff_div);
SEAL_C_FUNC ContextData_PlainUpperHalfThreshold(void *thisptr, uint64_t *puht);
SEAL_C_FUNC ContextData_PlainUpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *puhi);
SEAL_C_FUNC ContextData_UpperHalfThreshold(void *thisptr, uint64_t *count, uint64_t *uht);
SEAL_C_FUNC ContextData_UpperHalfIncrement(void *thisptr, uint64_t *count, uint64_t *uhi);
SEAL_C_FUNC ContextData_PrevContextData(void *thisptr, void **prev_data);
SEAL_C_FUNC ContextData_NextContextData(void *thisptr, void **next_data);
SEAL_C_FUNC ContextData_ChainIndex(void *thisptr, uint64_t *index);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// SEALNet
#include "seal/c/decryptor.h"
#include "seal/c/stdafx.h"
#include "seal/c/utilities.h"
// SEAL
#include "seal/decryptor.h"
using namespace std;
using namespace seal;
using namespace seal::c;
SEAL_C_FUNC Decryptor_Create(void *context, void *secret_key, void **decryptor)
{
SecretKey *secretKey = FromVoid<SecretKey>(secret_key);
IfNullRet(secretKey, E_POINTER);
const auto &sharedctx = SharedContextFromVoid(context);
IfNullRet(sharedctx.get(), E_POINTER);
IfNullRet(decryptor, E_POINTER);
try
{
Decryptor *decr = new Decryptor(sharedctx, *secretKey);
*decryptor = decr;
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Decryptor_Destroy(void *thisptr)
{
Decryptor *decryptor = FromVoid<Decryptor>(thisptr);
IfNullRet(decryptor, E_POINTER);
delete decryptor;
return S_OK;
}
SEAL_C_FUNC Decryptor_Decrypt(void *thisptr, void *encrypted, void *destination)
{
Decryptor *decryptor = FromVoid<Decryptor>(thisptr);
IfNullRet(decryptor, E_POINTER);
Ciphertext *encryptedptr = FromVoid<Ciphertext>(encrypted);
IfNullRet(encryptedptr, E_POINTER);
Plaintext *destinationptr = FromVoid<Plaintext>(destination);
IfNullRet(destinationptr, E_POINTER);
try
{
decryptor->decrypt(*encryptedptr, *destinationptr);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
SEAL_C_FUNC Decryptor_InvariantNoiseBudget(void *thisptr, void *encrypted, int *invariant_noise_budget)
{
Decryptor *decryptor = FromVoid<Decryptor>(thisptr);
IfNullRet(decryptor, E_POINTER);
Ciphertext *encryptedptr = FromVoid<Ciphertext>(encrypted);
IfNullRet(encryptedptr, E_POINTER);
IfNullRet(invariant_noise_budget, E_POINTER);
try
{
*invariant_noise_budget = decryptor->invariant_noise_budget(*encryptedptr);
return S_OK;
}
catch (const invalid_argument &)
{
return E_INVALIDARG;
}
}
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
///////////////////////////////////////////////////////////////////////////
//
// This API is provided as a simple interface for Microsoft SEAL library
// that can be PInvoked by .Net code.
//
///////////////////////////////////////////////////////////////////////////
#include "seal/c/defines.h"
#include <stdint.h>
SEAL_C_FUNC Decryptor_Create(void *context, void *secret_key, void **decryptor);
SEAL_C_FUNC Decryptor_Destroy(void *thisptr);
SEAL_C_FUNC Decryptor_Decrypt(void *thisptr, void *encrypted, void *destination);
SEAL_C_FUNC Decryptor_InvariantNoiseBudget(void *thisptr, void *encrypted, int *invariant_noise_budget);
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#pragma once
// STD
#include <cstddef>
// Check that std::size_t is 64 bits
static_assert(sizeof(std::size_t) == 8, "Require sizeof(std::size_t) == 8");
#ifdef _MSC_VER
// Check that architecture (platform) is x64
#ifndef _WIN64
static_assert(false, "Require architecture == x64");
#endif
#ifdef SEAL_C_EXPORTS
#define SEAL_C_DECOR extern "C" __declspec(dllexport)
#else
#define SEAL_C_DECOR extern "C" __declspec(dllimport)
#endif
#define SEAL_C_CALL __cdecl
#else // _MSC_VER
#define SEAL_C_DECOR extern "C"
#define SEAL_C_CALL
#define HRESULT long
#define _HRESULT_TYPEDEF_(hr) ((HRESULT)hr)
#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L)
#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L)
#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL)
#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL)
#define COR_E_IO _HRESULT_TYPEDEF_(0x80131620L)
#define COR_E_INVALIDOPERATION _HRESULT_TYPEDEF_(0x80131509L)
#define S_OK _HRESULT_TYPEDEF_(0L)
#define S_FALSE _HRESULT_TYPEDEF_(1L)
#define FACILITY_WIN32 7
#define HRESULT_FROM_WIN32(x) \
((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT)(((x)&0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
#define ERROR_INSUFFICIENT_BUFFER 122L
#define ERROR_INVALID_INDEX 1413L
#define ERROR_INVALID_OPERATION 4317L
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)
#endif // _MSC_VER
#define SEAL_C_FUNC SEAL_C_DECOR HRESULT SEAL_C_CALL
\ No newline at end of file
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
// dllmain.cpp : Defines the entry point for the DLL application.
#include "seal/c/stdafx.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment