Palisade lattice headers

Palisade lattice headers

\core\include\lattice\elemparams.h

class ElemParams : public Serializable

Wrapper class to hold the parameters for Element types and their inheritors.
参数类,首先看它有什么参数:

protected:
  usint cyclotomicOrder;
  usint ringDimension;  // True iff the Ring Dimension is a power of 2.

  bool isPowerOfTwo;
  IntegerType ciphertextModulus;
  IntegerType rootOfUnity;
  IntegerType bigCiphertextModulus;  // Used for only some applications.
  IntegerType bigRootOfUnity;        // Used for only some applications.

构造函数:

  /**
   * @brief Simple constructor method that takes as input root of unity, big
   * root of unity, cyclotomic order and the ciphertext modulus and big
   * ciphertext Modulus.  This is used for bit-packing operations.
   * @param order the cyclotomic order wrapped by the parameter set.
   * @param ctModulus the ciphertext modulus wrapped by the parameter set.
   * @param rUnity the root of unity.
   * @param bigCtModulus the big ciphertext modulus used for bit packing
   * operations.
   * @param bigRUnity the big root of unity used for bit packing operations.
   */
  ElemParams(usint order, const IntegerType& ctModulus,
             const IntegerType& rUnity = IntegerType(0),
             const IntegerType& bigCtModulus = IntegerType(0),
             const IntegerType& bigRUnity = IntegerType(0)) {
    cyclotomicOrder = order;
    ringDimension = GetTotient(order);
    isPowerOfTwo = ringDimension == cyclotomicOrder / 2;
    ciphertextModulus = ctModulus;
    rootOfUnity = rUnity;
    bigCiphertextModulus = bigCtModulus;
    bigRootOfUnity = bigRUnity;
  }

cyclotomicOrder 是分圆的次数,ringDimension 等于cyclotomicOrder 的欧拉函数值,与之对应的是分圆多项式的次数。环是模分圆多项式的。

  /**
   * @brief Copy constructor using assignment to copy wrapped elements.
   * @param rhs the input ElemParams copied.
   * @return the resulting parameter set with parameters copied.
   */
  ElemParams(const ElemParams& rhs) {
    cyclotomicOrder = rhs.cyclotomicOrder;
    ringDimension = rhs.ringDimension;
    isPowerOfTwo = rhs.isPowerOfTwo;
    ciphertextModulus = rhs.ciphertextModulus;
    rootOfUnity = rhs.rootOfUnity;
    bigCiphertextModulus = rhs.bigCiphertextModulus;
    bigRootOfUnity = rhs.bigRootOfUnity;
  }

  /**
   * @brief Copy constructor using move semnantics to copy wrapped elements.
   * @param rhs the input ElemParams copied.
   * @return the resulting copy of the parameter set.
   */
  ElemParams(const ElemParams&& rhs) {
    cyclotomicOrder = rhs.cyclotomicOrder;
    ringDimension = rhs.ringDimension;
    isPowerOfTwo = rhs.isPowerOfTwo;
    ciphertextModulus = std::move(rhs.ciphertextModulus);
    rootOfUnity = std::move(rhs.rootOfUnity);
    bigCiphertextModulus = std::move(rhs.bigCiphertextModulus);
    bigRootOfUnity = std::move(rhs.bigRootOfUnity);
  }

赋值运算符重载和析构函数

  /**
   * @brief Assignment operator using assignment operations of wrapped elements.
   * @param rhs the ElemParams instance to copy.
   */
  const ElemParams& operator=(const ElemParams& rhs) {
    cyclotomicOrder = rhs.cyclotomicOrder;
    ringDimension = rhs.ringDimension;
    isPowerOfTwo = rhs.isPowerOfTwo;
    ciphertextModulus = rhs.ciphertextModulus;
    rootOfUnity = rhs.rootOfUnity;
    bigCiphertextModulus = rhs.bigCiphertextModulus;
    bigRootOfUnity = rhs.bigRootOfUnity;
    return *this;
  }

  /**
   * @brief Simple destructor method.
   * @return
   */
  virtual ~ElemParams() {}

getter函数,没有setter函数,因此只能在构造时确定参数。

  /**
   * @brief Simple getter method for cyclotomic order.
   * @return The cyclotomic order.
   */
  usint GetCyclotomicOrder() const { return cyclotomicOrder; }

  /**
   * @brief Simple ring dimension getter method.  The ring dimension is the
   * evaluation of the totient function of the cyclotomic order.
   * @return the ring dimension.
   */
  usint GetRingDimension() const { return ringDimension; }

  /**
   * @brief Returns True if the cyclotomic order or ring dimension is a power
   * of 2.
   * @return True if the cyclotomic order or ring dimension is a power of 2.
   * False otherwise.
   */
  bool OrderIsPowerOfTwo() const { return isPowerOfTwo; }

  /**
   * @brief Simple getter method for the ciphertext modulus, not the big
   * ciphertext modulus.
   * @return The ciphertext modulus, not the big ciphertext modulus.
   */
  const IntegerType& GetModulus() const { return ciphertextModulus; }

  /**
   * @brief Simpler getter method for the big ciphertext modulus.
   * This is not relevant for all applications.
   * @return The big ciphertext modulus.
   */
  const IntegerType& GetBigModulus() const { return bigCiphertextModulus; }

  /**
   * @brief Simple getter method for the root of unity, not the big root of
   * unity.
   * @return The root of unity, not the big root of unity.
   */
  const IntegerType& GetRootOfUnity() const { return rootOfUnity; }

  /**
   * @brief Simple getter method for the big root of unity.
   * @return The the big root of unity.
   */
  const IntegerType& GetBigRootOfUnity() const { return bigRootOfUnity; }

输出运算符,判断相等运算符,判断不相等运算符重载
【注】友元不是成员函数

  /**
   * @brief Output strem operator.
   * @param out the preceding output stream.
   * @param item what to add to the output stream.
   * @return the appended output stream.
   */
  friend std::ostream& operator<<(std::ostream& out, const ElemParams& item) {
    return item.doprint(out);
  }

  /**
   * @brief Equality operator that tests the equality of all wrapped values.
   * @param other the other ElemenParams to compare to.
   * @return True if all elements are equal, and False otherwise.
   */
  virtual bool operator==(const ElemParams<IntegerType>& other) const {
    return cyclotomicOrder == other.cyclotomicOrder &&
           ringDimension == other.ringDimension &&
           ciphertextModulus == other.ciphertextModulus &&
           rootOfUnity == other.rootOfUnity &&
           bigCiphertextModulus == other.bigCiphertextModulus &&
           bigRootOfUnity == other.bigRootOfUnity;
  }

  /**
   * @brief Inequality operator that tests the equality of all wrapped values.
   * @param other the other ElemenParams to compare to.
   * @return False if all elements are equal, and True otherwise.
   */
  bool operator!=(const ElemParams<IntegerType>& other) const {
    return !(*this == other);
  }

save和load函数,暂时没搞懂要干啥

  template <class Archive>
  void save(Archive& ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("co", cyclotomicOrder));
    ar(::cereal::make_nvp("rd", ringDimension));
    ar(::cereal::make_nvp("2n", isPowerOfTwo));
    ar(::cereal::make_nvp("cm", ciphertextModulus));
    ar(::cereal::make_nvp("ru", rootOfUnity));
    ar(::cereal::make_nvp("bm", bigCiphertextModulus));
    ar(::cereal::make_nvp("br", bigRootOfUnity));
  }

  template <class Archive>
  void load(Archive& ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("co", cyclotomicOrder));
    ar(::cereal::make_nvp("rd", ringDimension));
    ar(::cereal::make_nvp("2n", isPowerOfTwo));
    ar(::cereal::make_nvp("cm", ciphertextModulus));
    ar(::cereal::make_nvp("ru", rootOfUnity));
    ar(::cereal::make_nvp("bm", bigCiphertextModulus));
    ar(::cereal::make_nvp("br", bigRootOfUnity));
  }
  std::string SerializedObjectName() const { return "ElemParams"; }
  static uint32_t SerializedVersion() { return 1; }

以上函数都是public的
下面这个是protected属性,是给输出运算符调用的。

  /**
   * @brief Pretty print operator for the ElemParams type.
   * @param out the ElemParams to output
   * @return the resulting output stream.
   */
  virtual std::ostream& doprint(std::ostream& out) const {
    out << "[m=" << cyclotomicOrder << (isPowerOfTwo ? "* " : " ")
        << "n=" << ringDimension << " q=" << ciphertextModulus
        << " ru=" << rootOfUnity << " bigq=" << bigCiphertextModulus
        << " bigru=" << bigRootOfUnity << "]";
    return out;
  }
};

\core\include\lattice\ilparams.h

Wraps parameters for integer lattice operations. Inherits from ElemParams.

class ILParamsImpl : public ElemParams

继承自ElemParams类,继承了所有成员。

 public:
  typedef IntType Integer;

构造函数

  /**
   * @brief Constructor for the case of partially pre-computed parameters.
   *
   * @param &order the order of the ciphertext.
   * @param &modulus the ciphertext modulus.
   * @param &rootOfUnity the root of unity used in the ciphertext.
   * @param bigModulus the big ciphertext modulus.
   * @param bigRootOfUnity the big ciphertext modulus used for bit packing
   * operations.
   * @return
   */
  ILParamsImpl(const usint order, const IntType &modulus,
               const IntType &rootOfUnity, const IntType &bigModulus = 0,   // 这个要传rootIfUnity
               const IntType &bigRootOfUnity = 0)
      : ElemParams<IntType>(order, modulus, rootOfUnity, bigModulus,
                            bigRootOfUnity) {}

  /**
   * @brief Constructor for the case of partially pre-computed parameters.
   *
   * @param &order the order of the ciphertext.
   * @param &modulus the ciphertext modulus.
   */
  ILParamsImpl(const usint order, const IntType &modulus)
      : ElemParams<IntType>(order, modulus) {
    this->rootOfUnity = RootOfUnity<IntType>(order, modulus); // 跟父类不同之处在于父类不需要计算rootOfUnity,交给子类计算。
  }

  /**
   * @brief Copy constructor.
   *
   * @param &rhs the input set of parameters which is copied.
   */
  ILParamsImpl(const ILParamsImpl &rhs) : ElemParams<IntType>(rhs) {}
  /**
   * @brief Assignment Operator.
   *
   * @param &rhs the params to be copied.
   * @return this object
   */
  const ILParamsImpl &operator=(const ILParamsImpl &rhs) {
    ElemParams<IntType>::operator=(rhs);
    return *this;
  }

  /**
   * @brief Move constructor.
   *
   * @param &rhs the input set of parameters which is copied.
   */
  ILParamsImpl(const ILParamsImpl &&rhs) : ElemParams<IntType>(rhs) {}

  /**
   * @brief Standard Destructor method.
   */
  ~ILParamsImpl() {}

相等运算符重载

  /**
   * @brief Equality operator compares ElemParams (which will be dynamic casted)
   *
   * @param &rhs is the specified Poly to be compared with this Poly.
   * @return True if this Poly represents the same values as the specified
   * DCRTPoly, False otherwise
   */
  bool operator==(const ElemParams<IntType> &rhs) const {
    if (dynamic_cast<const ILParamsImpl<IntType> *>(&rhs) == nullptr)   // 动态类型转换
      return false;

    return ElemParams<IntType>::operator==(rhs);
  }

下面这个函数供输出运算符调用,输出运算符重载在父类实现。

 private:
  std::ostream &doprint(std::ostream &out) const {
    out << "ILParams ";
    ElemParams<IntType>::doprint(out);
    out << std::endl;
    return out;
  }

save和load函数

 public:
  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::base_class<ElemParams<IntType>>(this));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::base_class<ElemParams<IntType>>(this));
  }

  std::string SerializedObjectName() const { return "ILParms"; }
  static uint32_t SerializedVersion() { return 1; }
};

\core\include\lattice\ildcrtparams.h

Wraps parameters for integer lattice operations using double-CRT representation. Inherits from ElemParams.

class ILDCRTParams : public ElemParams

/**
 * @brief Parameters for array of ideal lattices (used for Double-CRT).
 *
 * The double-CRT representation of polynomials is a common optimization for
 * lattice encryption operations. Basically, it allows large-modulus polynamials
 * to be represented as multiple smaller-modulus polynomials. The double-CRT
 * representations are discussed theoretically here:
 *   - Gentry C., Halevi S., Smart N.P. (2012) Homomorphic Evaluation of the AES
 * Circuit. In: Safavi-Naini R., Canetti R. (eds) Advances in Cryptology –
 * CRYPTO 2012. Lecture Notes in Computer Science, vol 7417. Springer, Berlin,
 * Heidelberg
 */
 template <typename IntType>
class ILDCRTParams : public ElemParams<IntType> {
 public:
  static const usint DEFAULT_NBITS = 20;

  typedef IntType Integer;
  using ILNativeParams = ILParamsImpl<NativeInteger>;  // typedef 不能够直接给模板类进行取别名。

首先看私有成员,比父类多出两个成员
m_parms是一个ILNativeParams对象的数组,每个对象包含ILParamsImpl<nativeInteger>中的所有成员,即cyclotomicOrder、ringDimension、isPowerOfTwo、ciphertextModulus、rootOfUnity、bigCiphertextModulus、bigRootOfUnity和函数。

originalModulus并不真正存放密文模数,ciphertextModulus才真正存放密文模数。

 private:
  std::ostream &doprint(std::ostream &out) const {
    out << "ILDCRTParams ";
    ElemParams<IntType>::doprint(out);
    out << std::endl << " Parms:" << std::endl;
    for (size_t i = 0; i < m_parms.size(); i++) {
      out << "   " << i << ":" << *m_parms[i] << std::endl;
    }
    out << "OriginalModulus " << originalModulus << std::endl;
    return out;
  }

  // array of smaller ILParams
  std::vector<std::shared_ptr<ILNativeParams>> m_parms;

  // original modulus when being constructed from a Poly or when
  // ctor is passed that parameter
  // note orignalModulus will be <= composite modules
  //   i.e. \Prod_i=0^k-1 m_params[i]->GetModulus() 它们的乘积
  // note not using ElemParams::ciphertextModulus due to object stripping
  Integer originalModulus;
};
构造函数,一个一个来

第一个:

  /**
   * @brief Constructor with basic parameter set.
   * q is selected as FirstPrime(bits, order)
   * @param order the order of the ciphertext.
   * @param depth is the size of the tower.
   * @param bits is the number of bits of each tower's moduli.
   */
  explicit ILDCRTParams(usint order = 0, usint depth = 1,   // 声明为explicit的构造函数不能在隐式转换中使用。也就是不能用隐式转换法创建对象。
                        usint bits = DEFAULT_NBITS);

第二个:
传入cyclotomicOrder,modulus,rootOfUnity参数,其中rootOfUnity参数没有用到,modulus参数限制了密文模数的大小,先声明三个变量:numOfTower保存模数的数目,moduli保存模数数组,rootsOtUnity保存与模数对应的单位根数组,当compositeModulus大于等于modulus时停止,将moduli和rootsOfUnity保存到成员m_params中,然后重新计算密文模数,将其保存到ciphertextModulus中。originalModulus保存modulus。
这个构造函数与bigModulus无关。

  /**
   * @brief Constructor with basic parameters
   *
   * @param cyclotomic_order the order of the ciphertext
   * @param &modulus is the modulus for the primary ciphertext. 是总的密文模数q
   * @param rootsOfUnity is unused
   */
  ILDCRTParams(const usint cyclotomic_order, const IntType &modulus,
               const IntType &rootOfUnity)
      : ElemParams<IntType>(cyclotomic_order, modulus, 0, 0, 0) {
    // NOTE parms generation uses this constructor to make an empty parms that
    // it will later populate during the gen process. For that special case...  populate:增添数据
    // we don't populate, and we just return

    if (cyclotomic_order == 0) return;

    DEBUG_FLAG(false);
    DEBUG(
        "in ILDCRTParams(const usint cyclotomic_order, const IntType &modulus, "
        "const IntType& rootOfUnity");
    DEBUGEXP(cyclotomic_order);
    DEBUGEXP(modulus);
    DEBUGEXP(rootOfUnity);
    usint numOfTower = 1;
    std::vector<NativeInteger> moduli;
    std::vector<NativeInteger> rootsOfUnity;

    NativeInteger q =
        FirstPrime<NativeInteger>(DEFAULT_NBITS, cyclotomic_order); // q = 1 mod cyclotomic_order
    IntType compositeModulus(1);

    for (;;) {
      moduli.push_back(q);
      rootsOfUnity.push_back(RootOfUnity(cyclotomic_order, q));
      compositeModulus = compositeModulus * IntType(q.ConvertToInt());
      if (compositeModulus >= modulus) break;   // 直到compositeModulus大于形参

      q = NextPrime(q, cyclotomic_order);
      numOfTower++;               // numOfTower记录有几个模数
    }
    originalModulus = modulus;      // originalModulus被设置为形参  
    DEBUGEXP(compositeModulus);
    DEBUGEXP(moduli);
    DEBUGEXP(rootsOfUnity);
    DEBUGEXP(m_parms.size());
    for (size_t i = 0; i < moduli.size(); i++) {
      m_parms.push_back(std::make_shared<ILNativeParams>(
          cyclotomic_order, moduli[i], rootsOfUnity[i]));
    }

    RecalculateModulus();
    DEBUGEXP(m_parms.size());
  }

第三个:
这个构造函数直接传入对应的四个数组,用传入的参数进行初始化。

  /**
   * @brief Constructor with some pre-computed parameters provided as input.
   * @param cyclotomic_order the order of the ciphertext
   * @param moduli the list of the smaller moduli of the component polynomials.
   * @param rootsOfUnity the list of the smaller roots of unity of the component
   * polynomials.
   * @param moduliBig the list of the big moduli of the component polynomials
   * (arbitrary cyclotomics).
   * @param rootsOfUnityBig the list of the roots of unity of the component
   * polynomials for big moduli (arbitrary cyclotomics).
   * @return
   */
  ILDCRTParams(const usint cyclotomic_order,
               const std::vector<NativeInteger> &moduli,
               const std::vector<NativeInteger> &rootsOfUnity,
               const std::vector<NativeInteger> &moduliBig = {},
               const std::vector<NativeInteger> &rootsOfUnityBig = {},
               const IntType &inputOriginalModulus = IntType(0))
      : ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0) {
    this->originalModulus = inputOriginalModulus;
    if (moduli.size() != rootsOfUnity.size()) {
      PALISADE_THROW(math_error,
                     "sizes of moduli and roots of unity do not match");
    }

    if (moduliBig.size() == moduli.size()) {	// 只有有相同元素个数的时候才设置bigModuli
      for (size_t i = 0; i < moduli.size(); i++) {
        m_parms.push_back(std::make_shared<ILNativeParams>(
            cyclotomic_order, moduli[i], rootsOfUnity[i], moduliBig[i],
            rootsOfUnityBig[i]));
      }
      RecalculateBigModulus();
    } else {
      for (size_t i = 0; i < moduli.size(); i++) {
        m_parms.push_back(std::make_shared<ILNativeParams>(
            cyclotomic_order, moduli[i], rootsOfUnity[i]));
      }
    }
    RecalculateModulus();
  }

第四个:只传入一个数组,保存模数数组,对应的单位根在ILNativeParams构造函数中计算。

  /**
   * @brief Constructor with only cylotomic order and chain of moduli.
   * Multiplied values of the chain of moduli is automatically calculated. Root
   * of unity of the modulus is also calculated.
   *
   * @param cyclotomic_order the order of the ciphertext
   * @param &moduli is the tower of moduli
   */
  ILDCRTParams(const usint cyclotomic_order,
               const std::vector<NativeInteger> &moduli,
               const IntType &inputOriginalModulus = IntType(0))
      : ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0) {
    this->originalModulus = inputOriginalModulus;

    for (size_t i = 0; i < moduli.size(); i++) {
      m_parms.push_back(std::make_shared<ILNativeParams>(cyclotomic_order,
                                                         moduli[i], 0, 0, 0));
    }
    RecalculateModulus();
  }

第五个:一步到位

  /**
   * @brief Constructor that takes in the cyclotomic order and the component
   * parameters of the component moduli.
   * @param cyclotomic_order the primary cyclotomic order.  This is not checked
   * against the component moduli.
   * @param parms the componet parameters.
   * @return
   */
  ILDCRTParams(const usint cyclotomic_order,
               std::vector<std::shared_ptr<ILNativeParams>> &parms,
               const IntType &inputOriginalModulus = IntType(0))
      : ElemParams<IntType>(cyclotomic_order, 0, 0, 0, 0), m_parms(parms) {
    this->originalModulus = inputOriginalModulus;

    RecalculateModulus();
  }

赋值操作符重载

  /**
   * Assignment Operator.
   *
   * @param &rhs the copied ILDCRTParams.
   * @return the resulting ILDCRTParams.
   */
  const ILDCRTParams &operator=(const ILDCRTParams &rhs) {
    ElemParams<IntType>::operator=(rhs);
    originalModulus = rhs.originalModulus;

    m_parms = rhs.m_parms;

    return *this;
  }

getter函数

  // ACCESSORS
  /**
   * @brief Getter method for the component parameters.
   * @return A vector of the component polynomial parameters.
   */
  const std::vector<std::shared_ptr<ILNativeParams>> &GetParams() const {
    return m_parms;
  }

返回模数的一部分

  /**
   * @brief Getter method that returns a subset of the component parameters.
   *
   * @param start The index of the first tower to include in the result.
   * @param end The index of the last tower to include.
   * @return A vector of the component polynomial parameters.
   */
  std::vector<std::shared_ptr<ILNativeParams>> GetParamPartition(
      uint32_t start, uint32_t end) const {
    if (end < start || end > this->GetParams().size()) {
      PALISADE_THROW(math_error,
                     "Incorrect parameters for GetParamPartition - (start: " +
                         std::to_string(start) +
                         ", end:" + std::to_string(end) + ")");
    }

    std::vector<std::shared_ptr<ILNativeParams>> resParams =
        std::vector<std::shared_ptr<ILNativeParams>>(end - start + 1);

    IntType q = IntType(1);
    for (uint32_t i = 0; i <= (end - start); i++) {
      resParams[i] = this->GetParams()[i + start];
      q = q.Mul(IntType(this->GetParams()[i + start]->GetModulus()));
    }

    return resParams;
  }

获取和设置originalModulus

  /**
   * @brief Simple getter method for the original modulus, not the ciphertex
   * modulus.
   * @return The original  modulus, not the big ciphertext modulus.
   */
  const IntType &GetOriginalModulus() const { return originalModulus; }
  /**
   * @brief Simple setter method for the original modulus, not the ciphertex
   * modulus.
   * @return void
   */
  void SetOriginalModulus(const IntType &inputOriginalModulus) {
    originalModulus = inputOriginalModulus;
  }

操作符重载

  /**
   * @brief Getter method for the component parameters of a specific index.
   * @param i the index of the parameters to return.  Note this this call is
   * unguarded if the index is out of bounds.
   * @return the parameters at index i.
   */
  std::shared_ptr<ILNativeParams> &operator[](const usint i) {
    return m_parms[i];
  }

去掉最后一个模数

  /**
   * @brief Removes the last parameter set and adjust the multiplied moduli.
   *
   */
  void PopLastParam() {
    this->ciphertextModulus /=
        IntType(m_parms.back()->GetModulus().ConvertToInt());
    m_parms.pop_back();
  }

析构函数

  /**
   * Destructor.
   */
  ~ILDCRTParams() {}

重载相等运算符

  /**
   * @brief Equality operator checks if the ElemParams are the same.
   *
   * @param &other ElemParams to compare against.
   * @return the equality check results.
   */
  bool operator==(const ElemParams<IntType> &other) const {
    const auto *dcrtParams = dynamic_cast<const ILDCRTParams *>(&other);

    if (dcrtParams == nullptr) return false;

    if (ElemParams<IntType>::operator==(other) == false) return false;  // 先判断父类的元素

    if (m_parms.size() != dcrtParams->m_parms.size()) return false;

    for (size_t i = 0; i < m_parms.size(); i++) {     // 再判断子类自己的元素
      if (*m_parms[i] != *dcrtParams->m_parms[i]) return false;
    }

    //    if (originalModulus != dcrtParams->originalModulus)   // originalModulus可以不同,注释掉了
    //      return false;

    return true;
  }
  /**
   * @brief Method to recalculate the composite modulus from the component
   * moduli.
   */
  void RecalculateModulus() {
    this->ciphertextModulus = 1;

    for (usint i = 0; i < m_parms.size(); i++) {
      this->ciphertextModulus =
          this->ciphertextModulus *
          IntType(m_parms[i]->GetModulus().ConvertToInt());
    }
  }

  /**
   * @brief Method to recalculate the big composite modulus from the component
   * moduli.
   */
  void RecalculateBigModulus() {
    this->bigCiphertextModulus = 1;

    for (usint i = 0; i < m_parms.size(); i++) {
      this->bigCiphertextModulus =
          this->bigCiphertextModulus *
          IntType(m_parms[i]->GetBigModulus().ConvertToInt());
    }
  }

save和load函数

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::base_class<ElemParams<IntType>>(this));
    ar(::cereal::make_nvp("p", m_parms));
    ar(::cereal::make_nvp("m", originalModulus));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::base_class<ElemParams<IntType>>(this));
    ar(::cereal::make_nvp("p", m_parms));
    ar(::cereal::make_nvp("m", originalModulus));
  }

  std::string SerializedObjectName() const { return "DCRTParams"; }
  static uint32_t SerializedVersion() { return 1; }

\core\include\lattice\elemparamfactory.h

这个类是用来生成上面参数类对象的。

#include "lattice/ildcrtparams.h"
#include "lattice/ilparams.h"
#include "math/backend.h"
#include "utils/parmfactory.h"

成员全是static

// predefined values of m are 16, 1024, 2048, 4096, 8192, 16384, 32768 and 65536

// the items in ElementOrder are an index into DefaultSet[]
enum ElementOrder { M16 = 0, M1024, M2048, M4096, M8192, M16384, M32768 };

class ElemParamFactory {
 public:
  static struct ElemParmSet {
    usint m;    // cyclotomic order
    usint n;    // ring dimension
    string q;   // ciphertext modulus
    string ru;  // root of unity
  } DefaultSet[];

返回大于等于 m m m 的最接近的 index

  static size_t GetNearestIndex(usint m) {
    size_t sIdx = 0;
    if (DefaultSet[0].m < m) {
      for (sIdx = 1; DefaultSet[sIdx].m != 0; sIdx++) {
        if (m <= DefaultSet[sIdx].m) break;
      }
    }
    if (DefaultSet[sIdx].m == 0) sIdx--;

    return sIdx;
  }

P应该就是上面三种 params 类型

  /**
   * GenElemParams for a particular predefined cyclotomic order
   *
   * @param o - the order (an ElementOrder)
   * @return new params
   */
  template <typename P>
  static shared_ptr<P> GenElemParams(ElementOrder o) {
    DEBUG_FLAG(false);
    DEBUG("in GenElemParams(ElementOrder o)");
    return std::make_shared<P>(
        DefaultSet[static_cast<int>(o)].m,
        typename P::Integer(DefaultSet[static_cast<int>(o)].q),
        typename P::Integer(DefaultSet[static_cast<int>(o)].ru));
  }
  /**
   * GenElemParams for a particular cyclotomic order - finds the predefined
   * order that's >= m
   *
   * @param m - order
   * @return new params
   */
  template <typename P>
  static shared_ptr<P> GenElemParams(usint m) {
    DEBUG_FLAG(false);
    DEBUG("in GenElemParams(usint m)");
    size_t sIdx = GetNearestIndex(m);

    return std::make_shared<P>(DefaultSet[sIdx].m,
                               typename P::Integer(DefaultSet[sIdx].q),
                               typename P::Integer(DefaultSet[sIdx].ru));
  }
  /**
   * GenElemParams for a particular cyclotomic order and bits in q
   * NOTE this is deprecated and will go away once ParamsGen is fully   注意:这已被弃用,一旦ParamsGen完全实现,它就会消失
   * implemented
   *
   * @param m - cyclotomic order
   * @param bits # of bits in q
   * @return new params
   */
  template <typename P>
  static shared_ptr<P> GenElemParams(usint m, usint bits, usint towersize = 1) {
    DEBUG_FLAG(false);
    DEBUG("in GenElemParams(usint m, usint bits, usint towers)");
    typename P::Integer q = FirstPrime<typename P::Integer>(bits, m);
    typename P::Integer ru = RootOfUnity<typename P::Integer>(m, q);
    return std::make_shared<P>(m, q, ru);
  }
  /**
   * GenElemParams given the three components directly
   *
   * @param m - cyclotomic order
   * @param ctModulus - ciphertext modulus
   * @param rootUnity - root of unity
   * @return
   */
  template <typename P>
  static shared_ptr<P> GenElemParams(usint m,
                                     const typename P::Integer& ctModulus,
                                     const typename P::Integer& rootUnity) {
    DEBUG_FLAG(false);
    DEBUG("in GenElemParams(usint m, const typename P::Integer etc)");
    return std::make_shared<P>(m, ctModulus, rootUnity);
  }
};

下面是实现
GenerateDCRTParams 是 utils/parmfactory.h 中惟一的函数。

template <>
inline shared_ptr<ILDCRTParams<M2Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M2Integer>>(usint m, usint bits,
                                                         usint towersize) {
  DEBUG_FLAG(false);
  DEBUG(
      "in GenElemParams<ILDCRTParams<M2Integer>>(usint m, usint bits, usint "
      "towersize)");
  DEBUGEXP(m);
  DEBUGEXP(bits);
  DEBUGEXP(towersize);
  return GenerateDCRTParams<M2Integer>(m, towersize, bits);
}

template <>
inline shared_ptr<ILDCRTParams<M4Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M4Integer>>(usint m, usint bits,
                                                         usint towersize) {
  DEBUG_FLAG(false);
  DEBUG(
      "in GenElemParams<ILDCRTParams<M4Integer>>(usint m, usint bits, usint "
      "towersize)");
  DEBUGEXP(m);
  DEBUGEXP(bits);
  DEBUGEXP(towersize);
  return GenerateDCRTParams<M4Integer>(m, towersize, bits);
}
#ifdef WITH_NTL
template <>
inline shared_ptr<ILDCRTParams<M6Integer>>
ElemParamFactory::GenElemParams<ILDCRTParams<M6Integer>>(usint m, usint bits,
                                                         usint towersize) {
  DEBUG_FLAG(false);
  DEBUG(
      "in GenElemParams<ILDCRTParams<M6Integer>>(usint m, usint bits, usint "
      "towersize)");
  DEBUGEXP(m);
  DEBUGEXP(bits);
  DEBUGEXP(towersize);
  return GenerateDCRTParams<M6Integer>(m, towersize, bits);
}

utils\parmfactory.h 中实现的 GererateDCRTParams函数

/**
 * Generate an ILDCRTParams with a given number of parms, with cyphertext moduli
 * of at least a given size
 * @param m - order
 * @param numOfTower - # of polynomials
 * @param pbits - number of bits in the prime, to start with
 * @return
 */
template <typename I>
inline shared_ptr<ILDCRTParams<I>> GenerateDCRTParams(usint m, usint numOfTower,
                                                      usint pbits) {
  DEBUG_FLAG(false);
  DEBUG("in GenerateDCRTParams");
  DEBUGEXP(m);
  DEBUGEXP(numOfTower);
  DEBUGEXP(pbits);
  if (numOfTower == 0) {
    PALISADE_THROW(math_error, "Can't make parms with numOfTower == 0");
  }

  std::vector<NativeInteger> moduli(numOfTower);
  std::vector<NativeInteger> rootsOfUnity(numOfTower);

  NativeInteger q = FirstPrime<NativeInteger>(pbits, m);
  I modulus(1);

  usint j = 0;
  DEBUGEXP(q);

  for (;;) {
    moduli[j] = q;
    rootsOfUnity[j] = RootOfUnity(m, q);
    modulus = modulus * I(q.ConvertToInt());
    DEBUG("j " << j << " modulus " << q << " rou " << rootsOfUnity[j]);
    if (++j == numOfTower) break;

    q = NextPrime(q, m);
  }

  auto params = std::make_shared<ILDCRTParams<I>>(m, moduli, rootsOfUnity);

  return params;
}

\core\include\lattice\stdlatticeparms.h

Header for the standard values for Lattice Parms, as determined by homomorphicencryption.org
定义了一些同态加密中用到的参数

// this is the representation of the standard lattice parameters defined in the
// Homomorphic Encryption Standard, as defined by
// http://homomorphicencryption.org

// given a distribution type and a security level, you can get the maxQ for a
// given ring dimension, and you can get the ring dimension given a maxQ

// The code below is very specific to the layout of the DistributionType and
// SecurityLevel enums IF you change them, go look at and change byRing and
// byLogQ

DistributationType

均匀分布,误差分布,三项分布

enum DistributionType {
  HEStd_uniform,
  HEStd_error,
  HEStd_ternary,
};

SecurityLevel

enum SecurityLevel {
  HEStd_128_classic,
  HEStd_192_classic,
  HEStd_256_classic,
  HEStd_NotSet,
};

inline std::ostream& operator<<(std::ostream& s, SecurityLevel sl) {
  switch (sl) {
    case HEStd_128_classic:
      s << "HEStd_128_classic";
      break;
    case HEStd_192_classic:
      s << "HEStd_192_classic";
      break;
    case HEStd_256_classic:
      s << "HEStd_256_classic";
      break;
    case HEStd_NotSet:
      s << "HEStd_NotSet";
      break;
    default:
      s << "UKNOWN";
      break;
  }
  return s;
}

StdLatticeParm 类

每个对象有四个成员(private),并且有它们对应的getter函数(public),剩下的都是public static成员,包括两个二位数组保存map,第一种map用ringDim成员索引,第二种map用maxLogQ成员索引,还有个vector保存StdLatticeParm成员,bool类型的initialized指示 这个vector成员是否被map到上面连个二维数组中。静态函数包括初始化、查找maxq和ringDim操作。

std::pair 包括两个成员 first 和 second,可以直接使用。

class    {
  DistributionType distType;
  usint ringDim;
  SecurityLevel minSecLev;
  usint maxLogQ;

  // NOTE!!! the declaration below relies upon there being three possible values
  // for the first index (the distribution type), and three possible values for
  // the second index (the security level)
  // The values in the enums, above, meet this criteria
  // it's also important that the different values are numbered from 0-2
  // again, the enums above do this
  // DO NOT change the values of the enums to be anything other than consecutive
  // numbers starting from 0, or this code will break in strange ways, and you
  // will suffer MAKE SURE that the number of entries in the DistributionType
  // enum is == the first index, and MAKE SURE that the number of entries in the
  // SecurityLevel enum is == the second index
  static map<usint, StdLatticeParm*> byRing[3][3];
  static map<usint, StdLatticeParm*> byLogQ[3][3];

  static vector<StdLatticeParm> StandardLatticeParmSets;
  static bool initialized;

 public:
  StdLatticeParm(DistributionType distType, usint ringDim,
                 SecurityLevel minSecLev, usint maxLogQ)
      : distType(distType),
        ringDim(ringDim),
        minSecLev(minSecLev),
        maxLogQ(maxLogQ) {}

  static void initializeLookups() {
    for (size_t i = 0; i < StandardLatticeParmSets.size(); i++) {
      StdLatticeParm& s = StandardLatticeParmSets[i];
      byRing[static_cast<int>(s.distType)][static_cast<int>(s.minSecLev)]
            [s.ringDim] = &s;
      byLogQ[static_cast<int>(s.distType)][static_cast<int>(s.minSecLev)]
            [s.maxLogQ] = &s;
    }
    initialized = true;
  }

  static usint FindMaxQ(DistributionType distType, SecurityLevel minSecLev,
                        usint ringDim) {
    int distTypeIdx = static_cast<int>(distType);
    int minSecLevIdx = static_cast<int>(minSecLev);
    if (!initialized) initializeLookups();
    auto it = byRing[distTypeIdx][minSecLevIdx].find(ringDim);
    if (it == byRing[distTypeIdx][minSecLevIdx].end()) return 0;
    return it->second->getMaxLogQ();
  }

  static usint FindRingDim(DistributionType distType, SecurityLevel minSecLev,
                           usint curLogQ) {
    if (!initialized) initializeLookups();
    usint prev = 0;

    int distTypeIdx = static_cast<int>(distType);
    int minSecLevIdx = static_cast<int>(minSecLev);
    for (std::pair<const unsigned int, StdLatticeParm*>& it :
         byLogQ[distTypeIdx][minSecLevIdx]) {
      if ((curLogQ <= it.second->getMaxLogQ()) && (curLogQ > prev))
        return it.second->getRingDim();
      prev = it.second->getMaxLogQ();
    }
    return 65536;
  }

  DistributionType getDistType() const { return distType; }
  usint getRingDim() const { return ringDim; }
  SecurityLevel getMinSecLev() const { return minSecLev; }
  usint getMaxLogQ() const { return maxLogQ; }
};

\core\include\lattice\ilelement.h

Represents and defines integer lattice element objects ins Palisade.

ILElement 抽象类

element 是所有纯虚函数的返回类型

/**
 * @brief Interface for ideal lattices
 *
 * Every lattice must implement these pure virtuals in order to properly
 * interoperate with PALISADE PKE. Element is the return type for all of these
 * virtual functions. There is no constructor here in the base class; it
 * contains no data to construct.
 */
template <typename Element, typename VecType>
class ILElement : public Serializable {
  using IntType = typename VecType::Integer;

public:
克隆函数:

  /**
   * @brief Clone the object by making a copy of it and returning the copy
   * @return new Element
   */
  virtual Element Clone() const = 0;

  /**
   * @brief Clone the object, but have it contain nothing
   * @return new Element
   */
  virtual Element CloneEmpty() const = 0;

  /**
   * @brief Clones the element's parameters, leaves vector initialized to 0
   * @return new Element
   */
  virtual Element CloneParametersOnly() const = 0;

  /**
   * @brief Clones the element with parameters and with noise for the vector
   * @param dgg
   * @param format
   * @return new Element
   */
  virtual Element CloneWithNoise(
      const DiscreteGaussianGeneratorImpl<VecType> &dgg,
      Format format = Format::EVALUATION) const = 0;

析构函数

  /**
   * @brief Standard destructor
   */
  virtual ~ILElement() {}

一些赋值操作符重载

  // Assignment operators
  /**
   * @brief Assignment operator that copies elements.
   * @param rhs
   */
  virtual const Element &operator=(const Element &rhs) = 0;
  /**
   * @brief Assignment operator that copies elements.
   * @param rhs
   */
  virtual const Element &operator=(Element &&rhs) = 0;
  /**
   * @brief Assignment operator that copies elements.
   * @param rhs
   */
  virtual const Element &operator=(std::initializer_list<uint64_t> rhs) = 0;

GETTER函数

  // GETTERS
  /**
   * @brief Get format of the element
   *
   * @return Format is either COEFFICIENT or EVALUATION
   */
  virtual Format GetFormat() const = 0;

  /**
   * @brief Get the length of the element.
   *
   * @return length
   */
  virtual usint GetLength() const = 0;

  /**
   * @brief Get modulus of the element
   *
   * @return the modulus.
   */
  virtual const IntType &GetModulus() const = 0;

  /**
   * @brief Get the values for the element
   *
   * @return the vector.
   */
  virtual const VecType &GetValues() const = 0;
  /**
   * @brief Get the cyclotomic order
   *
   * @return order
   */
  virtual usint GetCyclotomicOrder() const = 0;
  /**
   * @brief Gets the Value in the Element that is At Index and returns it.
   * This is only implemented for some derived classes, so the default
   * implementation throws an exception
   *
   * @param i is the index.
   * @return will throw an error.
   */
  virtual IntType &at(usint i) {
    PALISADE_THROW(not_implemented_error, "at not implemented");
  }
  virtual const IntType &at(usint i) const {
    PALISADE_THROW(not_implemented_error, "const at not implemented");
  }
  virtual IntType &operator[](usint i) {
    PALISADE_THROW(not_implemented_error, "[] not implemented");
  }
  virtual const IntType &operator[](usint i) const {
    PALISADE_THROW(not_implemented_error, "const [] not implemented");
  }
    //  virtual NativePoly DecryptionCRTInterpolate(PlaintextModulus ptm) const
  //= 0;

一些运算操作,返回的都是Element类型

  // OPERATORS
  /**
   * @brief Unary negation on a lattice		取负号操作
   * @return -lattice
   */
  virtual Element operator-() const = 0;

  /**
   * @brief Scalar addition - add an element to the first index only.	标量加法,只加到第一个索引上
   * This operation is only allowed in COEFFICIENT format.	仅在系数表示下才能用
   *
   * @param &element is the element to add entry-wise.
   * @return is the return of the addition operation.
   */
  virtual Element Plus(const IntType &element) const = 0;

  /**
   * @brief Scalar subtraction - subtract an element frp, all entries.
   *
   * @param &element is the element to subtract entry-wise.
   * @return is the return value of the minus operation.
   */
  virtual Element Minus(const IntType &element) const = 0;

  /**
   * @brief Scalar multiplication - multiply all entries.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  virtual Element Times(const IntType &element) const = 0;
    /**
   * @brief Scalar multiplication - mulltiply by a signed integer
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  virtual Element Times(
      bigintnat::NativeInteger::SignedNativeInt element) const = 0;

前面都是与一个数的运算,后面是与一个Element类型的运算

  /**
   * @brief Performs an addition operation and returns the result.
   *
   * @param &element is the element to add with.
   * @return is the result of the addition.
   */
  virtual Element Plus(const Element &element) const = 0;

  /**
   * @brief Performs a subtraction operation and returns the result.
   *
   * @param &element is the element to subtract with.
   * @return is the result of the subtraction.
   */
  virtual Element Minus(const Element &element) const = 0;

  /**
   * @brief Performs a multiplication operation and returns the result.
   *
   * @param &element is the element to multiply with.
   * @return is the result of the multiplication.
   */
  virtual Element Times(const Element &element) const = 0;

运算符重载

  // overloaded op= operators
  /**
   * @brief Performs += operation with a BigInteger and returns the result.
   *
   * @param &element is the element to add
   * @return is the result of the addition.
   */
  virtual const Element &operator+=(const IntType &element) = 0;

  /**
   * @brief Performs -= operation with a BigInteger and returns the result.
   *
   * @param &element is the element to subtract
   * @return is the result of the addition.
   */
  virtual const Element &operator-=(const IntType &element) = 0;

  /**
   * @brief Performs *= operation with a BigInteger and returns the result.
   *
   * @param &element is the element to multiply by
   * @return is the result of the multiplication.
   */
  virtual const Element &operator*=(const IntType &element) = 0;
    /**
   * @brief Performs an addition operation and returns the result.
   *
   * @param &element is the element to add
   * @return is the result of the addition.
   */
  virtual const Element &operator+=(const Element &element) = 0;

  /**
   * @brief Performs an subtraction operation and returns the result.
   *
   * @param &element is the element to subtract
   * @return is the result of the addition.
   */
  virtual const Element &operator-=(const Element &element) = 0;

  /**
   * @brief Performs an multiplication operation and returns the result.
   *
   * @param &element is the element to multiply by
   * @return is the result of the multiplication.
   */
  virtual const Element &operator*=(const Element &element) = 0;
    /**
   * @brief Equality operator.  Compares values of element to be compared to.
   * @param element the element to compare to.
   */
  virtual bool operator==(const Element &element) const = 0;

  /**
   * @brief Inequality operator.  Compares values of element to be compared to.
   * @param element the element to compare to.
   */
  inline bool operator!=(const Element &element) const {
    return !(*this == element);
  }
  /**
   * @brief Adds one to every entry of the Element, in place
   */
  virtual void AddILElementOne() = 0;

自同构操作

  /**
   * @brief Performs an automorphism transform operation and returns the result.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @return is the result of the automorphism transform.
   */
  virtual Element AutomorphismTransform(const usint &i) const = 0;

  /**
   * @brief Performs an automorphism transform operation using precomputed bit
   * reversal indices.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @param &map a vector with precomputed indices
   * @return is the result of the automorphism transform.
   */
  virtual Element AutomorphismTransform(
      usint i, const std::vector<uint32_t> &map) const = 0;

  /**
   * @brief Transpose the ring element using the automorphism operation
   *
   * @return is the result of the transposition.
   */
  virtual Element Transpose() const = 0;

基分解,用于 relinearlisation
base为 2 的幂

  /**
   * @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
   * \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
   * u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
   * {\log q/base} \rceil}} \f$; This is used as a subroutine in the
   * relinearization procedure.
   *
   * @param baseBits is the number of bits in the base, i.e., base = 2^baseBits
   * @param evalModeAnswer - if true, convert the resultant polynomials to
   * evaluation mode
   * @result is the pointer where the base decomposition vector is stored
   */
  virtual std::vector<Element> BaseDecompose(
      usint baseBits, bool evalModeAnswer = true) const = 0;

除法然后四舍五入
除以大整数 q q q

  /**
   * @brief Scalar division followed by rounding operation - operation on all
   * entries.
   *
   * @param &q is the element to divide entry-wise.
   * @return is the return value of the divide, followed by rounding operation.
   */
  virtual Element DivideAndRound(const IntType &q) const = 0;

判断是否有逆

  /**
   * @brief Determines if inverse exists
   *
   * @return true if there exists a multiplicative inverse.
   */
  virtual bool InverseExists() const = 0;

求无穷范数

  /**
   * @brief Returns the infinity norm, basically the largest value in the ring
   * element.
   *
   * @return the largest value in the ring element.
   */
  virtual double Norm() const = 0;

判断向量是否为空

  /**
   * @brief Returns true if the vector is empty/ m_values==nullptr
   *
   * @return true if the vector is empty and all values nullptr.  false
   * otherwise.
   */
  virtual bool IsEmpty() const = 0;

稀疏操作

  /**
   * @brief Make the element Sparse for SHE KeyGen operations.
   * Sets every index not equal to zero mod the wFactor to zero.
   *
   * @param &wFactor ratio between the original element's ring dimension and the
   * new ring dimension.
   */
  virtual void MakeSparse(const uint32_t &wFactor) = 0;

2 2 2 操作

  /**
   * @brief Calculate Element mod 2
   *
   * @return result of performing a mod-2 operation on the element.
   */
  virtual Element ModByTwo() const = 0;

求乘法逆


  /**
   * @brief Calculate and return the Multiplicative Inverse of the element
   * @return the multiplicative inverse of the element, if it exists.
   */
  virtual Element MultiplicativeInverse() const = 0;

乘以 p q \frac{p}{q} qp 然后四舍五入

  /**
   * @brief Scalar multiplication followed by division and rounding operation -
   * operation on all entries.
   *
   * @param &p is the integer muliplicand.
   * @param &q is the integer divisor.
   * @return is the return value of the multiply, divide and followed by
   * rounding operation.
   */
  virtual Element MultiplyAndRound(const IntType &p,
                                   const IntType &q) const = 0;

跟基分解相关联的操作,用于 relinearlisation

  /**
   * @brief Calculate a vector of elements by raising the base element to
   * successive powers
   *
   * @param baseBits
   * @return
   */
  virtual std::vector<Element> PowersOfBase(usint baseBits) const = 0;

求模操作

  /**
   * @brief Mod - perform a modulus operation.
   * Does proper mapping of [-modulus/2, modulus/2) to [0, modulus).  将从 [-modulus/2,modulus/2) 正确映射到 [0,modulus)
   *
   * @param modulus is the modulus to use.
   * @return is the return value of the modulus.
   */
  virtual Element Mod(const IntType &modulus) const = 0;

模切换

  /**
   * @brief Switch modulus and adjust the values
   *
   * @param &modulus is the modulus to be set.
   * @param &rootOfUnity is the corresponding root of unity for the modulus
   * @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
   * @param &rootOfUnityArb is the corresponding root of unity for the modulus
   * ASSUMPTION: This method assumes that the caller provides the correct
   * rootOfUnity for the modulus.
   */
  virtual void SwitchModulus(const IntType &modulus, const IntType &rootOfUnity,
                             const IntType &modulusArb = IntType::ZERO,
                             const IntType &rootOfUnityArb = IntType::ZERO) = 0;

转换格式,即在CRT和系数表示之间转换

  /**
   * @brief convert from Coefficient to CRT or vice versa; calls FFT and inverse
   * FFT.
   */
  virtual void SwitchFormat() = 0;

  /**
   * @brief Sets the format/representation of the element.
   * @param format the format/representation to set.
   */
  void SetFormat(const Format format) {
    if (this->GetFormat() != format) {
      this->SwitchFormat();
    }
  }
};

\core\include\lattice\backend.h

This file contains the functionality to switch between lattice backends

#include "lattice/elemparams.h"
#include "lattice/ildcrtparams.h"
#include "lattice/ilelement.h"
#include "lattice/ilparams.h"

#include "lattice/poly.h"

声明

namespace lbcrypto {

template <typename IntType>
class ILParamsImpl;
template <typename VecType>
class PolyImpl;
using M2Poly = PolyImpl<M2Vector>;
using M4Poly = PolyImpl<M4Vector>;
#ifdef WITH_NTL
using M6Poly = PolyImpl<M6Vector>;
#endif

using NativePoly = PolyImpl<NativeVector>;

using NativePoly64 = NativePoly;
using M2Params = ILParamsImpl<M2Integer>;
using M4Params = ILParamsImpl<M4Integer>;
#ifdef WITH_NTL
using M6Params = ILParamsImpl<M6Integer>;
#endif

using ILNativeParams = ILParamsImpl<NativeInteger>;

默认设置

// the default for the backend...
using ILParams = ILParamsImpl<BigInteger>;
using Poly = PolyImpl<BigVector>;

}  // namespace lbcrypto

下面定义与double-CRT有关

#include "lattice/dcrtpoly.h"

namespace lbcrypto {

template <typename IntType>
class ILDCRTParams;
template <typename VecType>
class DCRTPolyImpl;
using M2DCRTPoly = DCRTPolyImpl<M2Vector>;
using M4DCRTPoly = DCRTPolyImpl<M4Vector>;
#ifdef WITH_NTL
using M6DCRTPoly = DCRTPolyImpl<M6Vector>;
#endif

using M2DCRTParams = ILDCRTParams<M2Integer>;
using M4DCRTParams = ILDCRTParams<M4Integer>;
#ifdef WITH_NTL
using M6DCRTParams = ILDCRTParams<M6Integer>;
#endif

默认设置

// the default for the backend...
using DCRTPoly = DCRTPolyImpl<BigVector>;

}  // namespace lbcrypto

其他的

#ifdef WITH_NTL
#define RUN_BIG_POLYS(FUNCTION, MESSAGE) \
  {                                      \
    if (TestB2) {                        \
      using V = M2Poly;                  \
      FUNCTION<V>("BE2Poly " MESSAGE);   \
    }                                    \
    if (TestB4) {                        \
      using V = M4Poly;                  \
      FUNCTION<V>("BE4Poly " MESSAGE);   \
    }                                    \
    if (TestB6) {                        \
      using V = M6Poly;                  \
      FUNCTION<V>("BE6Poly " MESSAGE);   \
    }                                    \
  }

#define RUN_BIG_DCRTPOLYS(FUNCTION, MESSAGE) \
  {                                          \
    if (TestB2) {                            \
      using V = M2DCRTPoly;                  \
      FUNCTION<V>("BE2DCRTPoly " MESSAGE);   \
    }                                        \
    if (TestB4) {                            \
      using V = M4DCRTPoly;                  \
      FUNCTION<V>("BE4DCRTPoly " MESSAGE);   \
    }                                        \
    if (TestB6) {                            \
      using V = M6DCRTPoly;                  \
      FUNCTION<V>("BE6DCRTPoly " MESSAGE);   \
    }                                        \
  }
#else
#define RUN_BIG_POLYS(FUNCTION, MESSAGE) \
  {                                      \
    if (TestB2) {                        \
      using V = M2Poly;                  \
      FUNCTION<V>("BE2Poly " MESSAGE);   \
    }                                    \
    if (TestB4) {                        \
      using V = M4Poly;                  \
      FUNCTION<V>("BE4Poly " MESSAGE);   \
    }                                    \
  }

#define RUN_BIG_DCRTPOLYS(FUNCTION, MESSAGE) \
  {                                          \
    if (TestB2) {                            \
      using V = M2DCRTPoly;                  \
      FUNCTION<V>("BE2DCRTPoly " MESSAGE);   \
    }                                        \
    if (TestB4) {                            \
      using V = M4DCRTPoly;                  \
      FUNCTION<V>("BE4DCRTPoly " MESSAGE);   \
    }                                        \
  }
#endif

#define RUN_ALL_POLYS(FUNCTION, MESSAGE) \
  {                                      \
    RUN_BIG_POLYS(FUNCTION, MESSAGE)     \
    if (TestNative) {                    \
      using V = NativePoly;              \
      FUNCTION<V>("Native " MESSAGE);    \
    }                                    \
  }

\core\include\lattice\field2n.h

Represents and defines power-of-2 fields.

class Field2n : public std::vector<std::complex>, public Serializable

继承自vector<std::complex<double>>
private成员

 private:
  // Format of the field element
  Format format;

构造函数

public:
  /**
   * @brief Default Constructor
   */
  Field2n() : format(Format::COEFFICIENT) {}

  explicit Field2n(Format f) : format(f) {}
  /**
   * @brief Constructor for field element
   * @param size element size
   * @param f format/representation of the element.  Initially set to
   * Format::EVALUATION representation.
   * @param initializeElementToZero flag for initializing values to zero.  It is
   * set to false by default.
   */
  Field2n(int size, Format f = Format::EVALUATION,
          bool initializeElementToZero = false)
      : std::vector<std::complex<double>>(
            size,
            initializeElementToZero ? 0 : -std::numeric_limits<double>::max()) {
    this->format = f;
  }
  /**
   * @brief Constructor from ring element
   * @param & element ring element
   */
  explicit Field2n(const Poly &element);

  /**
   * @brief Constructor from ring element
   * @param & element ring element
   */
  explicit Field2n(const NativePoly &element);

  /**
   * @brief Constructor from DCRTPoly ring element
   * @param & element ring element
   */
  explicit Field2n(const DCRTPoly &element);

  /**
   * @brief Constructor from a ring element matrix
   * @param &element ring element matrix
   */
  explicit Field2n(const Matrix<int64_t> &element);

一些操作

  /**
   * @brief Method for getting the format/representation of the element
   *
   * @return format/representation of the field element
   */
  Format GetFormat() const { return format; }

  /**
   * @brief Inverse operation for the field elements
   *
   * @return the inverse field element
   */
  Field2n Inverse() const;

  /**
   * @brief Addition operation for field elements
   *
   * @param &rhs right hand side element for operation
   * @return result of the operation
   */
  Field2n Plus(const Field2n &rhs) const;

  /**
   * @brief Scalar addition operation for field elements
   *
   * @param &rhs right hand side element for operation
   * @return result of the operation
   */
  Field2n Plus(double rhs) const;

  /**
   * @brief Substraction operation for field elements
   *
   * @param &rhs right hand side element for operation
   * @return result of the operation
   */
  Field2n Minus(const Field2n &rhs) const;

  /**
   * @brief Multiplication operation for field elements
   *
   * @param &rhs right hand side element for operation
   * @return result of the operation
   */
  Field2n Times(const Field2n &rhs) const;

  /**
   * @brief Right shift operation for the field element
   *
   * @return the shifted field element
   */
  Field2n ShiftRight();

  /**
   * @brief Performs an automorphism transform operation and returns the result.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @return is the result of the automorphism transform.
   */
  Field2n AutomorphismTransform(size_t i) const;

  /**
   * @brief Transpose operation defined in section VI.B4 of
   * https://eprint.iacr.org/2017/844.pdf
   *
   * @return the transpose of the element
   */
  Field2n Transpose() const;

  /**
   * @brief Function for extracting odd factors of the field element
   *
   * @return the field element with odd parts of the initial element
   */
  Field2n ExtractOdd() const;

  /**
   * @brief Function for extracting even factors of the field element
   *
   * @return the field element with even parts of the initial element
   */
  Field2n ExtractEven() const;

  /**
   * @brief Permutation operation defined in Algorithm 4 of
   * https://eprint.iacr.org/2017/844.pdf
   *
   * @return permuted new field element
   */
  Field2n Permute() const;

  /**
   * @brief Inverse operation for permutation operation defined in
   * Algorithm 4 of https://eprint.iacr.org/2017/844.pdf
   *
   * @return non permuted version of the element
   */
  Field2n InversePermute() const;

  /**
   * @brief Operation for scalar multiplication
   *
   * @param d scalar for multiplication
   * @return the field element with the scalar multiplication
   */
  Field2n ScalarMult(double d);

  /**
   * @brief Method for switching format of the field elements
   */
  void SwitchFormat();

  /**
   * @brief Sets the evaluation or coefficient representation of the field
   * elements
   * @param &format the enum value corresponding to coefficient or evaluation
   * representation
   */
  inline void SetFormat(Format format) {
    if (this->format != format) {
      SwitchFormat();
    }
  }

  /**
   * @brief Method for getting the size of the element
   *
   * @return the size of the element
   */
  size_t Size() const { return this->size(); }

  /**
   * @brief Indexing operator for field elements
   *
   * @param idx index of the element
   * @return element at the index
   */
  inline std::complex<double> &operator[](std::size_t idx) {
    return (this->at(idx));
  }

  /**
   * @brief Indexing operator for field elements
   *
   * @param idx index of the element
   * @return element at the index
   */
  inline const std::complex<double> &operator[](std::size_t idx) const {
    return (this->at(idx));
  }

  /**
   * @brief In-place addition operation for field elements
   *
   * @param &element  right hand side element for operation
   * @return result of the operation
   */
  const Field2n &operator+=(const Field2n &element) {
    return *this = this->Plus(element);
  }

  /**
   * @brief In-place subtraction operation for field elements
   *
   * @param &element  right hand side element for operation
   * @return result of the operation
   */
  const Field2n &operator-=(const Field2n &element) {
    return *this = this->Minus(element);
  }

  /**
   * @brief Unary minus on a field element.
   * @return negation of the field element.
   */
  Field2n operator-() const {
    Field2n all0(size(), this->GetFormat(), true);
    return all0 - *this;
  }

  /**
   * @brief Substraction operator for field elements
   *
   * @param &a left hand side field element
   * @param &b right hand side field element
   * @return result of the substraction operation
   */
  friend inline Field2n operator-(const Field2n &a, const Field2n &b) {
    return a.Minus(b);
  }

  /**
   * @brief Addition operator for field elements
   *
   * @param &a left hand side field element
   * @param &b right hand side field element
   * @return result of the addition operation
   */
  friend inline Field2n operator+(const Field2n &a, const Field2n &b) {
    return a.Plus(b);
  }

  /**
   * @brief Scalar addition operator for field elements
   *
   * @param &a left hand side field element
   * @param &b  the scalar to be added
   * @return result of the addition operation
   */
  friend inline Field2n operator+(const Field2n &a, double scalar) {
    return a.Plus(scalar);
  }

  /**
   * @brief Multiplication operator for field elements
   *
   * @param &a left hand side field element
   * @param &b right hand side field element
   * @return result of the multiplication operation
   */
  friend inline Field2n operator*(const Field2n &a, const Field2n &b) {
    return a.Times(b);
  }

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
    ar(::cereal::make_nvp("f", format));
  }

save 和 load 函数

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
    ar(::cereal::make_nvp("f", format));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::base_class<std::vector<std::complex<double>>>(this));
    ar(::cereal::make_nvp("f", format));
  }

  std::string SerializedObjectName() const { return "Field2n"; }
  static uint32_t SerializedVersion() { return 1; }

 private:
  // Format of the field element
  Format format;
};
类结束
/**
 * @brief Stream output operator
 *
 * @param &os stream
 * @param &m matrix to be outputted
 * @return the chained stream
 */
inline std::ostream &operator<<(std::ostream &os, const Field2n &m) {
  os << "[ ";
  for (size_t row = 0; row < m.size(); ++row) {
    os << m.at(row) << " ";
  }
  os << " ]\n";
  return os;
}

下面两个头文件应该是核心

\core\include\lattice\poly.h

class PolyImpl : public ILElement<PolyImpl, VecType>

Ideal lattice using a vector representation

 public:
  using Integer = typename VecType::Integer;
  using Params = ILParamsImpl<Integer>;

  typedef VecType Vector;
  typedef PolyImpl<VecType> PolyType;
  typedef DiscreteGaussianGeneratorImpl<VecType> DggType;
  typedef DiscreteUniformGeneratorImpl<VecType> DugType;
  typedef TernaryUniformGeneratorImpl<VecType> TugType;
  typedef BinaryUniformGeneratorImpl<VecType> BugType;
  typedef PolyImpl<NativeVector> PolyNative;
  typedef PolyImpl<VecType> PolyLargeType;

private属性成员

 private:
  // stores either coefficient or Format::EVALUATION representation
  unique_ptr<VecType> m_values;

  // 1 for coefficient and 0 for Format::EVALUATION format
  Format m_format;

  // parameters for ideal lattices
  shared_ptr<Params> m_params;

  void ArbitrarySwitchFormat();
};
  /**
   * @brief Return the element name.
   * @return This method returns "PolyImpl".
   */
  static const std::string GetElementName() { return "PolyImpl"; }

构造函数

  /**
   * @brief Default constructor
   */
  PolyImpl();

  /**
   * @brief Construct given parameters and format
   * @param params - element parameters
   * @param format - Format::EVALUATION or COEFFICIENT
   * @param initializeElementToZero - if true, allocates  an empty vector set to
   * all 0s
   */
  PolyImpl(const shared_ptr<Params> params, Format format = Format::EVALUATION,
           bool initializeElementToZero = false);

  PolyImpl(const shared_ptr<ILDCRTParams<Integer>> params,
           Format format = Format::EVALUATION,
           bool initializeElementToZero = false);

 /**
   * @brief Construct given parameters and format
   * @param initializeElementToMax - if true, initializes entries in the vector
   * to the maximum value
   * @param params - element parameters
   * @param format - Format::EVALUATION or COEFFICIENT
   */
  PolyImpl(bool initializeElementToMax, const shared_ptr<Params> params,
           Format format);

下面是四种根据不同分布的构造函数
  /**
   * @brief Construct with a vector from a given generator
   *
   * @param &dgg the input discrete Gaussian Generator.
   * @param &params the input params.
   * @param format - Format::EVALUATION or COEFFICIENT
   */
  PolyImpl(const DggType &dgg, const shared_ptr<Params> params,
           Format format = Format::EVALUATION);

  /**
   * @brief Construct with a vector from a given generator
   *
   * @param &bug the input Binary Uniform Generator.
   * @param &params the input params.
   * @param format - Format::EVALUATION or COEFFICIENT
   */
  PolyImpl(const BugType &bug, const shared_ptr<Params> params,
           Format format = Format::EVALUATION);

  /**
   * @brief Construct with a vector from a given generator
   *
   * @param &tug the input Ternary Uniform Generator.
   * @param &params the input params.
   * @param format - Format::EVALUATION or COEFFICIENT
   * @param h - Hamming weight for sparse ternary distribution (by default, when
   * h = 0, the distribution is NOT sparse)
   */
  PolyImpl(const TugType &tug, const shared_ptr<Params> params,
           Format format = Format::EVALUATION, uint32_t h = 0);

  /**
   * @brief Construct with a vector from a given generator
   *
   * @param &dug the input discrete Uniform Generator.
   * @param &params the input params.
   * @param format - Format::EVALUATION or COEFFICIENT
   */
  PolyImpl(DugType &dug, const shared_ptr<Params> params,
           Format format = Format::EVALUATION);

C++ lambda表达式

  /**
   * @brief Create lambda that allocates a zeroed element for the case when it
   * is called from a templated class
   * @param params the params to use.
   * @param format - Format::EVALUATION or COEFFICIENT
   */
  inline static function<PolyType()> Allocator(const shared_ptr<Params> params,
                                               Format format) {
    return [=]() { return PolyType(params, format, true); };      // 返回一个函数
  }
  /**
   * @brief Allocator for discrete uniform distribution.
   *
   * @param params ILParams instance that is is passed.
   * @param resultFormat resultFormat for the polynomials generated.
   * @param stddev standard deviation for the discrete gaussian generator.
   * @return the resulting vector.
   */
  inline static function<PolyType()> MakeDiscreteGaussianCoefficientAllocator(
      shared_ptr<Params> params, Format resultFormat, double stddev) {
    return [=]() {
      DiscreteGaussianGeneratorImpl<VecType> dgg(stddev);
      PolyType ilvec(dgg, params, Format::COEFFICIENT);
      ilvec.SetFormat(resultFormat);
      return ilvec;
    };
  }

  /**
   * @brief Allocator for discrete uniform distribution.
   *
   * @param params ILParams instance that is is passed.
   * @param format format for the polynomials generated.
   * @return the resulting vector.
   */
  inline static function<PolyType()> MakeDiscreteUniformAllocator(
      shared_ptr<Params> params, Format format) {
    return [=]() {
      DiscreteUniformGeneratorImpl<VecType> dug;
      dug.SetModulus(params->GetModulus());
      return PolyType(dug, params, format);
    };
  }

拷贝构造函数

  /**
   * @brief Copy constructor.
   *
   * @param &element the copied element.
   * @param parms ILParams instance that is is passed.
   */
  PolyImpl(const PolyType &element, shared_ptr<Params> parms = 0);

  /**
   * @brief Copy constructor from a Poly of native integers.
   *
   * @param &element the copied element.
   * @param &format sets the format for the new Poly object
   */
  PolyImpl(const PolyNative &element, Format format);

  /**
   * @brief Move constructor.
   *
   * @param &&element the copied element.
   * @param parms ILParams instance that is is passed.
   */
  PolyImpl(PolyType &&element, shared_ptr<Params> parms = 0);

克隆函数

  /**
   * @brief Clone the object by making a copy of it and returning the copy
   * @return new Element
   */
  PolyType Clone() const { return PolyImpl(*this); }

  /**
   * @brief Clone the object, but have it contain nothing
   * @return new Element
   */
  PolyType CloneEmpty() const { return PolyImpl(); }

  /**
   * @brief Clone method that creates a new PolyImpl and clones only the params.
   *  The tower values are empty. The tower values can be filled by another
   * process/function or initializer list.
   * @return new Element
   */
  PolyType CloneParametersOnly() const;

  /**
   * @brief Clone method with noise.
   * Creates a new PolyImpl and clones the params. The tower values will be
   * filled up with noise based on the discrete gaussian.
   *
   * @param &dgg the input discrete Gaussian generator. The dgg will be the seed
   * to populate the towers of the PolyImpl with random numbers.
   * @return new Element
   */
  PolyType CloneWithNoise(const DiscreteGaussianGeneratorImpl<VecType> &dgg,
                          Format format) const;

析构函数

  /**
   * Destructor
   */
  ~PolyImpl();

赋值运算符重载

  /**
   * @brief Assignment Operator.
   *
   * @param &rhs the PolyImpl to be copied.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(const PolyType &rhs);

  /**
   * @brief Move Assignment.
   *
   * @param &rhs the PolyImpl to be copied.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(PolyType &&rhs);

  /**
   * @brief Initalizer list
   *
   * @param &rhs the list to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(std::initializer_list<uint64_t> rhs);

  /**
   * @brief Creates a Poly from a vector of signed integers (used for trapdoor
   * sampling)
   *
   * @param &rhs the vector to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(std::vector<int64_t> rhs);

  /**
   * @brief Creates a Poly from a vector of signed integers (used for trapdoor
   * sampling)
   *
   * @param &rhs the vector to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(std::vector<int32_t> rhs);

  /**
   * @brief Initalizer list
   *
   * @param &rhs the list to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  const PolyType &operator=(std::initializer_list<std::string> rhs);

  /**
   * @brief Assignment Operator. The usint val will be set at index zero and all
   * other indices will be set to zero.
   *
   * @param val is the usint to assign to index zero.
   * @return the resulting vector.
   */
  const PolyType &operator=(uint64_t val);

getter函数

  // GETTERS
  /**
   * @brief Get method to get ILParams for the current vector.
   *
   * @return the ring element params.
   */
  const shared_ptr<Params> GetParams() const { return m_params; }

  /**
   * @brief Get format of the element
   *
   * @return COEFFICIENT or Format::EVALUATION
   */
  Format GetFormat() const;

  /**
   * @brief Get the length of the element.
   *
   * @return length
   */
  usint GetLength() const;

  /**
   * @brief Get modulus of the element
   *
   * @return the modulus.
   */
  const Integer &GetModulus() const { return m_params->GetModulus(); }

  /**
   * @brief Get the values for the element
   *
   * @return the vector.
   */
  const VecType &GetValues() const;

 /**
   * @brief Get the cyclotomic order
   *
   * @return order
   */
  usint GetCyclotomicOrder() const { return m_params->GetCyclotomicOrder(); }

  /**
   * @brief Get the ring dimension.
   *
   * @return the ring dimension
   */
  usint GetRingDimension() const { return m_params->GetRingDimension(); }

  /**
   * @brief Get the root of unity.
   *
   * @return the root of unity.
   */
  const Integer &GetRootOfUnity() const { return m_params->GetRootOfUnity(); }

  /**
   * @brief Get value of element at index i.
   *
   * @return value at index i.
   */
  Integer &at(usint i);
  const Integer &at(usint i) const;

  /**
   * @brief Get value of element at index i.
   *
   * @return value at index i.
   */
  Integer &operator[](usint i);
  const Integer &operator[](usint i) const;

setter函数

  // SETTERS
  /**
   *  @brief Set VecType value to val
   *
   * @param index is the index at which the value is to be set.
   * @param val is the value to be set.
   */
  // SCALAR OPERATIONS

  /**
   * @brief Set method of the values.
   *
   * @param values is the set of values of the vector.
   * @param format is the format, either COEFFICIENT or EVALUATION.
   */
  void SetValues(const VecType &values, Format format);

  /**
   * @brief Set method of the values.
   *
   * @param values is the set of values of the vector.
   * @param format is the format, either COEFFICIENT or EVALUATION.
   */
  void SetValues(VecType &&values, Format format);

  /**
   * @brief Sets all values of element to zero.
   */
  void SetValuesToZero();

  /**
   * @brief Sets all values of element to maximum.
   */
  void SetValuesToMax();

标量运算

  /**
   * @brief Scalar addition - add an element to the first index only.
   * This operation is only allowed in COEFFICIENT format.
   *
   * @param &element is the element to add entry-wise.
   * @return is the return of the addition operation.
   */
  PolyImpl Plus(const Integer &element) const;

  /**
   * @brief Scalar subtraction - subtract an element to all entries.
   *
   * @param &element is the element to subtract entry-wise.
   * @return is the return value of the minus operation.
   */
  PolyImpl Minus(const Integer &element) const;

  /**
   * @brief Scalar multiplication - multiply all entries.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  PolyImpl Times(const Integer &element) const;

#if NATIVEINT != 64
  /**
   * @brief Scalar multiplication - by a signed integer.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  PolyImpl Times(int64_t element) const {
    return Times((bigintnat::NativeInteger::SignedNativeInt)element);
  }
#endif

  /**
   * @brief Scalar multiplication - by a signed integer.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  PolyImpl Times(bigintnat::NativeInteger::SignedNativeInt element) const;

向量运算

  // VECTOR OPERATIONS

  /**
   * @brief Unary minus on a lattice element.
   * @return negation of the lattice element.
   */
  PolyImpl operator-() const {      // 求负运算
    PolyImpl all0(this->GetParams(), this->GetFormat(), true);
    return all0 - *this;
  }
  /**
   * @brief Performs an addition operation and returns the result.
   *
   * @param &element is the element to add with.
   * @return is the result of the addition.
   */
  PolyImpl Plus(const PolyImpl &element) const;

  /**
   * @brief Performs a subtraction operation and returns the result.
   *
   * @param &element is the element to subtract with.
   * @return is the result of the subtraction.
   */
  PolyImpl Minus(const PolyImpl &element) const;

  /**
   * @brief Performs a multiplication operation and returns the result.
   *
   * @param &element is the element to multiply with.
   * @return is the result of the multiplication.
   */
  PolyImpl Times(const PolyImpl &element) const;

标量运算

  /**
   * @brief Performs += operation with a Integer and returns the result.
   *
   * @param &element is the element to add
   * @return is the result of the addition.
   */
  const PolyImpl &operator+=(const Integer &element) {
    return *this = this->Plus(element);
  }

  /**
   * @brief Performs -= operation with a Integer and returns the result.
   *
   * @param &element is the element to subtract
   * @return is the result of the subtraction.
   */
  const PolyImpl &operator-=(const Integer &element) {
    m_values->ModSubEq(element);
    return *this;
  }

  /**
   * @brief Performs *= operation with a Integer and returns the result.
   *
   * @param &element is the element to multiply by
   * @return is the result of the multiplication.
   */
  const PolyImpl &operator*=(const Integer &element) {
    m_values->ModMulEq(element);
    return *this;
  }

向量运算

  /**
   * @brief Performs an addition operation and returns the result.
   *
   * @param &element is the element to add
   * @return is the result of the addition.
   */
  const PolyImpl &operator+=(const PolyImpl &element);

  /**
   * @brief Performs an subtraction operation and returns the result.
   *
   * @param &element is the element to subtract
   * @return is the result of the subtract.
   */
  const PolyImpl &operator-=(const PolyImpl &element);

  /**
   * @brief Performs an multiplication operation and returns the result.
   *
   * @param &element is the element to multiply by
   * @return is the result of the multiplication.
   */
  const PolyImpl &operator*=(const PolyImpl &element);

相等运算符重载

  /**
   * @brief Equality operator compares this element to the input element.
   *
   * @param &rhs is the specified PolyImpl to be compared with this element.
   * @return true if this PolyImpl represents the same values as the specified
   * element, false otherwise
   */
  inline bool operator==(const PolyImpl &rhs) const {
    if (this->GetFormat() != rhs.GetFormat()) {
      return false;
    }
    if (m_params->GetRootOfUnity() != rhs.GetRootOfUnity()) {
      return false;
    }
    if (this->GetValues() != rhs.GetValues()) {
      return false;
    }
    return true;
  }
  /**
   * @brief Scalar multiplication followed by division and rounding operation -
   * operation on all entries.
   *
   * @param &p is the integer muliplicand.
   * @param &q is the integer divisor.
   * @return is the return value of the multiply, divide and followed by
   * rounding operation.
   */
  PolyImpl MultiplyAndRound(const Integer &p, const Integer &q) const;

  /**
   * @brief Scalar division followed by rounding operation - operation on all
   * entries.
   *
   * @param &q is the element to divide entry-wise.
   * @return is the return value of the divide, followed by rounding operation.
   */
  PolyImpl DivideAndRound(const Integer &q) const;

  /**
   * @brief Performs a negation operation and returns the result.
   *
   * @return is the result of the negation.
   */
  PolyImpl Negate() const;

其他函数

  // OTHER METHODS

  /**
   * @brief Adds one to every entry of the PolyImpl.
   */
  void AddILElementOne();

  /**
   * @brief Performs an automorphism transform operation and returns the result.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @return is the result of the automorphism transform.
   */
  PolyImpl AutomorphismTransform(const usint &k) const;

  /**
   * @brief Performs an automorphism transform operation using precomputed bit
   * reversal indices.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @param &map a vector with precomputed indices
   * @return is the result of the automorphism transform.
   */
  PolyImpl AutomorphismTransform(usint i, const std::vector<usint> &map) const;

  /**
   * @brief Interpolates based on the Chinese Remainder Transform Interpolation.
   * Does nothing for PolyImpl. Needed to support the linear CRT interpolation
   * in DCRTPoly.
   *
   * @return the original ring element.
   */
  PolyImpl CRTInterpolate() const { return *this; }

  PolyNative DecryptionCRTInterpolate(PlaintextModulus ptm) const;

  PolyNative ToNativePoly() const;

  PolyNative ToNativePolyCloneParams() const;
  /**
   * @brief Transpose the ring element using the automorphism operation
   *
   * @return is the result of the transposition.
   */
  PolyImpl Transpose() const;

  /**
   * @brief Performs a multiplicative inverse operation and returns the result.
   *
   * @return is the result of the multiplicative inverse.
   */
  PolyImpl MultiplicativeInverse() const;

  /**
   * @brief Perform a modulus by 2 operation.  Returns the least significant
   * bit.
   *
   * @return is the return value of the modulus by 2, also the least significant
   * bit.
   */
  PolyImpl ModByTwo() const;

  /**
   * @brief Modulus - perform a modulus operation. Does proper mapping of
   * [-modulus/2, modulus/2) to [0, modulus)
   *
   * @param modulus is the modulus to use.
   * @return is the return value of the modulus.
   */
  PolyImpl Mod(const Integer &modulus) const;
  /**
   * @brief Switch modulus and adjust the values
   *
   * @param &modulus is the modulus to be set.
   * @param &rootOfUnity is the corresponding root of unity for the modulus
   * @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
   * @param &rootOfUnityArb is the corresponding root of unity for the modulus
   * ASSUMPTION: This method assumes that the caller provides the correct
   * rootOfUnity for the modulus.
   */
  void SwitchModulus(const Integer &modulus, const Integer &rootOfUnity,
                     const Integer &modulusArb = Integer(0),
                     const Integer &rootOfUnityArb = Integer(0));

  /**
   * @brief Convert from Coefficient to Format::EVALUATION or vice versa; calls
   * FFT and inverse FFT.
   */
  void SwitchFormat();

  /**
   * @brief Make the element values sparse. Sets every index not equal to zero
   * mod the wFactor to zero.
   *
   * @param &wFactor ratio between the original ring dimension and the new ring
   * dimension.
   */
  void MakeSparse(const uint32_t &wFactor);

  /**
   * @brief Returns true if the vector is empty/ m_values==nullptr
   */
  bool IsEmpty() const;

  /**
   * @brief Determines if inverse exists
   *
   * @return is the Boolean representation of the existence of multiplicative
   * inverse.
   */
  bool InverseExists() const;

  /**
   * @brief Returns the infinity norm, basically the largest value in the ring
   * element.
   *
   * @return is the largest value in the ring element.
   */
  double Norm() const;

  /**
   * @brief Rounds the polynomial to an input integer.
   *
   * @param x is integer to round to.
   * @return is the result of the rounding operation.
   */
  PolyImpl Round(const Integer &x) const;

  /**
   * @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
   * \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
   * u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
   * {\log q/base} \rceil}} \f$; This is used as a subroutine in the
   * relinearization procedure.
   *
   * @param baseBits is the number of bits in the base, i.e., \f$ base =
   * 2^{baseBits} \f$.
   * @return is the pointer where the base decomposition vector is stored
   */
  std::vector<PolyImpl> BaseDecompose(usint baseBits,
                                      bool evalModeAnswer = true) const;

  /**
   * @brief Generate a vector of PolyImpl's as \f$ \left\{x, {base}*x,
   * {base}^2*x, ..., {base}^{\lfloor {\log q/{base}} \rfloor} \right\}*x \f$,
   * where \f$ x \f$ is the current PolyImpl object;
   * used as a subroutine in the relinearization procedure to get powers of a
   * certain "base" for the secret key element
   *
   * @param baseBits is the number of bits in the base, i.e., \f$ base =
   * 2^{baseBits} \f$.
   * @return is the pointer where the base decomposition vector is stored
   */
  std::vector<PolyImpl> PowersOfBase(usint baseBits) const;

  /**
   * @brief Shift entries in the vector left a specific number of entries.
   *
   * @param n the number of entries to shift left.
   * @return is the resulting vector from shifting left.
   */
  PolyImpl ShiftLeft(unsigned int n) const;

  /**
   * @brief Shift entries in the vector right a specific number of entries.
   *
   * @param n the number of entries to shift right.
   * @return is the resulting vector from shifting right.
   */
  PolyImpl ShiftRight(unsigned int n) const;

友元函数,运算符重载

  /**
   * @brief ostream operator
   * @param os the input preceding output stream
   * @param vec the element to add to the output stream.
   * @return a resulting concatenated output stream
   */
  friend inline std::ostream &operator<<(std::ostream &os,
                                         const PolyImpl &vec) {
    os << (vec.m_format == Format::EVALUATION ? "EVAL: " : "COEF: ")
       << vec.GetValues();
    return os;
  }

  /**
   * @brief Element-element addition operator.
   * @param a first element to add.
   * @param b second element to add.
   * @return the result of the addition operation.
   */
  friend inline PolyImpl operator+(const PolyImpl &a, const PolyImpl &b) {
    return a.Plus(b);
  }

  /**
   * @brief Element-integer addition operator.
   * @param a first element to add.
   * @param b integer to add.
   * @return the result of the addition operation.
   */
  friend inline PolyImpl operator+(const PolyImpl &a, const Integer &b) {
    return a.Plus(b);
  }

  /**
   * @brief Integer-element addition operator.
   * @param a integer to add.
   * @param b element to add.
   * @return the result of the addition operation.
   */
  friend inline PolyImpl operator+(const Integer &a, const PolyImpl &b) {
    return b.Plus(a);
  }

  /**
   * @brief Element-element subtraction operator.
   * @param a element to subtract from.
   * @param b element to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline PolyImpl operator-(const PolyImpl &a, const PolyImpl &b) {
    return a.Minus(b);
  }

  /**
   * @brief Element-integer subtraction operator.
   * @param a element to subtract from.
   * @param b integer to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline PolyImpl operator-(const PolyImpl &a, const Integer &b) {
    return a.Minus(b);
  }

  /**
   * @brief Element-element multiplication operator.
   * @param a element to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline PolyImpl operator*(const PolyImpl &a, const PolyImpl &b) {
    return a.Times(b);
  }

  /**
   * @brief Element-integer multiplication operator.
   * @param a element to multiply.
   * @param b integer to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline PolyImpl operator*(const PolyImpl &a, const Integer &b) {
    return a.Times(b);
  }

  /**
   * @brief Integer-element multiplication operator.
   * @param a integer to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline PolyImpl operator*(const Integer &a, const PolyImpl &b) {
    return b.Times(a);
  }

  /**
   * @brief Element-signed-integer multiplication operator.
   * @param a element to multiply.
   * @param b integer to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline PolyImpl operator*(const PolyImpl &a, int64_t b) {
    return a.Times((bigintnat::NativeInteger::SignedNativeInt)b);
  }

  /**
   * @brief signed-integer-element multiplication operator.
   * @param a integer to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline PolyImpl operator*(int64_t a, const PolyImpl &b) {
    return b.Times((bigintnat::NativeInteger::SignedNativeInt)a);
  }
  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_values));
    ar(::cereal::make_nvp("f", m_format));
    ar(::cereal::make_nvp("p", m_params));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_values));
    ar(::cereal::make_nvp("f", m_format));
    ar(::cereal::make_nvp("p", m_params));
  }

  std::string SerializedObjectName() const { return "Poly"; }
  static uint32_t SerializedVersion() { return 1; }

类外函数

template <>
inline PolyImpl<NativeVector> PolyImpl<NativeVector>::DecryptionCRTInterpolate(
    PlaintextModulus ptm) const {
  return this->Mod(ptm);
}

// biginteger version
template <>
inline PolyImpl<NativeVector> PolyImpl<BigVector>::ToNativePolyCloneParams()
    const {
  PolyImpl<NativeVector> interp(
      std::make_shared<ILParamsImpl<NativeInteger>>(
          this->GetCyclotomicOrder(), this->GetModulus().ConvertToInt(),
          this->GetRootOfUnity().ConvertToInt()),
      this->GetFormat(), true);

  for (usint i = 0; i < this->GetLength(); i++) {
    interp[i] = (*this)[i].ConvertToInt();
  }

  return interp;
}

// native poly version
template <>
inline PolyImpl<NativeVector> PolyImpl<NativeVector>::ToNativePolyCloneParams()
    const {
  return *this;
}

\core\include\lattice\dcrtpoly.h

Represents integer lattice elements with double-CRT

class DCRTPolyImpl : public ILElement<DCRTPolyImpl<VecType>, VecType>

#include "math/backend.h"
#include "utils/inttypes.h"

#include "utils/exception.h"

#include "lattice/elemparams.h"
#include "lattice/ildcrtparams.h"
#include "lattice/ilelement.h"
#include "lattice/ilparams.h"
#include "lattice/poly.h"
#include "math/distrgen.h"
/**
 * @brief Ideal lattice for the double-CRT representation.
 * The implementation contains a vector of underlying native-integer lattices
 * The double-CRT representation of polynomials is a common optimization for
 * lattice encryption operations. Basically, it allows large-modulus polynomials
 * to be represented as multiple smaller-modulus polynomials.  The double-CRT
 * representations are discussed theoretically here:
 *   - Gentry C., Halevi S., Smart N.P. (2012) Homomorphic Evaluation of the AES
 * Circuit. In: Safavi-Naini R., Canetti R. (eds) Advances in Cryptology –
 * CRYPTO 2012. Lecture Notes in Computer Science, vol 7417. Springer, Berlin,
 * Heidelberg
 */
private成员
 private:
  shared_ptr<Params> m_params;

  // array of vectors used for double-CRT presentation
  std::vector<PolyType> m_vectors;

  // Either Format::EVALUATION (0) or Format::COEFFICIENT (1)
  Format m_format;
};
}  // namespace lbcrypto
template <typename VecType>
class DCRTPolyImpl : public ILElement<DCRTPolyImpl<VecType>, VecType> {
 public:
  using Integer = typename VecType::Integer;
  using Params = ILDCRTParams<Integer>;

  typedef VecType Vector;

  typedef DCRTPolyImpl<VecType> DCRTPolyType;
  typedef DiscreteGaussianGeneratorImpl<NativeVector> DggType;
  typedef DiscreteUniformGeneratorImpl<NativeVector> DugType;
  typedef TernaryUniformGeneratorImpl<NativeVector> TugType;
  typedef BinaryUniformGeneratorImpl<NativeVector> BugType;

  // this class contains an array of these:
  using PolyType = PolyImpl<NativeVector>;

  // the composed polynomial type
  typedef PolyImpl<VecType> PolyLargeType;

  static const std::string GetElementName() { return "DCRTPolyImpl"; }

构造函数

  // CONSTRUCTORS

  /**
   * @brief Constructor that initialized m_format to EVALUATION and calls
   * m_params to nothing
   */
  DCRTPolyImpl();

  /**
   * Constructor that initializes parameters.
   *
   *@param params parameter set required for DCRTPoly.
   *@param format the input format fixed to EVALUATION. Format is a enum type
   *that indicates if the polynomial is in Evaluation representation or
   *Coefficient representation. It is defined in inttypes.h.
   *@param initializeElementToZero
   */
  DCRTPolyImpl(const shared_ptr<Params> params, Format format = EVALUATION,
               bool initializeElementToZero = false);

  const DCRTPolyType &operator=(const PolyLargeType &element);

  const DCRTPolyType &operator=(const NativePoly &element);

根据四种分布的构造函数

  /**
   * @brief Constructor based on discrete Gaussian generator.
   *
   * @param &dgg the input discrete Gaussian generator. The dgg will be the seed
   * to populate the towers of the DCRTPoly with random numbers.
   * @param params parameter set required for DCRTPoly.
   * @param format the input format fixed to EVALUATION. Format is a enum type    // 固定是EVALUATION format
   * that indicates if the polynomial is in Evaluation representation or
   * Coefficient representation. It is defined in inttypes.h.
   */
  DCRTPolyImpl(const DggType &dgg, const shared_ptr<Params> params,
               Format format = EVALUATION);

  /**
   * @brief Constructor based on binary distribution generator. This is not
   * implemented. Will throw an error.
   *
   * @param &bug the input binary uniform generator. The bug will be the seed to
   * populate the towers of the DCRTPoly with random numbers.
   * @param params parameter set required for DCRTPoly.
   * @param format the input format fixed to EVALUATION. Format is a enum type
   * that indicates if the polynomial is in Evaluation representation or
   * Coefficient representation. It is defined in inttypes.h.
   */
  DCRTPolyImpl(const BugType &bug, const shared_ptr<Params> params,
               Format format = EVALUATION);

  /**
   * @brief Constructor based on ternary distribution generator.
   *
   * @param &tug the input ternary uniform generator. The bug will be the seed
   * to populate the towers of the DCRTPoly with random numbers.
   * @param params parameter set required for DCRTPoly.
   * @param format the input format fixed to EVALUATION. Format is a enum type
   * that indicates if the polynomial is in Evaluation representation or
   * Coefficient representation. It is defined in inttypes.h.
   * @param h - Hamming weight for sparse ternary distribution (by default, when
   * h = 0, the distribution is NOT sparse)
   */
  DCRTPolyImpl(const TugType &tug, const shared_ptr<Params> params,
               Format format = EVALUATION, uint32_t h = 0);

  /**
   * @brief Constructor based on discrete uniform generator.
   *
   * @param &dug the input discrete Uniform Generator.
   * @param params the input params.
   * @param &format the input format fixed to EVALUATION. Format is a enum type
   * that indicates if the polynomial is in Evaluation representation or
   * Coefficient representation. It is defined in inttypes.h.
   */
  DCRTPolyImpl(DugType &dug, const shared_ptr<Params> params,
               Format format = EVALUATION);
  /**
   * @brief Construct using a single Poly. The Poly is copied into every tower.
   * Each tower will be reduced to it's corresponding modulus  via GetModuli(at
   * tower index). The format is derived from the passed in Poly.
   *
   * @param &element Poly to build other towers from.
   * @param params parameter set required for DCRTPoly.
   */
  DCRTPolyImpl(const PolyLargeType &element, const shared_ptr<Params> params);

  /**
   * @brief Construct using a single NativePoly. The NativePoly is copied into
   * every tower. Each tower will be reduced to it's corresponding modulus  via
   * GetModuli(at tower index). The format is derived from the passed in
   * NativePoly.
   *
   * @param &element Poly to build other towers from.
   * @param params parameter set required for DCRTPoly.
   */
  DCRTPolyImpl(const NativePoly &element, const shared_ptr<Params> params);

  /**
   * @brief Construct using an tower of ILVectro2ns. The params and format for
   * the DCRTPoly will be derived from the towers.
   *
   * @param &towers vector of Polys which correspond to each tower of DCRTPoly.
   */
  explicit DCRTPolyImpl(const std::vector<PolyType> &elements);
  /**
   * @brief Create lambda that allocates a zeroed element for the case when it
   * is called from a templated class
   * @param params the params to use.
   * @param format - EVALUATION or COEFFICIENT
   */
  inline static function<DCRTPolyType()> Allocator(
      const shared_ptr<Params> params, Format format) {
    return [=]() { return DCRTPolyType(params, format, true); };
  }

  /**
   * @brief Allocator for discrete uniform distribution.
   *
   * @param params Params instance that is is passed.
   * @param resultFormat resultFormat for the polynomials generated.
   * @param stddev standard deviation for the discrete gaussian generator.
   * @return the resulting vector.
   */
  inline static function<DCRTPolyType()>
  MakeDiscreteGaussianCoefficientAllocator(shared_ptr<Params> params,
                                           Format resultFormat, double stddev) {
    return [=]() {
      DggType dgg(stddev);
      DCRTPolyType ilvec(dgg, params, COEFFICIENT);
      ilvec.SetFormat(resultFormat);
      return ilvec;
    };
  }

  /**
   * @brief Allocator for discrete uniform distribution.
   *
   * @param params Params instance that is is passed.
   * @param format format for the polynomials generated.
   * @return the resulting vector.
   */
  inline static function<DCRTPolyType()> MakeDiscreteUniformAllocator(
      shared_ptr<Params> params, Format format) {
    return [=]() {
      DugType dug;
      return DCRTPolyType(dug, params, format);
    };
  }
  /**
   * @brief Copy constructor.
   *
   * @param &element DCRTPoly to copy from
   */
  DCRTPolyImpl(const DCRTPolyType &element);

  /**
   * @brief Move constructor.
   *
   * @param &&element DCRTPoly to move from
   */
  explicit DCRTPolyImpl(const DCRTPolyType &&element);
  // CLONE OPERATIONS
  /**
   * @brief Clone the object by making a copy of it and returning the copy
   * @return new Element
   */
  DCRTPolyType Clone() const { return DCRTPolyImpl(*this); }

  /**
   * @brief Makes a copy of the DCRTPoly, but it includes only a sequential
   * subset of the towers that the original holds.
   *
   * @param startTower The index number of the first tower to clone
   * @param endTower The index number of the last tower to clone
   * @return new Element
   */
  DCRTPolyType CloneTowers(uint32_t startTower, uint32_t endTower) const {
    vector<NativeInteger> moduli(endTower - startTower + 1);
    vector<NativeInteger> roots(endTower - startTower + 1);

    for (uint32_t i = startTower; i <= endTower; i++) {
      moduli[i - startTower] = this->GetParams()->GetParams()[i]->GetModulus();
      roots[i - startTower] =
          this->GetParams()->GetParams()[i]->GetRootOfUnity();
    }

    auto params = DCRTPolyImpl::Params(this->GetCyclotomicOrder(), moduli,
                                       roots, {}, {}, 0);

    auto res =
        DCRTPolyImpl(std::make_shared<typename DCRTPolyImpl::Params>(params),
                     EVALUATION, false);

    for (uint32_t i = startTower; i <= endTower; i++) {
      res.SetElementAtIndex(i - startTower, this->GetElementAtIndex(i));
    }

    return res;
  }
  /**
   * @brief Clone the object, but have it contain nothing
   * @return new Element
   */
  DCRTPolyType CloneEmpty() const { return DCRTPolyImpl(); }

  /**
   * @brief Clone method creates a new DCRTPoly and clones only the params. The
   * tower values are empty. The tower values can be filled by another
   * process/function or initializer list.
   */
  DCRTPolyType CloneParametersOnly() const;

  /**
   * @brief Clone with noise.  This method creates a new DCRTPoly and clones the
   * params. The tower values will be filled up with noise based on the discrete
   * gaussian.
   *
   * @param &dgg the input discrete Gaussian generator. The dgg will be the seed
   * to populate the towers of the DCRTPoly with random numbers.
   * @param format the input format fixed to EVALUATION. Format is a enum type
   * that indicates if the polynomial is in Evaluation representation or
   * Coefficient representation. It is defined in inttypes.h.
   */
  DCRTPolyType CloneWithNoise(const DiscreteGaussianGeneratorImpl<VecType> &dgg,
                              Format format = EVALUATION) const;

  /**
   * @brief Destructor.
   */
  ~DCRTPolyImpl();

getter函数

  // GETTERS

  /**
   * @brief returns the parameters of the element.
   * @return the element parameter set.
   */
  const shared_ptr<Params> GetParams() const { return m_params; }

  /**
   * @brief returns the element's cyclotomic order
   * @return returns the cyclotomic order of the element.
   */
  usint GetCyclotomicOrder() const { return m_params->GetCyclotomicOrder(); }

  /**
   * @brief returns the element's ring dimension
   * @return returns the ring dimension of the element.
   */
  usint GetRingDimension() const { return m_params->GetRingDimension(); }

  /**
   * @brief returns the element's modulus
   * @return returns the modulus of the element.
   */
  const Integer &GetModulus() const { return m_params->GetModulus(); }

  /**
   * @brief returns the element's original modulus, derived from Poly

   * @return returns the modulus of the element.
   */
  const Integer &GetOriginalModulus() const {
    return m_params->GetOriginalModulus();
  }

  /**
   * @brief returns the element's root of unity.
   * @return the element's root of unity.
   */
  const Integer &GetRootOfUnity() const {
    static Integer t(0);
    return t;
  }

  /**
   * @brief Get method for length of each component element.
   * NOTE assumes all components are the same size.
   *
   * @return length of the component element
   */
  usint GetLength() const {
    if (m_vectors.size() == 0) return 0;

    return m_vectors[0].GetValues().GetLength();
  }
  /**
   * @brief Get interpolated value of elements at all tower index i.
   * Note this operation is computationally intense.      // 注意,这个操作需要大量的计算。
   * @return interpolated value at index i.
   */
  Integer &at(usint i);
  const Integer &at(usint i) const;

  /**
   * @brief Get interpolated value of element at index i.
   * Note this operation is computationally intense.
   * @return interpolated value at index i.
   */
  Integer &operator[](usint i);
  const Integer &operator[](usint i) const;
  /**
   * @brief Get method of individual tower of elements.
   * Note this behavior is different than poly
   * @param i index of tower to be returned.
   * @returns a reference to the returned tower
   */
  const PolyType &GetElementAtIndex(usint i) const;

  /**
   * @brief Get method of the number of component elements, also known as the
   * number of towers.
   *
   * @return the number of component elements.
   */
  usint GetNumOfElements() const;

  /**
   * @brief Get method that returns a vector of all component elements.
   *
   * @returns a vector of the component elements.
   */
  const std::vector<PolyType> &GetAllElements() const;

  /**
   * @brief Get method of the format.
   *
   * @return the format, either COEFFICIENT or EVALUATION
   */
  Format GetFormat() const;
  /**
   * @brief Write the element as \f$ \sum\limits{i=0}^{\lfloor {\log q/base}
   * \rfloor} {(base^i u_i)} \f$ and return the vector of \f$ \left\{u_0,
   * u_1,...,u_{\lfloor {\log q/base} \rfloor} \right\} \in R_{{base}^{\lceil
   * {\log q/base} \rceil}} \f$; This is used as a subroutine in the
   * relinearization procedure.
   *
   * @param baseBits is the number of bits in the base, i.e., \f$ base =
   * 2^{baseBits} \f$.
   * @return is the pointer where the base decomposition vector is stored
   */
  std::vector<DCRTPolyType> BaseDecompose(usint baseBits,
                                          bool evalModeAnswer = true) const;

  /**
   * @brief Generate a vector of PolyImpl's as \f$ \left\{x, {base}*x,
   * {base}^2*x, ..., {base}^{\lfloor {\log q/{base}} \rfloor} \right\}*x \f$,
   * where \f$ x \f$ is the current PolyImpl object;
   * used as a subroutine in the relinearization procedure to get powers of a
   * certain "base" for the secret key element.
   *
   * @param baseBits is the number of bits in the base, i.e., \f$ base =
   * 2^{baseBits} \f$.
   * @return is the pointer where the base decomposition vector is stored
   */
  std::vector<DCRTPolyType> PowersOfBase(usint baseBits) const;

  /**
   * CRT basis decomposition of c as [c qi/q]_qi
   *
   * @param &baseBits bits in the base for additional digit decomposition if
   * base > 0
   * @return is the pointer where the resulting vector is stored
   */
  std::vector<DCRTPolyType> CRTDecompose(uint32_t baseBits = 0) const;

向量运算

  // VECTOR OPERATIONS

  /**
   * @brief Assignment Operator.
   *
   * @param &rhs the copied element.
   * @return the resulting element.
   */
  const DCRTPolyType &operator=(const DCRTPolyType &rhs);

  /**
   * @brief Move Assignment Operator.
   *
   * @param &rhs the copied element.
   * @return the resulting element.
   */
  const DCRTPolyType &operator=(DCRTPolyType &&rhs);

  /**
   * @brief Initalizer list
   *
   * @param &rhs the list to initalized the element.
   * @return the resulting element.
   */
  DCRTPolyType &operator=(std::initializer_list<uint64_t> rhs);

  /**
   * @brief Assignment Operator. The usint val will be set at index zero and all
   * other indices will be set to zero.
   *
   * @param val is the usint to assign to index zero.
   * @return the resulting vector.
   */
  DCRTPolyType &operator=(uint64_t val);

  /**
   * @brief Creates a Poly from a vector of signed integers (used for trapdoor
   * sampling)
   *
   * @param &rhs the vector to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  DCRTPolyType &operator=(const std::vector<int64_t> &rhs);

  /**
   * @brief Creates a Poly from a vector of signed integers (used for trapdoor
   * sampling)
   *
   * @param &rhs the vector to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */
  DCRTPolyType &operator=(const std::vector<int32_t> &rhs);

  /**
   * @brief Initalizer list
   *
   * @param &rhs the list to set the PolyImpl to.
   * @return the resulting PolyImpl.
   */

  DCRTPolyType &operator=(std::initializer_list<std::string> rhs);
  /**
   * @brief Unary minus on a element.
   * @return additive inverse of the an element.
   */
  DCRTPolyType operator-() const {
    DCRTPolyType all0(this->GetParams(), this->GetFormat(), true);
    return all0 - *this;
  }

  /**
   * @brief Equality operator.
   *
   * @param &rhs is the specified element to be compared with this element.
   * @return true if this element represents the same values as the specified
   * element, false otherwise
   */
  bool operator==(const DCRTPolyType &rhs) const;

  /**
   * @brief Performs an entry-wise addition over all elements of each tower with
   * the towers of the element on the right hand side.
   *
   * @param &rhs is the element to add with.
   * @return is the result of the addition.
   */
  const DCRTPolyType &operator+=(const DCRTPolyType &rhs);

  /**
   * @brief Performs an entry-wise subtraction over all elements of each tower
   * with the towers of the element on the right hand side.
   *
   * @param &rhs is the element to subtract from.
   * @return is the result of the addition.
   */
  const DCRTPolyType &operator-=(const DCRTPolyType &rhs);
  /**
   * @brief Permutes coefficients in a polynomial. Moves the ith index to the
   * first one, it only supports odd indices.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @return is the result of the automorphism transform.
   */
  DCRTPolyType AutomorphismTransform(const usint &i) const {
    DCRTPolyType result(*this);
    for (usint k = 0; k < m_vectors.size(); k++) {
      result.m_vectors[k] = m_vectors[k].AutomorphismTransform(i);
    }
    return result;
  }

  /**
   * @brief Performs an automorphism transform operation using precomputed bit
   * reversal indices.
   *
   * @param &i is the element to perform the automorphism transform with.
   * @param &map a vector with precomputed indices
   * @return is the result of the automorphism transform.
   */
  DCRTPolyType AutomorphismTransform(usint i,
                                     const std::vector<usint> &map) const {
    DCRTPolyType result(*this);
    for (usint k = 0; k < m_vectors.size(); k++) {
      result.m_vectors[k] = m_vectors[k].AutomorphismTransform(i, map);
    }
    return result;
  }

  /**
   * @brief Transpose the ring element using the automorphism operation
   *
   * @return is the result of the transposition.
   */
  DCRTPolyType Transpose() const {
    if (m_format == COEFFICIENT) {
      PALISADE_THROW(not_implemented_error,
                     "DCRTPolyImpl element transposition is currently "
                     "implemented only in the Evaluation representation.");
    } else {
      usint m = m_params->GetCyclotomicOrder();
      return AutomorphismTransform(m - 1);
    }
  }
  /**
   * @brief Performs an addition operation and returns the result.
   *
   * @param &element is the element to add with.
   * @return is the result of the addition.
   */
  DCRTPolyType Plus(const DCRTPolyType &element) const;

  /**
   * @brief Performs a multiplication operation and returns the result.
   *
   * @param &element is the element to multiply with.
   * @return is the result of the multiplication.
   */
  DCRTPolyType Times(const DCRTPolyType &element) const;

  /**
   * @brief Performs a subtraction operation and returns the result.
   *
   * @param &element is the element to subtract from.
   * @return is the result of the subtraction.
   */
  DCRTPolyType Minus(const DCRTPolyType &element) const;

标量运算

  // SCALAR OPERATIONS

  /**
   * @brief Scalar addition - add an element to the first index of each tower.
   *
   * @param &element is the element to add entry-wise.
   * @return is the result of the addition operation.
   */
  DCRTPolyType Plus(const Integer &element) const;

  /**
   * @brief Scalar addition for elements in CRT format.
   * CRT elements are represented as vector of integer elements which
   * correspond to the represented number modulo the primes in the
   * tower chain (in same order).
   *
   * @param &element is the element to add entry-wise.
   * @return is the result of the addition operation.
   */
  DCRTPolyType Plus(const vector<Integer> &element) const;

  /**
   * @brief Scalar subtraction - subtract an element to all entries.
   *
   * @param &element is the element to subtract entry-wise.
   * @return is the return value of the minus operation.
   */
  DCRTPolyType Minus(const Integer &element) const;

  /**
   * @brief Scalar subtraction for elements in CRT format.
   * CRT elements are represented as vector of integer elements which
   * correspond to the represented number modulo the primes in the
   * tower chain (in same order).
   *
   * @param &element is the element to subtract entry-wise.
   * @return is the result of the subtraction operation.
   */
  DCRTPolyType Minus(const vector<Integer> &element) const;

  /**
   * @brief Scalar multiplication - multiply all entries.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  DCRTPolyType Times(const Integer &element) const;

  /**
   * @brief Scalar multiplication - multiply by a signed integer
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  DCRTPolyType Times(bigintnat::NativeInteger::SignedNativeInt element) const;

#if NATIVEINT != 64
  /**
   * @brief Scalar multiplication - multiply by a signed integer
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  DCRTPolyType Times(int64_t element) const {
    return Times((bigintnat::NativeInteger::SignedNativeInt)element);
  }
#endif

  /**
   * @brief Scalar multiplication by an integer represented in CRT Basis.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  DCRTPolyType Times(const std::vector<NativeInteger> &element) const;

  /**
   * @brief Scalar modular multiplication by an integer represented in CRT
   * Basis.
   *
   * @param &element is the element to multiply entry-wise.
   * @return is the return value of the times operation.
   */
  DCRTPolyType Times(const std::vector<Integer> &element) const;

  /**
   * @brief Scalar multiplication followed by division and rounding operation -
   * operation on all entries.
   *
   * @param &p is the element to multiply entry-wise.
   * @param &q is the element to divide entry-wise.
   * @return is the return value of the multiply, divide and followed by
   * rounding operation.
   */
  DCRTPolyType MultiplyAndRound(const Integer &p, const Integer &q) const;

  /**
   * @brief Scalar division followed by rounding operation - operation on all
   * entries.
   *
   * @param &q is the element to divide entry-wise.
   * @return is the return value of the divide, followed by rounding operation.
   */
  DCRTPolyType DivideAndRound(const Integer &q) const;

  /**
   * @brief Performs a negation operation and returns the result.
   *
   * @return is the result of the negation.
   */
  DCRTPolyType Negate() const;

  const DCRTPolyType &operator+=(const Integer &element) {
    for (usint i = 0; i < this->GetNumOfElements(); i++) {
      this->m_vectors[i] +=
          (element.Mod(this->m_vectors[i].GetModulus())).ConvertToInt();
    }
    return *this;
  }

  /**
   * @brief Performs a subtraction operation and returns the result.
   *
   * @param &element is the element to subtract from.
   * @return is the result of the subtraction.
   */
  const DCRTPolyType &operator-=(const Integer &element) {
    for (usint i = 0; i < this->GetNumOfElements(); i++) {
      this->m_vectors[i] -=
          (element.Mod(this->m_vectors[i].GetModulus())).ConvertToInt();
    }
    return *this;
  }

  /**
   * @brief Performs a multiplication operation and returns the result.
   *
   * @param &element is the element to multiply by.
   * @return is the result of the multiplication.
   */
  const DCRTPolyType &operator*=(const Integer &element);

  /**
   * @brief Performs an multiplication operation and returns the result.
   *
   * @param &element is the element to multiply with.
   * @return is the result of the multiplication.
   */
  const DCRTPolyType &operator*=(const DCRTPolyType &element);

  /**
   * @brief Get value of element at index i.
   *
   * @return value at index i.
   */
  PolyType &ElementAtIndex(usint i);

  // multiplicative inverse operation
  /**
   * @brief Performs a multiplicative inverse operation and returns the result.
   *
   * @return is the result of the multiplicative inverse.
   */
  DCRTPolyType MultiplicativeInverse() const;

  /**
   * @brief Perform a modulus by 2 operation.  Returns the least significant
   * bit.
   *
   * @return is the resulting value.
   */
  DCRTPolyType ModByTwo() const;

  /**
   * @brief Modulus - perform a modulus operation. Does proper mapping of
   * [-modulus/2, modulus/2) to [0, modulus)
   *
   * @param modulus is the modulus to use.
   * @return is the return value of the modulus.
   */
  DCRTPolyType Mod(const Integer &modulus) const {
    PALISADE_THROW(not_implemented_error,
                   "Mod of an Integer not implemented on DCRTPoly");
  }
  // OTHER FUNCTIONS AND UTILITIES

  /**
   * @brief Get method that should not be used
   *
   * @return will throw an error.
   */
  const VecType &GetValues() const {
    PALISADE_THROW(not_implemented_error,
                   "GetValues not implemented on DCRTPoly");
  }

  /**
   * @brief Set method that should not be used, will throw an error.
   *
   * @param &values
   * @param format
   */
  void SetValues(const VecType &values, Format format) {
    PALISADE_THROW(not_implemented_error,
                   "SetValues not implemented on DCRTPoly");
  }

  /**
   * @brief Sets element at index
   *
   * @param index where the element should be set
   * @param element The element to store
   */
  void SetElementAtIndex(usint index, const PolyType &element) {
    m_vectors[index] = element;
  }

  /**
   * @brief Sets element at index
   *
   * @param index where the element should be set
   * @param element The element to store
   */
  void SetElementAtIndex(usint index, PolyType &&element) {
    m_vectors[index] = std::move(element);
  }

  /**
   * @brief Sets all values of element to zero.
   */
  void SetValuesToZero();

  /**
   * @brief Adds "1" to every entry in every tower.
   */
  void AddILElementOne();

  /**
   * @brief Add uniformly random values to all components except for the first
   * one
   */
  DCRTPolyType AddRandomNoise(const Integer &modulus) const {
    PALISADE_THROW(not_implemented_error,
                   "AddRandomNoise is not currently implemented for DCRTPoly");
  }

  /**
   * @brief Make DCRTPoly Sparse. Sets every index of each tower not equal to
   * zero mod the wFactor to zero.
   *
   * @param &wFactor ratio between the sparse and none-sparse values.
   */
  void MakeSparse(const uint32_t &wFactor);

  /**
   * @brief Returns true if ALL the tower(s) are empty.
   * @return true if all towers are empty
   */
  bool IsEmpty() const;

  /**
   * @brief Drops the last element in the double-CRT representation. The
   * resulting DCRTPoly element will have one less tower.
   */
  void DropLastElement();

  /**
   * @brief Drops the last i elements in the double-CRT representation.
   */
  void DropLastElements(size_t i);

  /**
   * @brief Drops the last element in the double-CRT representation and scales
   * down by the last CRT modulus. The resulting DCRTPoly element will have one
   * less tower.
   * @param &QlQlInvModqlDivqlModq precomputed values for
   * [Q^(l)*[Q^(l)^{-1}]_{q_l}/q_l]_{q_i}
   * @param &QlQlInvModqlDivqlModqPrecon NTL-specific precomputations
   * @param &qlInvModq precomputed values for [q_l^{-1}]_{q_i}
   * @param &qlInvModqPrecon NTL-specific precomputations
   */
  void DropLastElementAndScale(
      const std::vector<NativeInteger> &QlQlInvModqlDivqlModq,
      const std::vector<NativeInteger> &QlQlInvModqlDivqlModqPrecon,
      const std::vector<NativeInteger> &qlInvModq,
      const std::vector<NativeInteger> &qlInvModqPrecon);

  /**
   * @brief ModReduces reduces the DCRTPoly element's composite modulus by
   * dropping the last modulus from the chain of moduli as well as dropping the
   * last tower.
   *
   * @param &t is the plaintextModulus used for the DCRTPoly
   * @param &tModqPrecon NTL-specific precomputations for [t]_{q_i}
   * @param &negtInvModq precomputed values for [-t^{-1}]_{q_i}
   * @param &negtInvModqPrecon NTL-specific precomputations for [-t^{-1}]_{q_i}
   * @param &qlInvModq precomputed values for [q_{l}^{-1}]_{q_i}
   * @param &qlInvModqPrecon NTL-specific precomputations for [q_{l}^{-1}]_{q_i}
   */
  void ModReduce(const NativeInteger &t,
                 const std::vector<NativeInteger> &tModqPrecon,
                 const NativeInteger &negtInvModq,
                 const NativeInteger &negtInvModqPrecon,
                 const std::vector<NativeInteger> &qlInvModq,
                 const std::vector<NativeInteger> &qlInvModqPrecon);

  /**
   * @brief Interpolates the DCRTPoly to an Poly based on the Chinese Remainder
   * Transform Interpolation. and then returns a Poly with that single element
   *
   * @return the interpolated ring element as a Poly object.
   */
  PolyLargeType CRTInterpolate() const;

  PolyType DecryptionCRTInterpolate(PlaintextModulus ptm) const;

  NativePoly ToNativePoly() const;

  /**
   * @brief Interpolates the DCRTPoly to an Poly based on the Chinese Remainder
   * Transform Interpolation, only at element index i, all other elements are
   * zero. and then returns a Poly with that single element
   *
   * @return the interpolated ring element as a Poly object.
   */
  PolyLargeType CRTInterpolateIndex(usint i) const;

  /**
   * @brief Computes and returns the product of primes in the current moduli
   * chain. Compared to GetModulus, which always returns the product of all
   * primes in the crypto parameters, this method will return a different
   * modulus, based on the towers/moduli that are currently in the chain (some
   * towers are dropped along the way).
   *
   * @return the product of moduli in the current towers.
   */
  BigInteger GetWorkingModulus() const;

  /**
   * @brief Returns the element parameters for DCRTPoly elements in an extended
   * CRT basis, which is the concatenation of the towers currently in "this"
   * DCRTPoly, and the moduli in ParamsP.
   *
   * @return element parameters of the extended basis.
   */
  shared_ptr<Params> GetExtendedCRTBasis(std::shared_ptr<Params> paramsP) const;
论文中RNS操作
  /**
   * @brief Performs approximate CRT basis switching:
   * {X}_{Q} -> {X'}_{P}
   * X' = X + alpha*Q for small alpha
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * [X']_{p_j} = [\sum_i([x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)]_{p_j}
   *
   * Source: "A full RNS variant of approximate homomorphic encryption" by
   * Cheon, et. al.
   *
   * @param &paramsQ parameters for the CRT basis {q_1,...,q_l}
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &QHatinvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
   * @param &QHatinvModqPrecon NTL-specific precomputations
   * @param &QHatModp precomputed values for [Q/q_i]_{p_j}
   * @param &modpBarrettMu 128-bit Barrett reduction precomputed values
   * @return the representation of {X + alpha*Q} in basis {P}.
   */
  DCRTPolyType ApproxSwitchCRTBasis(
      const std::shared_ptr<Params> paramsQ,
      const std::shared_ptr<Params> paramsP,
      const std::vector<NativeInteger> &QHatInvModq,
      const std::vector<NativeInteger> &QHatInvModqPrecon,
      const std::vector<std::vector<NativeInteger>> &QHatModp,
      const std::vector<DoubleNativeInt> &modpBarrettMu) const;

  /**
   * @brief Performs approximate modulus raising:
   * {X}_{Q} -> {X'}_{Q,P}.
   * X' = X + alpha*Q for small alpha
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * {X}_{Q} -> {X'}_Q : trivial
   * {X}_{Q} -> {X'}_P : use DCRTPoly::ApproxSwitchCRTBasis
   *
   * Source: "A full RNS variant of approximate homomorphic encryption" by
   * Cheon, et. al.
   *
   * @param &paramsQ parameters for the CRT basis {q_1,...,q_l}
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &QHatInvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
   * @param &QHatInvModqPrecon NTL-specific precomputations
   * @param &QHatModp precomputed values for [Q/q_i]_{p_j}
   * @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
   * p_j
   * @return the representation of {X + alpha*Q} in basis {Q,P}.
   */
  void ApproxModUp(const shared_ptr<Params> paramsQ,
                   const shared_ptr<Params> paramsP,
                   const shared_ptr<Params> paramsQP,
                   const vector<NativeInteger> &QHatInvModq,
                   const vector<NativeInteger> &QHatInvModqPrecon,
                   const vector<vector<NativeInteger>> &QHatModp,
                   const vector<DoubleNativeInt> &modpBarrettMu);

  /**
   * @brief Performs approximate modulus reduction:
   * {X}_{Q,P} -> {\approx(X/P)}_{Q}.
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * 1) use DCRTPoly::ApproxSwitchCRTBasis : {X}_{P} -> {X'}_{Q}
   * 2) compute : {(X-X') * P^{-1}}_{Q}
   *
   * Source: "A full RNS variant of approximate homomorphic encryption" by
   * Cheon, et. al.
   *
   * @param &paramsQ parameters for the CRT basis {q_1,...,q_l}
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &PInvModq precomputed values for (P^{-1} mod q_j)
   * @param &PInvModqPrecon NTL-specific precomputations
   * @param &PHatInvModp precomputed values for [(P/p_j)^{-1}]_{p_j}
   * @param &PHatInvModpPrecon NTL-specific precomputations
   * @param &PHatModq precomputed values for [P/p_j]_{q_i}
   * @param &modqBarrettMu 128-bit Barrett reduction precomputed values for
   * q_i
   * @param &tInvModp precomputed values for [t^{-1}]_{p_j}
   * used in BGVrns
   * @param t often corresponds to the plaintext modulus
   * used in BGVrns
   * @return the representation of {\approx(X/P)}_{Q}
   */
  DCRTPolyType ApproxModDown(
      const shared_ptr<Params> paramsQ, const shared_ptr<Params> paramsP,
      const vector<NativeInteger> &PInvModq,
      const vector<NativeInteger> &PInvModqPrecon,
      const vector<NativeInteger> &PHatInvModp,
      const vector<NativeInteger> &PHatInvModpPrecon,
      const vector<vector<NativeInteger>> &PHatModq,
      const vector<DoubleNativeInt> &modqBarrettMu,
      const vector<NativeInteger> &tInvModp = vector<NativeInteger>(),
      const vector<NativeInteger> &tInvModpPrecon = vector<NativeInteger>(),
      const NativeInteger &t = 0,
      const vector<NativeInteger> &tModqPrecon = vector<NativeInteger>()) const;

  /**
   * @brief Performs CRT basis switching:
   * {X}_{Q} -> {X}_{P}
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * 1) X=\sum_i[x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)-alpha*Q
   * 2) compute round[[x_i*(Q/q_i)^{-1}]_{q_i} / q_i] to find alpha
   * 3) [X]_{p_j}=[\sum_i[x_i*(Q/q_i)^{-1}]_{q_i}*(Q/q_i)]_{p_j}-[alpha*Q]_{p_j}
   *
   * Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
   * BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
   * 2018/117. (https://eprint.iacr.org/2018/117)
   *
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &QHatInvModq precomputed values for [(Q/q_i)^{-1}]_{q_i}
   * @param &QHatInvModqPrecon NTL-specific precomputations
   * @param &QHatModp precomputed values for [Q/q_i]_{p_j}
   * @param &alphaQModp precomputed values for [alpha*Q]_{p_j}
   * @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
   * p_j
   * @params &qInv precomputed values for 1/q_i
   * @return the representation of {X}_{P}
   */
  DCRTPolyType SwitchCRTBasis(
      const shared_ptr<Params> paramsP,
      const std::vector<NativeInteger> &QHatInvModq,
      const std::vector<NativeInteger> &QHatInvModqPrecon,
      const std::vector<std::vector<NativeInteger>> &QHatModp,
      const std::vector<std::vector<NativeInteger>> &alphaQModp,
      const std::vector<DoubleNativeInt> &modpBarrettMu,
      const std::vector<double> &qInv) const;

  /**
   * @brief Performs modulus raising:
   * {X}_{Q} -> {X}_{Q,P}
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * {X}_{Q} -> {X}_P : use DCRTPoly::SwitchCRTBasis
   * combine {X}_{Q} and {X}_{P}
   * Outputs the resulting polynomial in CRT/RNS
   *
   * Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
   * BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
   * 2018/117. (https://eprint.iacr.org/2018/117)
   *
   * @param &paramsQP parameters for the CRT basis {q_1,...,q_l,p_1,...,p_k}
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &QHatInvModq precomputed values for [QInv_i]_{q_i}
   * @param &QHatInvModqPrecon NTL-specific precomputations
   * @param &QHatModp precomputed values for [QHat_i]_{p_j}
   * @param &alphaQModp precomputed values for [alpha*Q]_{p_j}
   * @param &modpBarrettMu 128-bit Barrett reduction precomputed values for
   * p_j
   * @params &qInv precomputed values for 1/q_i
   * @param resultFormat Specifies the format we want the result to be in
   *
   */
  void ExpandCRTBasis(const shared_ptr<Params> paramsQP,
                      const shared_ptr<Params> paramsP,
                      const std::vector<NativeInteger> &QHatInvModq,
                      const std::vector<NativeInteger> &QHatInvModqPrecon,
                      const std::vector<std::vector<NativeInteger>> &QHatModp,
                      const std::vector<std::vector<NativeInteger>> &alphaQModp,
                      const std::vector<DoubleNativeInt> &modpBarrettMu,
                      const std::vector<double> &qInv,
                      Format resultFormat = EVALUATION);

  /**
   * @brief Performs scale and round:
   * {X}_{Q} -> {\round(t/Q*X)}_t
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * [\sum_i x_i*[t*QHatInv_i/q_i]_t + Round(\sum_i x_i*{t*QHatInv_i/q_i})]_t
   *
   * Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
   * BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
   * 2018/117. (https://eprint.iacr.org/2018/117)
   *
   * @param &t often corresponds to the plaintext modulus
   * @param &tQHatInvModqDivqModt precomputed values for
   * [Floor{t*QHatInv_i/q_i}]_t
   * @param &tQHatInvModqDivqModtPrecon NTL-specific precomputations
   * @param &tQHatInvModqBDivqModt precomputed values for
   * [Floor{t*QHatInv_i*B/q_i}]_t used when CRT moduli are 45..60 bits long
   * @param &tQHatInvBDivqModtPrecon NTL-specific precomputations
   * used when CRT moduli are 45..60 bits long
   * @param &tQHatInvModqDivqFrac precomputed values for Frac{t*QHatInv_i/q_i}
   * @param &tQHatInvBDivqFrac precomputed values for Frac{t*QHatInv_i*B/q_i}
   * used when CRT moduli are 45..60 bits long
   * @return the result of computation as a polynomial with native 64-bit
   * coefficients
   */
  PolyType ScaleAndRound(
      const NativeInteger &t,
      const std::vector<NativeInteger> &tQHatInvModqDivqModt,
      const std::vector<NativeInteger> &tQHatInvModqDivqModtPrecon,
      const std::vector<NativeInteger> &tQHatInvModqBDivqModt,
      const std::vector<NativeInteger> &tQHatInvModqBDivqModtPrecon,
      const std::vector<double> &tQHatInvModqDivqFrac,
      const std::vector<double> &tQHatInvModqBDivqFrac) const;

  /**
   * @brief Computes approximate scale and round:
   * {X}_{Q,P} -> {\approx{t/Q * X}}_{P}
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * Let S = {Q,P}
   * 1) [\sum_k x_k * alpha_k]_{p_j}
   * 2) alpha_k = [Floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
   *
   * Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
   * BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
   * 2018/117. (https://eprint.iacr.org/2018/117)
   *
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &tPSHatInvModsDivsModp precomputed values for
   * [\floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
   * @param &modpBarretMu 128-bit Barrett reduction precomputed values for
   * p_j
   * @return the result {\approx{t/Q * X}}_{P}
   */
  DCRTPolyType ApproxScaleAndRound(
      const shared_ptr<Params> paramsP,
      const std::vector<std::vector<NativeInteger>> &tPSHatInvModsDivsModp,
      const std::vector<DoubleNativeInt> &modpBarretMu) const;

  /**
   * @brief Computes scale and round:
   * {X}_{Q,P} -> {t/Q * X}_{P}
   * {Q} = {q_1,...,q_l}
   * {P} = {p_1,...,p_k}
   *
   * Brief algorithm:
   * Let S = {Q,P}
   * 1) [\sum_k x_k * alpha_k + Round(\sum_k beta_k * x_k)]_{p_j}
   * 2) alpha_k = [Floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
   * 3) beta_k = {t*P*[[SHatInv_k]_{s_k}/s_k}
   *
   * Source: Halevi S., Polyakov Y., and Shoup V. An Improved RNS Variant of the
   * BFV Homomorphic Encryption Scheme. Cryptology ePrint Archive, Report
   * 2018/117. (https://eprint.iacr.org/2018/117)
   *
   * @param &paramsP parameters for the CRT basis {p_1,...,p_k}
   * @param &tPSHatInvModsDivsModp precomputed values for
   * [\floor[t*P*[[SHatInv_k]_{s_k}/s_k]]_{p_j}
   * @param &tPSHatInvModsDivsFrac precomputed values for
   * {t*P*[[SHatInv_k]_{s_k}/s_k}
   * @param &modpBarretMu 128-bit Barrett reduction precomputed values for
   * p_j
   * @return the result {t/Q * X}_{P}
   */
  DCRTPolyType ScaleAndRound(
      const shared_ptr<Params> paramsP,
      const std::vector<std::vector<NativeInteger>> &tPSHatInvModsDivsModp,
      const std::vector<double> &tPSHatInvModsDivsFrac,
      const std::vector<DoubleNativeInt> &modpBarretMu) const;

  /**
   * @brief Computes scale and round for fast rounding:
   * {X}_{Q} -> {\round(t/Q * X)}_t
   * {Q} = {q_1,...,q_l}
   *
   * Brief algorithm:
   *
   * Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
   * Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
   * Schemes. Cryptology ePrint Archive: Report 2016/510.
   * (https://eprint.iacr.org/2016/510)
   *
   * @param &moduliQ moduli {q_1,...,q_l}
   * @param &t often corresponds to the plaintext modulus
   * @param &tgamma t * gamma : t * 2^26 reduction
   * @param &tgammaQHatModq [t*gamma*(Q/q_i)]_{q_i}
   * @param &tgammaQHatModqPrecon NTL-specific precomputations
   * @param &negInvqModtgamma [-q^{-1}]_{t*gamma}
   * @param &negInvqModtgammaPrecon NTL-specific precomputations
   * @return
   */
  PolyType ScaleAndRound(
      const std::vector<NativeInteger> &moduliQ, const NativeInteger &t,
      const NativeInteger &tgamma,
      const std::vector<NativeInteger> &tgammaQHatModq,
      const std::vector<NativeInteger> &tgammaQHatModqPrecon,
      const std::vector<NativeInteger> &negInvqModtgamma,
      const std::vector<NativeInteger> &negInvqModtgammaPrecon) const;

  /**
   * @brief Expands basis:
   * {X}_{Q} -> {X}_{Q,Bsk,mtilde}
   * mtilde is a redundant modulus used to remove q overflows generated from
   * fast conversion. Outputs the resulting polynomial in CRT/RNS
   * {Q} = {q_1,...,q_l}
   * {Bsk} = {bsk_1,...,bsk_k}
   *
   *
   * Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
   * Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
   * Schemes. Cryptology ePrint Archive: Report 2016/510.
   * (https://eprint.iacr.org/2016/510)
   *
   * @param paramsBsk: container of Bsk moduli and roots on unity
   * @param &moduliQ: basis {Q} = {q_1,q_2,...,q_l}
   * @param &moduliBsk: basis {Bsk U mtilde} ...
   * @param &modbskBarrettMu: 128-bit Barrett reduction precomputed values for
   * bsk_j
   * @param &mtildeQHatInvModq: [mtilde*(Q/q_i)^{-1}]_{q_i}
   * @param &mtildeQHatInvModqPrecon NTL-specific precomputations
   * @param &QHatModbsk: [Q/q_i]_{bsk_j}
   * @param &QHatModmtilde: [Q/q_i]_{mtilde}
   * @param &QModbsk: [Q]_{bsk_j}
   * @param &QModbskPrecon NTL-specific precomputations
   * @param &negQInvModmtilde: [-Q^{-1}]_{mtilde}
   * @param &mtildeInvModbsk: [mtilde^{-1}]_{bsk_j}
   * @param &mtildeInvModbskPrecon NTL-specific precomputations
   */
  void FastBaseConvqToBskMontgomery(
      const shared_ptr<Params> paramsBsk,
      const std::vector<NativeInteger> &moduliQ,
      const std::vector<NativeInteger> &moduliBsk,
      const std::vector<DoubleNativeInt> &modbskBarrettMu,
      const std::vector<NativeInteger> &mtildeQHatInvModq,
      const std::vector<NativeInteger> &mtildeQHatInvModqPrecon,
      const std::vector<std::vector<NativeInteger>> &QHatModbsk,
      const std::vector<uint16_t> &QHatModmtilde,
      const std::vector<NativeInteger> &QModbsk,
      const std::vector<NativeInteger> &QModbskPrecon,
      const uint16_t &negQInvModmtilde,
      const std::vector<NativeInteger> &mtildeInvModbsk,
      const std::vector<NativeInteger> &mtildeInvModbskPrecon);

  /**
   * @brief Computes scale and floor:
   * {X}_{Q,Bsk} -> {\floor{t/Q * X}}_{Bsk}
   * {Q} = {q_1,...,q_l}
   * {Bsk} = {bsk_1,...,bsk_k}
   * Outputs the resulting polynomial in CRT/RNS
   *
   * Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
   * Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
   * Schemes. Cryptology ePrint Archive: Report 2016/510.
   * (https://eprint.iacr.org/2016/510)
   *
   * @param &t: plaintext modulus
   * @param &moduliQ: {Q} = {q_1,...,q_l}
   * @param &moduliBsk: {Bsk} = {bsk_1,...,bsk_k}
   * @param &modbskBarrettMu: 128-bit Barrett reduction precomputed values for
   * bsk_j
   * @param &tQHatInvModq: [(Q/q_i)^{-1}]_{q_i}
   * @param &tQHatInvModqPrecon: NTL-specific precomputations
   * @param &QHatModbsk: [Q/q_i]_{bsk_i}
   * @param &qInvModbsk: [(q_i)^{-1}]_{bsk_j}
   * @param &tQInvModbsk: [t*Q^{-1}]_{bsk_j}
   * @param &tQInvModbskPrecon: NTL-specific precomputations
   */
  void FastRNSFloorq(const NativeInteger &t,
                     const std::vector<NativeInteger> &moduliQ,
                     const std::vector<NativeInteger> &moduliBsk,
                     const std::vector<DoubleNativeInt> &modbskBarrettMu,
                     const std::vector<NativeInteger> &tQHatInvModq,
                     const std::vector<NativeInteger> &tQHatInvModqPrecon,
                     const std::vector<std::vector<NativeInteger>> &QHatModbsk,
                     const std::vector<std::vector<NativeInteger>> &qInvModbsk,
                     const std::vector<NativeInteger> &tQInvModbsk,
                     const std::vector<NativeInteger> &tQInvModbskPrecon);

  /**
   * @brief @brief Converts basis:
   * {X}_{Q,Bsk} -> {X}_{Bsk}
   * {Q} = {q_1,...,q_l}
   * {Bsk} = {bsk_1,...,bsk_k}
   * using Shenoy Kumaresan method.
   * Outputs the resulting polynomial in CRT/RNS
   *
   * Source: Jean-Claude Bajard and Julien Eynard and Anwar Hasan and Vincent
   * Zucca. A Full RNS Variant of FV like Somewhat Homomorphic Encryption
   * Schemes. Cryptology ePrint Archive: Report 2016/510.
   * (https://eprint.iacr.org/2016/510)
   *
   * Note in the source paper, B is referred to by M.
   *
   * @param &moduliQ: basis Q = {q_1,...,q_l}
   * @param &modqBarrettMu precomputed Barrett Mu for q_i
   * @param &moduliBsk: basis {Bsk} = {bsk_1,...,bsk_k}
   * @param &modbskBarrettMu: precomputed Barrett Mu for bsk_j
   * @param &BHatInvModb: [(B/b_j)^{-1}]_{b_j}
   * @param &BHatInvModbPrecon NTL precomptations for [(B/b_j)^{-1}]_{b_j}
   * @param &BHatModmsk: [B/b_j]_{msk}
   * @param &BInvModmsk: [B^{-1}]_{msk}
   * @param &BInvModmskPrecon NTL precomptation for [B^{-1}]_{msk}
   * @param &BHatModq: [B/b_j]_{q_i}
   * @param &BModq: [B]_{q_i}
   * @param &BModqPrecon NTL precomptations for [B]_{q_i}
   */
  void FastBaseConvSK(const std::vector<NativeInteger> &moduliQ,
                      const std::vector<DoubleNativeInt> &modqBarrettMu,
                      const std::vector<NativeInteger> &moduliBsk,
                      const std::vector<DoubleNativeInt> &modbskBarrettMu,
                      const std::vector<NativeInteger> &BHatInvModb,
                      const std::vector<NativeInteger> &BHatInvModbPrecon,
                      const std::vector<NativeInteger> &BHatModmsk,
                      const NativeInteger &BInvModmsk,
                      const NativeInteger &BInvModmskPrecon,
                      const std::vector<std::vector<NativeInteger>> &BHatModq,
                      const std::vector<NativeInteger> &BModq,
                      const std::vector<NativeInteger> &BModqPrecon);
  /**
   * @brief Convert from Coefficient to CRT or vice versa; calls FFT and inverse
   * FFT.
   */
  void SwitchFormat();

  /**
   * @brief Switch modulus and adjust the values
   *
   * @param &modulus is the modulus to be set
   * @param &rootOfUnity is the corresponding root of unity for the modulus
   * @param &modulusArb is the modulus used for arbitrary cyclotomics CRT
   * @param &rootOfUnityArb is the corresponding root of unity for the modulus
   * ASSUMPTION: This method assumes that the caller provides the correct
   * rootOfUnity for the modulus
   */
  void SwitchModulus(const Integer &modulus, const Integer &rootOfUnity,
                     const Integer &modulusArb = Integer(0),
                     const Integer &rootOfUnityArb = Integer(0)) {
    PALISADE_THROW(not_implemented_error,
                   "SwitchModulus not implemented on DCRTPoly");
  }

  /**
   * @brief Switch modulus at tower i and adjust the values
   *
   * @param index is the index for the tower
   * @param &modulus is the modulus to be set
   * @param &rootOfUnity is the corresponding root of unity for the modulus
   * ASSUMPTION: This method assumes that the caller provides the correct
   * rootOfUnity for the modulus
   */
  void SwitchModulusAtIndex(usint index, const Integer &modulus,
                            const Integer &rootOfUnity);

  /**
   * @brief Determines if inverse exists
   *
   * @return is the Boolean representation of the existence of multiplicative
   * inverse.
   */
  bool InverseExists() const;

  /**
   * @brief Returns the infinity norm, basically the largest value in the ring
   * element.
   *
   * @return is the largest value in the ring element.
   */
  double Norm() const;

  /**
   * @brief ostream operator
   * @param os the input preceding output stream
   * @param vec the element to add to the output stream.
   * @return a resulting concatenated output stream
   */
  friend inline std::ostream &operator<<(std::ostream &os,
                                         const DCRTPolyType &vec) {
    // os << (vec.m_format == EVALUATION ? "EVAL: " : "COEF: ");
    for (usint i = 0; i < vec.GetAllElements().size(); i++) {
      if (i != 0) os << std::endl;
      os << i << ": ";
      os << vec.GetAllElements()[i];
    }
    return os;
  }
  /**
   * @brief Element-element addition operator.
   * @param a first element to add.
   * @param b second element to add.
   * @return the result of the addition operation.
   */
  friend inline DCRTPolyType operator+(const DCRTPolyType &a,
                                       const DCRTPolyType &b) {
    return a.Plus(b);
  }
  /**
   * @brief Element-integer addition operator.
   * @param a first element to add.
   * @param b integer to add.
   * @return the result of the addition operation.
   */
  friend inline DCRTPolyType operator+(const DCRTPolyType &a,
                                       const Integer &b) {
    return a.Plus(b);
  }

  /**
   * @brief Integer-element addition operator.
   * @param a integer to add.
   * @param b element to add.
   * @return the result of the addition operation.
   */
  friend inline DCRTPolyType operator+(const Integer &a,
                                       const DCRTPolyType &b) {
    return b.Plus(a);
  }

  /**
   * @brief Element-integer addition operator with CRT integer.
   * @param a first element to add.
   * @param b integer to add.
   * @return the result of the addition operation.
   */
  friend inline DCRTPolyType operator+(const DCRTPolyType &a,
                                       const vector<Integer> &b) {
    return a.Plus(b);
  }

  /**
   * @brief Integer-element addition operator with CRT integer.
   * @param a integer to add.
   * @param b element to add.
   * @return the result of the addition operation.
   */
  friend inline DCRTPolyType operator+(const vector<Integer> &a,
                                       const DCRTPolyType &b) {
    return b.Plus(a);
  }

  /**
   * @brief Element-element subtraction operator.
   * @param a element to subtract from.
   * @param b element to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline DCRTPolyType operator-(const DCRTPolyType &a,
                                       const DCRTPolyType &b) {
    return a.Minus(b);
  }

  /**
   * @brief Element-integer subtraction operator with CRT integer.
   * @param a first element to subtract.
   * @param b integer to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline DCRTPolyType operator-(const DCRTPolyType &a,
                                       const vector<Integer> &b) {
    return a.Minus(b);
  }

  /**
   * @brief Integer-element subtraction operator with CRT integer.
   * @param a integer to subtract.
   * @param b element to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline DCRTPolyType operator-(const vector<Integer> &a,
                                       const DCRTPolyType &b) {
    return b.Minus(a);
  }

  /**
   * @brief Element-integer subtraction operator.
   * @param a element to subtract from.
   * @param b integer to subtract.
   * @return the result of the subtraction operation.
   */
  friend inline DCRTPolyType operator-(const DCRTPolyType &a,
                                       const Integer &b) {
    return a.Minus(b);
  }

  /**
   * @brief Element-element multiplication operator.
   * @param a element to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(const DCRTPolyType &a,
                                       const DCRTPolyType &b) {
    return a.Times(b);
  }

  /**
   * @brief Element-integer multiplication operator.
   * @param a element to multiply.
   * @param b integer to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(const DCRTPolyType &a,
                                       const Integer &b) {
    return a.Times(b);
  }

  /**
   * @brief Element-CRT number multiplication operator.
   * @param a element to multiply.
   * @param b integer to multiply, in CRT format.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(const DCRTPolyType &a,
                                       const vector<Integer> &b) {
    return a.Times(b);
  }

  /**
   * @brief Integer-element multiplication operator.
   * @param a integer to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(const Integer &a,
                                       const DCRTPolyType &b) {
    return b.Times(a);
  }

  /**
   * @brief Element-signed-integer multiplication operator.
   * @param a element to multiply.
   * @param b integer to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(const DCRTPolyType &a, int64_t b) {
    return a.Times((bigintnat::NativeInteger::SignedNativeInt)b);
  }

  /**
   * @brief signed-Integer-element multiplication operator.
   * @param a integer to multiply.
   * @param b element to multiply.
   * @return the result of the multiplication operation.
   */
  friend inline DCRTPolyType operator*(int64_t a, const DCRTPolyType &b) {
    return b.Times((bigintnat::NativeInteger::SignedNativeInt)a);
  }

save和load

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_vectors));
    ar(::cereal::make_nvp("f", m_format));
    ar(::cereal::make_nvp("p", m_params));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_vectors));
    ar(::cereal::make_nvp("f", m_format));
    ar(::cereal::make_nvp("p", m_params));
  }

  std::string SerializedObjectName() const { return "DCRTPoly"; }
  static uint32_t SerializedVersion() { return 1; }

namespace lbcrypto {

typedef DCRTPolyImpl<BigVector> DCRTPoly;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值