Program Listing for File lwe-keyswitchkey32.h
↰ Return to documentation for file (binfhe/include/lwe-keyswitchkey32.h)
//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2026, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================
#ifndef SRC_BINFHE_INCLUDE_LWE_KEYSWITCHKEY32_H_
#define SRC_BINFHE_INCLUDE_LWE_KEYSWITCHKEY32_H_
#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "lwe-cryptoparameters.h"
#include "lwe-keyswitchkey-fwd.h"
#include "utils/serializable.h"
namespace lbcrypto {
#if NATIVEINT != 32
class LWESwitchingKey32Impl;
using LWESwitchingKey32 = std::shared_ptr<LWESwitchingKey32Impl>;
using ConstLWESwitchingKey32 = const std::shared_ptr<const LWESwitchingKey32Impl>;
class LWESwitchingKey32Impl : public Serializable {
public:
LWESwitchingKey32Impl() = default;
static bool Fits(const LWECryptoParams& params) {
const auto& qKS = params.GetqKS();
if (qKS.GetMSB() > MAX_MODULUS_SIZE32)
return false;
uint64_t rows{static_cast<uint64_t>(params.GetN()) * params.GetDigitCountKS()};
return rows <= static_cast<uint64_t>(-1) / qKS.ConvertToInt<uint64_t>();
}
LWESwitchingKey32Impl(uint32_t N, uint32_t baseKS, uint32_t digitCount, uint32_t topExtent, uint32_t n)
: m_N(N),
m_m(baseKS),
m_d(digitCount),
m_top(topExtent),
m_n(n),
m_rows(static_cast<uint64_t>(digitCount - 1) * (baseKS - 1) + (topExtent - 1)),
m_sizeA(static_cast<uint64_t>(N) * m_rows * n),
m_sizeB(static_cast<uint64_t>(N) * m_rows),
m_keyA(new uint32_t[m_sizeA]),
m_keyB(new uint32_t[m_sizeB]) {}
LWESwitchingKey32Impl(const LWECryptoParams& params, const LWESwitchingKeyImpl& K);
LWESwitchingKey Widen(const LWECryptoParams& params) const;
uint32_t* RowA(uint32_t i, uint32_t val, uint32_t pos) {
return m_keyA.get() + Slot(i, val, pos) * m_n;
}
const uint32_t* RowA(uint32_t i, uint32_t val, uint32_t pos) const {
return m_keyA.get() + Slot(i, val, pos) * m_n;
}
uint32_t& B(uint32_t i, uint32_t val, uint32_t pos) {
return m_keyB[Slot(i, val, pos)];
}
uint32_t B(uint32_t i, uint32_t val, uint32_t pos) const {
return m_keyB[Slot(i, val, pos)];
}
uint32_t GetDigitExtent(uint32_t pos) const {
return pos + 1 < m_d ? m_m : m_top;
}
uint32_t GetN() const {
return m_N;
}
uint32_t GetBaseKS() const {
return m_m;
}
uint32_t GetDigitCount() const {
return m_d;
}
uint32_t Getn() const {
return m_n;
}
uint64_t KeyBytes() const {
return (m_sizeA + m_sizeB) * sizeof(uint32_t);
}
bool operator==(const LWESwitchingKey32Impl& other) const {
if (m_N != other.m_N || m_m != other.m_m || m_d != other.m_d || m_top != other.m_top || m_n != other.m_n)
return false;
return std::equal(m_keyA.get(), m_keyA.get() + m_sizeA, other.m_keyA.get()) &&
std::equal(m_keyB.get(), m_keyB.get() + m_sizeB, other.m_keyB.get());
}
bool operator!=(const LWESwitchingKey32Impl& other) const {
return !(*this == other);
}
template <class Archive>
void save(Archive& ar, std::uint32_t const version) const {
ar(::cereal::make_nvp("N", m_N));
ar(::cereal::make_nvp("m", m_m));
ar(::cereal::make_nvp("d", m_d));
ar(::cereal::make_nvp("top", m_top));
ar(::cereal::make_nvp("n", m_n));
Bytes(ar, m_keyA.get(), m_sizeA);
Bytes(ar, m_keyB.get(), m_sizeB);
}
template <class Archive>
void load(Archive& ar, std::uint32_t const version) {
if (version > SerializedVersion()) {
OPENFHE_THROW("serialized object version " + std::to_string(version) +
" is from a later version of the library");
}
ar(::cereal::make_nvp("N", m_N));
ar(::cereal::make_nvp("m", m_m));
ar(::cereal::make_nvp("d", m_d));
ar(::cereal::make_nvp("top", m_top));
ar(::cereal::make_nvp("n", m_n));
Size();
m_keyA.reset(new uint32_t[m_sizeA]);
m_keyB.reset(new uint32_t[m_sizeB]);
Bytes(ar, m_keyA.get(), m_sizeA);
Bytes(ar, m_keyB.get(), m_sizeB);
}
std::string SerializedObjectName() const override {
return "LWESwitchingKey32";
}
static uint32_t SerializedVersion() {
return 1;
}
private:
// One flat array, in whichever form the archive takes: the binary archives move it as a block,
// and the JSON archive, which has no binary support, takes it one element at a time. Both sides
// call this, so the two representations stay paired.
template <class Archive, typename T>
static void Bytes(Archive& ar, T* p, uint64_t n) {
if constexpr (::cereal::traits::is_output_serializable<::cereal::BinaryData<T*>, Archive>::value ||
::cereal::traits::is_input_serializable<::cereal::BinaryData<T*>, Archive>::value) {
ar(::cereal::binary_data(p, n * sizeof(T)));
} else {
for (uint64_t i = 0; i < n; ++i)
ar(p[i]);
}
}
void Size() {
m_rows = static_cast<uint64_t>(m_d - 1) * (m_m - 1) + (m_top - 1);
m_sizeA = static_cast<uint64_t>(m_N) * m_rows * m_n;
m_sizeB = static_cast<uint64_t>(m_N) * m_rows;
}
uint64_t Slot(uint32_t i, uint32_t val, uint32_t pos) const {
return static_cast<uint64_t>(i) * m_rows + static_cast<uint64_t>(pos) * (m_m - 1) + (val - 1);
}
uint32_t m_N{0};
uint32_t m_m{0};
uint32_t m_d{0};
uint32_t m_top{0};
uint32_t m_n{0};
uint64_t m_rows{0};
uint64_t m_sizeA{0};
uint64_t m_sizeB{0};
std::unique_ptr<uint32_t[]> m_keyA;
std::unique_ptr<uint32_t[]> m_keyB;
};
#endif // NATIVEINT != 32
} // namespace lbcrypto
#endif // SRC_BINFHE_INCLUDE_LWE_KEYSWITCHKEY32_H_