Palisade math biginteger headers

Palisade math biginteger headers

\core\include\math\bigintnat\ubintnat.h

This file contains the main class for native integers.
It implements the same methods as other mathematical backends.

#ifndef LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H
#define LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H

#include <cstdlib>
#include <fstream>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <vector>

#include "math/interface.h"
#include "math/nbtheory.h"
#include "utils/debug.h"
#include "utils/exception.h"
#include "utils/inttypes.h"
#include "utils/memory.h"
#include "utils/palisadebase64.h"
#include "utils/serializable.h"

// the default behavior of the native integer layer is
// to assume that the user does not need bounds/range checks
// in the native integer code
// if you want them, change this #define to true
// we use a #define to resolve which to use at compile time
// sadly, making the choice according to some setting that
// is checked at runtime has awful performance; using this
// #define in a simple expression causes the compiler to
// optimize away the test
#define NATIVEINT_DO_CHECKS false

using U32BITS = uint32_t;
using U64BITS = uint64_t;
#if defined(HAVE_INT128)
using U128BITS = unsigned __int128;
#endif

常量引用详解
定义了一堆DoubleDataType的实现:包含两倍比特长度的数据和有符号的数据。

namespace bigintnat {

const double LOG2_10 =
    3.32192809;  //!< @brief A pre-computed  constant of Log base 2 of 10.

const usint BARRETT_LEVELS = 8;  //!< @brief The number of levels (precomputed
                                 //!< values) used in the Barrett reductions.

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type void for default case
 *
 * @tparam utype primitive integer data type.
 */
template <typename utype>
struct DoubleDataType {
  using DoubleType = void;
  using SignedType = void;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 64 bit if integral datatype is 32bit
 */
template <>
struct DoubleDataType<uint32_t> {
  using DoubleType = uint64_t;
  using SignedType = int32_t;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 128 bit if integral datatype is 64bit
 */
template <>
struct DoubleDataType<uint64_t> {
#if defined(HAVE_INT128)
  using DoubleType = __uint128_t;
#else
  using DoubleType = uint64_t;
#endif
  using SignedType = int64_t;
};

#if defined(HAVE_INT128)
template <>
struct DoubleDataType<unsigned __int128> {
  using DoubleType = __uint128_t;
  using SignedType = __int128;
};
#endif

NativeIntegerT类

struct typeD

为NativeIntegerT中的public成员,将一个double-word数表示为两个single-word数。

  // a data structure to represent a double-word integer as two single-word
  // integers
  struct typeD {
    NativeInt hi = 0;
    NativeInt lo = 0;
    inline std::string ConvertToString() {
      std::string ret("hi [");
      ret += toString(hi);
      ret += "], lo [";
      ret += toString(lo);
      ret += "]";
      return ret;
    }
  };
/**
 * @brief Main class for big integers represented as an array of native
 * (primitive) unsigned integers
 * @tparam NativeInt native unsigned integer type
 */
template <typename NativeInt>
class NativeIntegerT
    : public lbcrypto::BigIntegerInterface<NativeIntegerT<NativeInt>> {   // 位于\core\include\math\interface.h
 public:
  using Integer = NativeInt;
  using DNativeInt = typename DoubleDataType<NativeInt>::DoubleType;    // 取决于 NativeInt类型,但都是无符号的
  using SignedNativeInt = typename DoubleDataType<NativeInt>::SignedType;
一堆构造函数
  /// CONSTRUCTORS

  /**
   * Default constructor.
   */
  NativeIntegerT() : m_value(0) {}

  /**
   * Copy constructor.
   *
   * @param &val is the native integer to be copied.
   */
  NativeIntegerT(const NativeIntegerT &val) : m_value(val.m_value) {}

  /**
   * Move constructor.
   *
   * @param &&val is the native integer to be copied.
   */
  NativeIntegerT(const NativeIntegerT &&val)
      : m_value(std::move(val.m_value)) {}

  /**
   * Constructor from a string.
   *
   * @param &strval is the initial integer represented as a string.
   */
  NativeIntegerT(const std::string &strval) { AssignVal(strval); }

  /**
   * Constructor from an unsigned integer.
   *
   * @param &val is the initial integer represented as a NativeInt.
   */
  NativeIntegerT(NativeInt val) : m_value(val) {}

  /**
   * Constructors from smaller basic types
   * @param init
   */
  template <typename T = NativeInt>
  NativeIntegerT(int16_t init,
                 typename std::enable_if<!std::is_same<T, int16_t>::value,  // enable_if的主要作用就是当某个condition成立时,enable_if可以提供某种类型。std::is_name:https://blog.csdn.net/chengyq116/article/details/119431341
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(uint16_t init,
                 typename std::enable_if<!std::is_same<T, uint16_t>::value,
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(int32_t init,
                 typename std::enable_if<!std::is_same<T, int32_t>::value,
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(uint32_t init,
                 typename std::enable_if<!std::is_same<T, uint32_t>::value,
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(
      long init,
      typename std::enable_if<!std::is_same<T, long>::value, bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(unsigned long init,
                 typename std::enable_if<!std::is_same<T, unsigned long>::value,
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(long long init,
                 typename std::enable_if<!std::is_same<T, long long>::value,
                                         bool>::type = true)
      : m_value(init) {}

  template <typename T = NativeInt>
  NativeIntegerT(
      unsigned long long init,
      typename std::enable_if<!std::is_same<T, unsigned long long>::value,
                              bool>::type = true)
      : m_value(init) {}

#if defined(HAVE_INT128)
  template <typename T = NativeInt>
  NativeIntegerT(
      unsigned __int128 val,
      typename std::enable_if<!std::is_same<T, unsigned __int128>::value,
                              bool>::type = true)
      : m_value(val) {}

  template <typename T = NativeInt>
  NativeIntegerT(__int128 val,
                 typename std::enable_if<!std::is_same<T, __int128>::value,
                                         bool>::type = true)
      : m_value(val) {}
#endif

  /**
   * Constructor from a BigInteger
   *
   * @param &val is the initial integer represented as a big integer.
   */
  NativeIntegerT(const lbcrypto::BigInteger &val)
      : m_value(val.ConvertToInt()) {}

  /**
   * Constructor from double is not permitted
   *
   * @param val
   */
  NativeIntegerT(double val)
      __attribute__((deprecated("Cannot construct from a double")));
赋值函数
  /// ASSIGNMENT OPERATORS

  /**
   * Copy assignment operator
   *
   * @param &val is the native integer to be assigned from.
   * @return assigned NativeIntegerT ref.
   */
  const NativeIntegerT &operator=(const NativeIntegerT &val) {
    this->m_value = val.m_value;
    return *this;
  }

  /**
   * Move assignment operator
   *
   * @param &&val is the native integer to be assigned from.
   * @return assigned NativeIntegerT ref.
   */
  const NativeIntegerT &operator=(const NativeIntegerT &&val) {
    this->m_value = val.m_value;
    return *this;
  }

  /**
   * Assignment operator from string
   *
   * @param strval is the string to be assigned from
   * @return the assigned NativeIntegerT ref.
   */
  const NativeIntegerT &operator=(const std::string strval) {
    *this = NativeIntegerT(strval);
    return *this;
  }

  /**
   * Assignment operator from unsigned integer
   *
   * @param &val is the unsigned integer value that is assigned.
   * @return the assigned BigInteger ref.
   */
  const NativeIntegerT &operator=(const NativeInt &val) {
    this->m_value = val;
    return *this;
  }
setter函数
  // ACCESSORS

  /**
   * Basic set method for setting the value of a native integer
   *
   * @param &strval is the string representation of the native integer to be
   * copied.
   */
  void SetValue(const std::string &strval) { AssignVal(strval); }

  /**
   * Basic set method for setting the value of a native integer
   *
   * @param &val is the big binary integer representation of the native
   * integer to be assigned.
   */
  void SetValue(const NativeIntegerT &val) { m_value = val.m_value; }

  /**
   *  Set this int to 1.
   *  Note some compilers don't like using the ONE constant, above :(
   */
  void SetIdentity() { this->m_value = 1; }
算术操作
  // ARITHMETIC OPERATIONS

  /**
   * Addition operation.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  NativeIntegerT Add(const NativeIntegerT &b) const {
    return NATIVEINT_DO_CHECKS ? AddCheck(b) : AddFast(b);  // 是否有 bounds checking ,在文件最前面定义
  }

  /**
   * Addition operation. In-place variant.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  const NativeIntegerT &AddEq(const NativeIntegerT &b) {
    return NATIVEINT_DO_CHECKS ? AddEqCheck(b) : AddEqFast(b);
  }

  /**
   * AddEqCheck is the addition in place operation with bounds checking.
   * In-place variant.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  const NativeIntegerT &AddEqCheck(const NativeIntegerT &b) {   // 判断加起来之后是否溢出
    NativeInt oldv = m_value;
    m_value += b.m_value;
    if (m_value < oldv) {
      PALISADE_THROW(lbcrypto::math_error, "Overflow");
    }
    return *this;
  }

  /**
   * AddEqFast is the addition in place operation without bounds checking.
   * In-place variant.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  const NativeIntegerT &AddEqFast(const NativeIntegerT &b) {
    m_value += b.m_value;
    return *this;
  }

  /**
   * Subtraction operation.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  NativeIntegerT Sub(const NativeIntegerT &b) const {
    return NATIVEINT_DO_CHECKS ? SubCheck(b) : SubFast(b);
  }

  /**
   * SubCheck is the subtraction operation with bounds checking.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  NativeIntegerT SubCheck(const NativeIntegerT &b) const {
    return m_value <= b.m_value ? 0 : m_value - b.m_value;    // 默认是无符号整数,不出现负数
  }

  /**
   * SubFast is the subtraction operation without bounds checking.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  NativeIntegerT SubFast(const NativeIntegerT &b) const {
    return m_value - b.m_value;
  }

  /**
   * Subtraction operation. In-place variant.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  const NativeIntegerT &SubEq(const NativeIntegerT &b) {
    return NATIVEINT_DO_CHECKS ? SubEqCheck(b) : SubEqFast(b);
  }

  /**
   * SubEqCheck is the subtraction in place operation with bounds checking.
   * In-place variant.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  const NativeIntegerT &SubEqCheck(const NativeIntegerT &b) {
    m_value = m_value <= b.m_value ? 0 : m_value - b.m_value;
    return *this;
  }

  /**
   * SubEqFast is the subtraction in place operation without bounds checking.
   * In-place variant.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  const NativeIntegerT &SubEqFast(const NativeIntegerT &b) {
    m_value -= b.m_value;
    return *this;
  }

  // overloaded binary operators based on integer arithmetic and comparison
  // functions.
  NativeIntegerT operator-() const { return NativeIntegerT(0).Sub(*this); } // 取负数 

  /**
   * Multiplication operation.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  NativeIntegerT Mul(const NativeIntegerT &b) const {
    return NATIVEINT_DO_CHECKS ? MulCheck(b) : MulFast(b);
  }

  /**
   * MulCheck is the multiplication operation with bounds checking.
   *
   * @param b is the value to multiply with
   * @return result of the multiplication operation
   */
  NativeIntegerT MulCheck(const NativeIntegerT &b) const {
    NativeInt prod = m_value * b.m_value;
    if (prod > 0 && (prod < m_value || prod < b.m_value))
      PALISADE_THROW(lbcrypto::math_error, "Overflow");
    return prod;
  }

  /**
   * MulFast is the multiplication operation without bounds checking.
   *
   * @param b is the value to multiply with.
   * @return result of the multiplication operation.
   */
  NativeIntegerT MulFast(const NativeIntegerT &b) const {
    return m_value * b.m_value;
  }

  /**
   * Multiplication operation. In-place variant.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  const NativeIntegerT &MulEq(const NativeIntegerT &b) {
    return NATIVEINT_DO_CHECKS ? MulEqCheck(b) : MulEqFast(b);
  }

  /**
   * MulEqCheck is the multiplication in place operation with bounds checking.
   * In-place variant.
   *
   * @param b is the value to multiply with
   * @return result of the multiplication operation
   */
  const NativeIntegerT &MulEqCheck(const NativeIntegerT &b) {
    NativeInt oldval = m_value;
    m_value *= b.m_value;
    if (m_value < oldval) {
      PALISADE_THROW(lbcrypto::math_error, "Overflow");
    }
    return *this;
  }

  /**
   * MulEqFast is the multiplication in place operation without bounds
   * checking. In-place variant.
   *
   * @param b is the value to multiply with
   * @return result of the multiplication operation
   */
  const NativeIntegerT &MulEqFast(const NativeIntegerT &b) {
    m_value *= b.m_value;
    return *this;
  }

  /**
   * Division operation.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  NativeIntegerT DividedBy(const NativeIntegerT &b) const {
    if (b.m_value == 0) PALISADE_THROW(lbcrypto::math_error, "Divide by zero");
    return this->m_value / b.m_value;
  }

  /**
   * Division operation. In-place variant.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  const NativeIntegerT &DividedByEq(const NativeIntegerT &b) {
    if (b.m_value == 0) PALISADE_THROW(lbcrypto::math_error, "Divide by zero");
    this->m_value /= b.m_value;
    return *this;
  }

  /**
   * Exponentiation operation. Returns x^p.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  NativeIntegerT Exp(usint p) const {
    if (p == 0) {
      return 1;
    }
    if (p == 1) {
      return NativeIntegerT(*this);
    }
    NativeIntegerT tmp = (*this).Exp(p / 2);
    if (p % 2 == 0) {
      return tmp * tmp;
    } else {
      return tmp * tmp * (*this);
    }
  }

  /**
   * Exponentiation operation. Returns x^p. In-place variant.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  const NativeIntegerT &ExpEq(usint p) {
    if (p == 0) {
      this->m_value = 1;
      return *this;
    }
    if (p == 1) {
      return *this;
    }
    NativeIntegerT tmp = this->Exp(p / 2);
    if (p % 2 == 0) {
      *this = (tmp * tmp);
      return *this;
    } else {
      (*this) *= (tmp * tmp);
      return *this;
    }
  }
  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  NativeIntegerT MultiplyAndRound(const NativeIntegerT &p,
                                  const NativeIntegerT &q) const {
    NativeIntegerT ans = m_value * p.m_value;
    return ans.DivideAndRound(q);
  }

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const NativeIntegerT &MultiplyAndRoundEq(const NativeIntegerT &p,
                                           const NativeIntegerT &q) {
    this->MulEq(p);
    this->DivideAndRoundEq(q);
    return *this;
  }

  /**
   * Computes the quotient of x*p/q, where x,p,q are all NativeInt numbers, x
   * is the current value; uses DNativeInt arithmetic   // D是double的意思,比特长度为2倍
   *
   * @param p is the multiplicand
   * @param q is the divisor
   * @return the quotient
   */
  template <typename T = NativeInt>
  NativeIntegerT MultiplyAndDivideQuotient(
      const NativeIntegerT &p, const NativeIntegerT &q,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt xD = m_value;
    DNativeInt pD = p.m_value;
    DNativeInt qD = q.m_value;
    return NativeIntegerT(xD * pD / qD);
  }

  template <typename T = NativeInt>
  NativeIntegerT MultiplyAndDivideQuotient(
      const NativeIntegerT &p, const NativeIntegerT &q,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeInt xD = m_value;
    NativeInt pD = p.m_value;
    NativeInt qD = q.m_value;
    return NativeIntegerT(xD * pD / qD);
  }

  /**
   * Computes the remainder of x*p/q, where x,p,q are all NativeInt numbers, x
   * is the current value; uses DNativeInt arithmetic. In-place variant.
   *
   * @param p is the multiplicand
   * @param q is the divisor
   * @return the remainder
   */
  template <typename T = NativeInt>
  NativeIntegerT MultiplyAndDivideRemainder(
      const NativeIntegerT &p, const NativeIntegerT &q,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt xD = m_value;
    DNativeInt pD = p.m_value;
    DNativeInt qD = q.m_value;
    return NativeIntegerT((xD * pD) % qD);
  }

  template <typename T = NativeInt>
  NativeIntegerT MultiplyAndDivideRemainder(
      const NativeIntegerT &p, const NativeIntegerT &q,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeInt xD = m_value;
    NativeInt pD = p.m_value;
    NativeInt qD = q.m_value;
    return NativeIntegerT((xD * pD) % qD);
  }

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  NativeIntegerT DivideAndRound(const NativeIntegerT &q) const {
    if (q == 0) {
      PALISADE_THROW(lbcrypto::math_error, "Divide by zero");
    }
    NativeInt ans = m_value / q.m_value;
    NativeInt rem = m_value % q.m_value;
    NativeInt halfQ = q.m_value >> 1;
    if (!(rem <= halfQ)) {
      ans += 1;
    }
    return ans;
  }

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const NativeIntegerT &DivideAndRoundEq(const NativeIntegerT &q) {
    return *this = this->DivideAndRound(q);
  }

  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Naive modulus operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  NativeIntegerT Mod(const NativeIntegerT &modulus) const {
    return m_value % modulus.m_value;
  }

  /**
   * Naive modulus operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  const NativeIntegerT &ModEq(const NativeIntegerT &modulus) {
    m_value %= modulus.m_value;
    return *this;
  }

  /**
   * Precomputes a parameter mu for Barrett modular reduction.
   *
   * @return the precomputed parameter mu.
   */
  template <typename T = NativeInt>
  NativeIntegerT ComputeMu(
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt temp(1);
    temp <<= 2 * this->GetMSB() + 3;
    return NativeInt(temp / DNativeInt(this->m_value));
  }

  template <typename T = NativeInt>
  NativeIntegerT ComputeMu(
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    lbcrypto::BigInteger temp(static_cast<T>(1));
    temp <<= 2 * this->GetMSB() + 3;
    return NativeInt((temp / lbcrypto::BigInteger(*this)).ConvertToInt());
  }

  /**
   * Barrett modulus operation.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  template <typename T = NativeInt>
  NativeIntegerT Mod(
      const NativeIntegerT &modulus, const NativeIntegerT &mu,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    typeD tmp1;
    tmp1.lo = this->m_value;
    tmp1.hi = 0;
    DNativeInt tmp(this->m_value);

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    // RShiftD is more efficient than the right-shifting of DNativeInt
    NativeInt ql = RShiftD(tmp1, n + beta);
    MultD(ql, mu.m_value, tmp1);
    DNativeInt q = GetD(tmp1);

    // we cannot use RShiftD here because alpha - beta > 63
    // for q larger than 57 bits
    q >>= alpha - beta;
    tmp -= q * DNativeInt(modulus.m_value);

    NativeIntegerT ans;
    ans.m_value = NativeInt(tmp);

    // correction at the end
    if (ans.m_value > modulus.m_value) {
      ans.m_value -= modulus.m_value;
    }
    return ans;
  }

  template <typename T = NativeInt>
  NativeIntegerT Mod(const NativeIntegerT &modulus, const NativeIntegerT &mu,
                     typename std::enable_if<std::is_same<T, DNativeInt>::value,
                                             bool>::type = true) const {
    typeD prod;
    prod.lo = this->m_value;
    prod.hi = 0;
    typeD result = prod;

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    NativeInt ql = RShiftD(prod, n + beta);
    MultD(ql, mu.m_value, prod);

    ql = RShiftD(prod, alpha - beta);
    MultD(ql, modulus.m_value, prod);
    SubtractD(result, prod);

    NativeIntegerT ans(result.lo);
    // correction at the end
    if (ans.m_value > modulus.m_value) {
      ans.m_value -= modulus.m_value;
    }
    return ans;
  }

  /**
   * Barrett modulus operation. In-place variant.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  template <typename T = NativeInt>
  const NativeIntegerT &ModEq(
      const NativeIntegerT &modulus, const NativeIntegerT &mu,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    typeD tmp1;
    tmp1.lo = this->m_value;
    tmp1.hi = 0;
    DNativeInt tmp(this->m_value);

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    // RShiftD is more efficient than the right-shifting of DNativeInt
    NativeInt ql = RShiftD(tmp1, n + beta);
    MultD(ql, mu.m_value, tmp1);
    DNativeInt q = GetD(tmp1);

    // we cannot use RShiftD here because alpha - beta > 63
    // for q larger than 57 bits
    q >>= alpha - beta;
    tmp -= q * DNativeInt(modulus.m_value);

    this->m_value = NativeInt(tmp);

    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  template <typename T = NativeInt>
  const NativeIntegerT &ModEq(
      const NativeIntegerT &modulus, const NativeIntegerT &mu,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    typeD prod;
    prod.lo = this->m_value;
    prod.hi = 0;
    typeD result = prod;

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    NativeInt ql = RShiftD(prod, n + beta);
    MultD(ql, mu.m_value, prod);

    ql = RShiftD(prod, alpha - beta);
    MultD(ql, modulus.m_value, prod);
    SubtractD(result, prod);

    this->m_value = result.lo;
    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  /**
   * Modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  NativeIntegerT ModAdd(const NativeIntegerT &b,
                        const NativeIntegerT &modulus) const {
    NativeInt mod = modulus.m_value;
    NativeInt op1 = this->m_value;
    NativeInt op2 = b.m_value;
    if (op1 >= mod) {
      op1 %= mod;
    }
    if (op2 >= mod) {
      op2 %= mod;
    }
    op1 += op2;
    if (op1 >= mod) {
      op1 -= mod;
    }
    return op1;
  }

  /**
   * Modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const NativeIntegerT &ModAddEq(const NativeIntegerT &b,
                                 const NativeIntegerT &modulus) {
    NativeInt mod = modulus.m_value;
    NativeInt op2 = b.m_value;
    if (this->m_value >= mod) {
      this->m_value %= mod;
    }
    if (op2 >= mod) {
      op2 %= mod;
    }
    this->m_value += op2;
    if (this->m_value >= mod) {
      this->m_value -= mod;
    }
    return *this;
  }

  /**
   * Modulus addition where operands are < modulus.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  inline NativeIntegerT ModAddFast(const NativeIntegerT &b,
                                   const NativeIntegerT &modulus) const {
    NativeInt r = this->m_value + b.m_value;
    if (r >= modulus.m_value) {
      r -= modulus.m_value;
    }
    return r;
  }
  /**
   * Modulus addition where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const NativeIntegerT &ModAddFastEq(const NativeIntegerT &b,
                                     const NativeIntegerT &modulus) {
    this->m_value += b.m_value;
    if (this->m_value >= modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  /**
   * Barrett modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  NativeIntegerT ModAdd(const NativeIntegerT &b, const NativeIntegerT &modulus,
                        const NativeIntegerT &mu) const {
    NativeInt mod(modulus.m_value);
    NativeIntegerT av(this->m_value);
    NativeIntegerT bv(b.m_value);
    if (av.m_value >= mod) {
      av.ModEq(modulus, mu);
    }
    if (bv.m_value >= mod) {
      bv.ModEq(modulus, mu);
    }
    av.m_value += bv.m_value;
    if (av.m_value >= mod) {
      av.m_value -= mod;
    }
    return av;
  }

  /**
   * Barrett modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  const NativeIntegerT &ModAddEq(const NativeIntegerT &b,
                                 const NativeIntegerT &modulus,
                                 const NativeIntegerT &mu) {
    NativeInt mod(modulus.m_value);
    NativeIntegerT bv(b.m_value);
    if (this->m_value >= mod) {
      this->ModEq(modulus, mu);
    }
    if (bv.m_value >= mod) {
      bv.ModEq(modulus, mu);
    }
    this->m_value += bv.m_value;
    if (this->m_value >= mod) {
      this->m_value -= mod;
    }
    return *this;
  }

  /**
   * Modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  NativeIntegerT ModSub(const NativeIntegerT &b,
                        const NativeIntegerT &modulus) const {
    NativeInt mod(modulus.m_value);
    NativeInt av(this->m_value);
    NativeInt bv(b.m_value);
    // reduce this to a value lower than modulus
    if (av >= mod) {
      av %= mod;
    }
    // reduce b to a value lower than modulus
    if (bv >= mod) {
      bv %= mod;
    }

    if (av >= bv) {
      av -= bv;
    } else {
      av += (mod - bv);
    }
    return av;
  }

  /**
   * Modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const NativeIntegerT &ModSubEq(const NativeIntegerT &b,
                                 const NativeIntegerT &modulus) {
    NativeInt mod(modulus.m_value);
    NativeInt bv(b.m_value);
    // reduce this to a value lower than modulus
    if (this->m_value >= mod) {
      this->m_value %= mod;
    }
    // reduce b to a value lower than modulus
    if (bv >= mod) {
      bv %= mod;
    }

    if (this->m_value >= bv) {
      this->m_value -= bv;
    } else {
      this->m_value += (mod - bv);
    }
    return *this;
  }

  /**
   * Modulus subtraction where operands are < modulus.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  inline NativeIntegerT ModSubFast(const NativeIntegerT &b,
                                   const NativeIntegerT &modulus) const {
    NativeInt mod(modulus.m_value);
    NativeInt av(this->m_value);
    NativeInt bv(b.m_value);

    if (av >= bv) {
      av -= bv;
    } else {
      av += (mod - bv);
    }
    return av;
  }

  /**
   * Modulus subtraction where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const NativeIntegerT &ModSubFastEq(const NativeIntegerT &b,
                                     const NativeIntegerT &modulus) {
    if (this->m_value >= b.m_value) {
      this->m_value -= b.m_value;
    } else {
      this->m_value += (modulus.m_value - b.m_value);
    }
    return *this;
  }

  /**
   * Barrett modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  NativeIntegerT ModSub(const NativeIntegerT &b, const NativeIntegerT &modulus,
                        const NativeIntegerT &mu) const {
    NativeInt mod(modulus.m_value);
    NativeIntegerT av(this->m_value);
    NativeIntegerT bv(b.m_value);
    if (av.m_value >= mod) {
      av.ModEq(modulus, mu);
    }
    if (bv.m_value >= mod) {
      bv.ModEq(modulus, mu);
    }

    if (av.m_value >= bv.m_value) {
      av.m_value -= bv.m_value;
    } else {
      av.m_value += (mod - bv.m_value);
    }
    return av;
  }

  /**
   * Barrett modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  const NativeIntegerT &ModSubEq(const NativeIntegerT &b,
                                 const NativeIntegerT &modulus,
                                 const NativeIntegerT &mu) {
    NativeIntegerT bv(b.m_value);
    NativeInt mod(modulus.m_value);
    if (this->m_value >= mod) {
      this->ModEq(modulus, mu);
    }
    if (bv.m_value >= mod) {
      bv.ModEq(modulus, mu);
    }

    if (this->m_value >= bv.m_value) {
      this->m_value -= bv.m_value;
    } else {
      this->m_value += (mod - bv.m_value);
    }
    return *this;
  }

  /**
   * Modulus multiplication operation.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  template <typename T = NativeInt>
  NativeIntegerT ModMul(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeInt aval = this->m_value;
    NativeInt bval = b.m_value;
    NativeInt mod = modulus.m_value;
    if (aval > mod) {
      aval %= mod;
    }
    if (bval > mod) {
      bval %= mod;
    }
    DNativeInt av(aval);
    DNativeInt bv(bval);
    DNativeInt result = av * bv;
    DNativeInt dmod(mod);
    if (result >= dmod) {
      result %= dmod;
    }
    return NativeIntegerT(result);
  }

  template <typename T = NativeInt>
  NativeIntegerT ModMul(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeIntegerT mu(modulus.ComputeMu());
    NativeIntegerT a = *this;
    NativeIntegerT bW = b;
    if (a > modulus) {
      a.ModEq(modulus, mu);
    }
    if (bW > modulus) {
      bW.ModEq(modulus, mu);
    }
    return a.ModMul(bW, modulus, mu);
  }

  /**
   * Modulus multiplication operation. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  template <typename T = NativeInt>
  const NativeIntegerT &ModMulEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    NativeInt bval = b.m_value;
    NativeInt mod = modulus.m_value;
    if (this->m_value > mod) {
      this->m_value %= mod;
    }
    if (bval > mod) {
      bval %= mod;
    }
    DNativeInt av(m_value);
    DNativeInt bv(bval);
    DNativeInt result = av * bv;
    DNativeInt dmod(mod);
    if (result >= dmod) {
      result %= dmod;
    }
    *this = NativeIntegerT(result);
    return *this;
  }

  template <typename T = NativeInt>
  const NativeIntegerT &ModMulEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) {     // mu在函数内计算
    NativeIntegerT mu(modulus.ComputeMu());
    NativeIntegerT bW = b;
    if (*this > modulus) {
      ModEq(modulus, mu);
    }
    if (bW > modulus) {
      bW.ModEq(modulus, mu);
    }
    ModMulEq(bW, modulus, mu);
    return *this;
  }

  /**
   * Barrett modulus multiplication.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  NativeIntegerT ModMul(const NativeIntegerT &b, const NativeIntegerT &modulus,
                        const NativeIntegerT &mu) const {
    NativeIntegerT ans(*this);
    ans.ModMulEq(b, modulus, mu);
    return ans;
  }

  /**
   * Barrett modulus multiplication. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  template <typename T = NativeInt>
  const NativeIntegerT &ModMulEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,                                           // mu 已经给好了
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    NativeIntegerT bb(b);

    if (this->m_value > modulus.m_value) {
      this->ModEq(modulus, mu);
    }
    if (bb.m_value > modulus.m_value) {
      bb.ModEq(modulus, mu);
    }

    typeD prod1;
    MultD(this->m_value, b.m_value, prod1);
    DNativeInt prod = GetD(prod1);

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    // RShiftD is more efficient than the right-shifting of DNativeInt
    NativeInt ql = RShiftD(prod1, n + beta);
    MultD(ql, mu.m_value, prod1);
    DNativeInt q = GetD(prod1);

    // we cannot use RShiftD here because alpha - beta > 63
    // for q larger than 57 bits
    q >>= alpha - beta;
    prod -= q * DNativeInt(modulus.m_value);

    this->m_value = NativeInt(prod);

    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  template <typename T = NativeInt>
  const NativeIntegerT &ModMulEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    NativeIntegerT bb(b);

    if (this->m_value > modulus.m_value) {
      this->ModEq(modulus, mu);
    }
    if (bb.m_value > modulus.m_value) {
      bb.ModEq(modulus, mu);
    }

    typeD prod1;
    MultD(this->m_value, b.m_value, prod1);
    typeD prod = prod1;

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    NativeInt ql = RShiftD(prod1, n + beta);
    MultD(ql, mu.m_value, prod1);

    typeD q;
    ql = RShiftD(prod1, alpha - beta);
    MultD(ql, modulus.m_value, q);
    SubtractD(prod, q);

    this->m_value = prod.lo;

    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  /**
   * Modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  template <typename T = NativeInt>
  NativeIntegerT ModMulFast(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt av(m_value);
    DNativeInt bv(b.m_value);
    DNativeInt result = av * bv;
    DNativeInt mod(modulus.m_value);
    if (result >= mod) {
      result %= mod;
    }
    return NativeIntegerT(result);
  }

  template <typename T = NativeInt>
  NativeIntegerT ModMulFast(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeIntegerT mu(modulus.ComputeMu());
    NativeIntegerT a = *this;
    NativeIntegerT bW = b;
    if (a > modulus) {
      a.ModEq(modulus, mu);
    }
    if (bW > modulus) {
      bW.ModEq(modulus, mu);
    }
    return a.ModMulFast(bW, modulus, mu);
  }

  /**
   * Modulus multiplication that assumes the operands are < modulus. In-place
   * variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const NativeIntegerT &ModMulFastEq(const NativeIntegerT &b,
                                     const NativeIntegerT &modulus) {
    return *this = this->ModMulFast(b, modulus);
  }

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  /* Source: http://homes.esat.kuleuven.be/~fvercaut/papers/bar_mont.pdf
    @article{knezevicspeeding,
    title={Speeding Up Barrett and Montgomery Modular Multiplications},
    author={Knezevic, Miroslav and Vercauteren, Frederik and Verbauwhede,
    Ingrid}
    }
    We use the Generalized Barrett modular reduction algorithm described in
    Algorithm 2 of the Source. The algorithm was originally proposed in J.-F.
    Dhem. Modified version of the Barrett algorithm. Technical report, 1994
    and described in more detail in the PhD thesis of the author published at
    http://users.belgacom.net/dhem/these/these_public.pdf (Section 2.2.4).
    We take \alpha equal to n + 3. So in our case, \mu = 2^(n + \alpha) =
    2^(2*n + 3). Generally speaking, the value of \alpha should be \ge \gamma
    + 1, where \gamma + n is the number of digits in the dividend. We use the
    upper bound of dividend assuming that none of the dividends will be larger
    than 2^(2*n + 3). The value of \mu is computed by NativeVector::ComputeMu.
    */
  template <typename T = NativeInt>
  NativeIntegerT ModMulFast(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeIntegerT ans(*this);

    typeD prod1;
    MultD(ans.m_value, b.m_value, prod1);
    DNativeInt prod = GetD(prod1);
    typeD q0(prod1);

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    // RShiftD is more efficient than the right-shifting of DNativeInt
    NativeInt ql = RShiftD(q0, n + beta);
    MultD(ql, mu.m_value, q0);
    DNativeInt q = GetD(q0);

    // we cannot use RShiftD here because alpha - beta > 63
    // for q larger than 57 bits
    q >>= alpha - beta;
    prod -= q * DNativeInt(modulus.m_value);

    ans.m_value = NativeInt(prod);

    // correction at the end
    if (ans.m_value > modulus.m_value) {
      ans.m_value -= modulus.m_value;
    }
    return ans;
  }

  template <typename T = NativeInt>
  NativeIntegerT ModMulFast(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeIntegerT ans(*this);

    typeD prod1;
    MultD(ans.m_value, b.m_value, prod1);
    typeD prod = prod1;

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    NativeInt ql = RShiftD(prod1, n + beta);
    MultD(ql, mu.m_value, prod1);

    typeD q;
    ql = RShiftD(prod1, alpha - beta);
    MultD(ql, modulus.m_value, q);
    SubtractD(prod, q);

    ans.m_value = prod.lo;

    // correction at the end
    if (ans.m_value > modulus.m_value) {
      ans.m_value -= modulus.m_value;
    }
    return ans;
  }

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   * In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  template <typename T = NativeInt>
  const NativeIntegerT &ModMulFastEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    typeD prod1;
    MultD(this->m_value, b.m_value, prod1);
    DNativeInt prod = GetD(prod1);
    typeD q0(prod1);

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    // RShiftD is more efficient than the right-shifting of DNativeInt
    NativeInt ql = RShiftD(q0, n + beta);
    MultD(ql, mu.m_value, q0);
    DNativeInt q = GetD(q0);

    // we cannot use RShiftD here because alpha - beta > 63
    // for q larger than 57 bits
    q >>= alpha - beta;
    prod -= q * DNativeInt(modulus.m_value);

    this->m_value = NativeInt(prod);

    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  template <typename T = NativeInt>
  const NativeIntegerT &ModMulFastEq(
      const NativeIntegerT &b, const NativeIntegerT &modulus,
      const NativeIntegerT &mu,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) {
    typeD prod1;
    MultD(this->m_value, b.m_value, prod1);
    typeD prod = prod1;

    long n = modulus.GetMSB();
    long alpha = n + 3;
    long beta = -2;

    NativeInt ql = RShiftD(prod1, n + beta);
    MultD(ql, mu.m_value, prod1);

    typeD q;
    ql = RShiftD(prod1, alpha - beta);
    MultD(ql, modulus.m_value, q);
    SubtractD(prod, q);

    this->m_value = prod.lo;

    // correction at the end
    if (this->m_value > modulus.m_value) {
      this->m_value -= modulus.m_value;
    }
    return *this;
  }

  /*  The next three subroutines implement the modular multiplication
    algorithm for the case when the multiplicand is used multiple times (known
    in advance), as in NTT. The algorithm is described in
    https://arxiv.org/pdf/1205.2926.pdf (Dave Harvey, FASTER ARITHMETIC FOR
    NUMBER-THEORETIC TRANSFORMS). The algorithm is described in lines 5-7 of
    Algorithm 2. The algorithm was originally proposed and implemented in NTL
    (https://www.shoup.net/ntl/) by Victor Shoup.
    */

  /**
   * Precomputation for a multiplicand.
   *
   * @param modulus is the modulus to perform operations with.
   * @return the precomputed factor.
   */
  template <typename T = NativeInt>
  NativeIntegerT PrepModMulConst(
      const NativeIntegerT &modulus,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt w = DNativeInt(this->m_value) << MaxBits();
    return NativeInt(w / DNativeInt(modulus.m_value));
  }

  template <typename T = NativeInt>
  NativeIntegerT PrepModMulConst(
      const NativeIntegerT &modulus,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    lbcrypto::BigInteger w = lbcrypto::BigInteger(m_value) << MaxBits();
    return NativeInt(
        (w / lbcrypto::BigInteger(modulus.m_value)).ConvertToInt());
  }

  /**
   * Modular multiplication using a precomputation for the multiplicand.
   *
   * @param &b is the NativeIntegerT to multiply.
   * @param modulus is the modulus to perform operations with.
   * @param &bInv precomputation for b.
   * @return is the result of the modulus multiplication operation.
   */
  NativeIntegerT ModMulFastConst(const NativeIntegerT &b,
                                 const NativeIntegerT &modulus,
                                 const NativeIntegerT &bInv) const {
    NativeInt q = MultDHi(this->m_value, bInv.m_value);
    NativeInt yprime = this->m_value * b.m_value - q * modulus.m_value;
    return SignedNativeInt(yprime) - SignedNativeInt(modulus.m_value) >= 0
               ? yprime - modulus.m_value
               : yprime;
  }

  /**
   * Modular multiplication using a precomputation for the multiplicand.
   * In-place variant.
   *
   * @param &b is the NativeIntegerT to multiply.
   * @param modulus is the modulus to perform operations with.
   * @param &bInv precomputation for b.
   * @return is the result of the modulus multiplication operation.
   */
  const NativeIntegerT &ModMulFastConstEq(const NativeIntegerT &b,
                                          const NativeIntegerT &modulus,
                                          const NativeIntegerT &bInv) {
    NativeInt q = MultDHi(this->m_value, bInv.m_value);
    NativeInt yprime = this->m_value * b.m_value - q * modulus.m_value;
    this->m_value =
        SignedNativeInt(yprime) - SignedNativeInt(modulus.m_value) >= 0
            ? yprime - modulus.m_value
            : yprime;
    return *this;
  }

  /**
   * Modulus exponentiation operation.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  template <typename T = NativeInt>
  NativeIntegerT ModExp(
      const NativeIntegerT &b, const NativeIntegerT &mod,
      typename std::enable_if<!std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    DNativeInt exp(b.m_value);
    DNativeInt product(1);
    DNativeInt modulus(mod.m_value);
    DNativeInt mid(m_value % mod.m_value);
    const DNativeInt ZERO(0);
    const DNativeInt ONE(1);
    const DNativeInt TWO(2);

    while (true) {
      if (exp % TWO == ONE) {
        product = product * mid;
      }

      // running product is calculated
      if (product >= modulus) {
        product = product % modulus;
      }

      // divide by 2 and check even to odd to find bit value
      exp >>= 1;
      if (exp == ZERO) {
        break;
      }

      // mid calculates mid^2%q
      mid = mid * mid;
      mid = mid % modulus;
    }
    return NativeIntegerT(product);
  }

  template <typename T = NativeInt>
  NativeIntegerT ModExp(
      const NativeIntegerT &b, const NativeIntegerT &mod,
      typename std::enable_if<std::is_same<T, DNativeInt>::value, bool>::type =
          true) const {
    NativeInteger mu(mod.ComputeMu());
    NativeInteger exp(b.m_value);
    NativeInteger product(1);
    NativeInteger modulus(mod.m_value);
    NativeInteger mid(m_value % mod.m_value);
    const NativeInteger ZERO(0);
    const NativeInteger ONE(1);
    const NativeInteger TWO(2);

    while (true) {
      if (exp % TWO == ONE) {
        product.ModMulFastEq(mid, modulus, mu);
      }

      // divide by 2 and check even to odd to find bit value
      exp >>= 1;
      if (exp == ZERO) {
        break;
      }

      mid.ModMulFastEq(mid, modulus, mu);
    }

    return NativeIntegerT(product);
  }

  /**
   * Modulus exponentiation operation. In-place variant.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  const NativeIntegerT &ModExpEq(const NativeIntegerT &b,
                                 const NativeIntegerT &mod) {
    *this = ModExp(b, mod);
    return *this;
  }

  /**
   * Modulus inverse operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  NativeIntegerT ModInverse(const NativeIntegerT &mod) const {
    NativeInt modulus = mod.m_value;
    NativeInt a = m_value % modulus;
    if (a == 0) {
      std::string msg = toString(m_value) +
                        " does not have a ModInverse using " +
                        toString(modulus);
      PALISADE_THROW(lbcrypto::math_error, msg);
    }
    if (modulus == 1) {
      return 0;
    }

    SignedNativeInt m0 = modulus;
    SignedNativeInt y = 0;
    SignedNativeInt x = 1;
    while (a > 1) {
      // q is quotient
      SignedNativeInt q = a / modulus;

      SignedNativeInt t = modulus;
      modulus = a % modulus;
      a = t;

      // Update y and x
      t = y;
      y = x - q * y;
      x = t;
    }

    // Make x positive
    if (x < 0) x += m0;

    return NativeInt(x);
  }

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  const NativeIntegerT &ModInverseEq(const NativeIntegerT &mod) {
    *this = ModInverse(mod);
    return *this;
  }
移位运算
  // SHIFT OPERATIONS

  /**
   * Left shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  NativeIntegerT LShift(usshort shift) const { return m_value << shift; }

  /**
   * Left shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const NativeIntegerT &LShiftEq(usshort shift) {
    m_value <<= shift;
    return *this;
  }

  /**
   * Right shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  NativeIntegerT RShift(usshort shift) const { return m_value >> shift; }

  /**
   * Right shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const NativeIntegerT &RShiftEq(usshort shift) {
    m_value >>= shift;
    return *this;
  }
比较运算
  // COMPARE

  /**
   * Compares the current NativeIntegerT to NativeIntegerT a.
   *
   * @param a is the NativeIntegerT to be compared with.
   * @return  -1 for strictly less than, 0 for equal to and 1 for strictly
   * greater than conditons.
   */
  int Compare(const NativeIntegerT &a) const {
    if (this->m_value < a.m_value)
      return -1;
    else if (this->m_value > a.m_value)
      return 1;
    return 0;
  }

一些转化函数
  // CONVERTERS

  /**
   * Converts the value to an int.
   *
   * @return the int representation of the value as usint.
   */
  template <typename OutputType = NativeInt>
  OutputType ConvertToInt() const {
    if (sizeof(OutputType) < sizeof(m_value))
      PALISADE_THROW(lbcrypto::type_error,
                     "Invalid integer conversion: sizeof(OutputIntType) < "
                     "sizeof(InputIntType)");
    return static_cast<OutputType>(m_value);
  }

  /**
   * Converts the value to an double.
   *
   * @return double representation of the value.
   */
  double ConvertToDouble() const { return static_cast<double>(m_value); }

  /**
   * Convert a string representation of a binary number to a NativeIntegerT.
   *
   * @param bitString the binary num in string.
   * @return the binary number represented as a big binary int.
   */
  static NativeIntegerT FromBinaryString(const std::string &bitString) {    // string 保存二进制字符串
    if (bitString.length() > MaxBits()) {
      PALISADE_THROW(lbcrypto::math_error,
                     "Bit string is too long to fit in a bigintnat");
    }
    NativeInt v = 0;
    for (size_t i = 0; i < bitString.length(); i++) {
      int n = bitString[i] - '0';
      if (n < 0 || n > 1) {
        PALISADE_THROW(lbcrypto::math_error,
                       "Bit string must contain only 0 or 1");
      }
      v <<= 1;
      v |= n;
    }
    return v;
  }
其他函数
  // OTHER FUNCTIONS

  /**
   * Returns the MSB location of the value.
   *
   * @return the index of the most significant bit.
   */
  usint GetMSB() const { return lbcrypto::GetMSB(this->m_value); }

  /**
   * Get the number of digits using a specific base - support for arbitrary
   * base may be needed.
   *
   * @param base is the base with which to determine length in.
   * @return the length of the representation in a specific base.
   */
  usint GetLengthForBase(usint base) const { return GetMSB(); }

  /**
   * Get a specific digit at "digit" index; big integer is seen as an array of
   * digits, where a 0 <= digit < base Warning: only power-of-2 bases are
   * currently supported. Example: for number 83, index 2 and base 4 we have:
   *
   *                         index:0,1,2,3
   * 83 --base 4 decomposition--> (3,0,1,1) --at index 2--> 1
   *
   * The return number is 1.
   *
   * @param index is the "digit" index of the requested digit
   * @param base is the base with which to determine length in.
   * @return is the requested digit
   */
  usint GetDigitAtIndexForBase(usint index, usint base) const {
    usint DigitLen = ceil(log2(base));
    usint digit = 0;
    usint newIndex = 1 + (index - 1) * DigitLen;
    for (usint i = 1; i < base; i = i * 2) {
      digit += GetBitAtIndex(newIndex) * i;
      newIndex++;
    }
    return digit;
  }

  /**
   * Gets the bit at the specified index.
   *
   * @param index is the index of the bit to get.
   * @return resulting bit.
   */
  uschar GetBitAtIndex(usint index) const {
    if (index == 0) {
      PALISADE_THROW(lbcrypto::math_error, "Zero index in GetBitAtIndex");
    }

    return (m_value >> (index - 1)) & 0x01;
  }

  /**
   * A zero allocator that is called by the Matrix class.
   * It is used to initialize a Matrix of NativeIntegerT objects.
   */
  static NativeIntegerT Allocator() { return 0; }
输出流的函数
  // STRINGS & STREAMS

  /**
   * Stores the based 10 equivalent/Decimal value of the NativeIntegerT in a
   * string object and returns it.
   *
   * @return value of this NativeIntegerT in base 10 represented as a string.
   */
  const std::string ToString() const { return toString(m_value); }

  static const std::string IntegerTypeName() { return "UBNATINT"; }

  /**
   * Console output operation.
   *
   * @param os is the std ostream object.
   * @param ptr_obj is NativeIntegerT to be printed.
   * @return is the ostream object.
   */
  friend std::ostream &operator<<(std::ostream &os,
                                  const NativeIntegerT &ptr_obj) {
    os << ptr_obj.ToString();
    return os;
  }
序列化函数
  // SERIALIZATION

  template <class Archive, typename T = void>
  typename std::enable_if<std::is_same<NativeInt, U64BITS>::value ||
                              std::is_same<NativeInt, U32BITS>::value,
                          T>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_value));
  }

#if defined(HAVE_INT128)
  template <class Archive>
  typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
                              !cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    // get an array with 2 unint64_t values for m_value
    uint64_t vec[2];
    ar(::cereal::binary_data(vec, sizeof(vec)));  // 2*8 - size in bytes
    m_value = vec[1];                             // most significant word
    m_value <<= 64;
    m_value += vec[0];  // least significant word
  }

  template <class Archive>
  typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
                              cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    // get an array with 2 unint64_t values for m_value
    uint64_t vec[2];
    ar(::cereal::make_nvp("i", vec));
    m_value = vec[1];  // most significant word
    m_value <<= 64;
    m_value += vec[0];  // least significant word
  }
#endif

  template <class Archive, typename T = void>
  typename std::enable_if<std::is_same<NativeInt, U64BITS>::value ||
                              std::is_same<NativeInt, U32BITS>::value,
                          T>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_value));
  }

#if defined(HAVE_INT128)
  template <class Archive>
  typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
                              !cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    // save 2 unint64_t values instead of unsigned __int128
    constexpr U128BITS mask = (static_cast<U128BITS>(1) << 64) - 1;
    uint64_t vec[2];
    vec[0] = m_value & mask;  // least significant word
    vec[1] = m_value >> 64;   // most significant word
    ar(::cereal::binary_data(vec, sizeof(vec)));
  }

  template <class Archive>
  typename std::enable_if<std::is_same<NativeInt, U128BITS>::value &&
                              cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    // save 2 unint64_t values instead of unsigned __int128
    constexpr U128BITS mask = (static_cast<U128BITS>(1) << 64) - 1;
    uint64_t vec[2];
    vec[0] = m_value & mask;  // least significant word
    vec[1] = m_value >> 64;   // most significant word
    ar(::cereal::make_nvp("i", vec));
  }
#endif

  std::string SerializedObjectName() const { return "NATInteger"; }

  static uint32_t SerializedVersion() { return 1; }

  static constexpr unsigned MaxBits() { return m_uintBitLength; }

  static bool IsNativeInt() { return true; }
protected成员
 protected:
  /**
   * Converts the string v into base-r integer where r is equal to 2^bitwidth
   * of integral data type.
   *
   * @param v The input string
   */
  void AssignVal(const std::string &str) {
    NativeInt test_value = 0;
    m_value = 0;
    for (size_t i = 0; i < str.length(); i++) {
      int v = str[i] - '0';
      if (v < 0 || v > 9) {
        PALISADE_THROW(lbcrypto::type_error, "String contains a non-digit");
      }
      m_value *= 10;
      m_value += v;

      if (m_value < test_value) {
        PALISADE_THROW(
            lbcrypto::math_error,
            str + " is too large to fit in this native integer object");
      }
      test_value = m_value;
    }
  }
private成员
 private:
  // representation as a
  NativeInt m_value;

  // variable to store the bit width of the integral data type.
  static constexpr unsigned m_uintBitLength = sizeof(NativeInt) * 8;    // constexpr 意思是计算出来结果不会改变,放在编译阶段计算。
  // variable to store the maximum value of the integral data type.
  static constexpr NativeInt m_uintMax = std::numeric_limits<NativeInt>::max();

  static constexpr NativeInt NATIVEINTMASK = NativeInt(~0);

  /**
   * AddCheck is the addition operation with bounds checking.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  inline NativeIntegerT AddCheck(const NativeIntegerT &b) const {
    NativeInt newv = m_value + b.m_value;
    if (newv < m_value || newv < b.m_value) {
      PALISADE_THROW(lbcrypto::math_error, "Overflow");
    }
    return newv;
  }

  /**
   * AddFast is the addition operation without bounds checking.
   *
   * @param b is the value to add to this.
   * @return result of the addition operation.
   */
  inline NativeIntegerT AddFast(const NativeIntegerT &b) const {
    return m_value + b.m_value;
  }

  // Computes res -= a;
  static inline void SubtractD(typeD &res, const typeD &a) {
    if (res.lo < a.lo) {
      res.lo += m_uintMax + 1 - a.lo;
      res.hi--;
    } else {
      res.lo -= a.lo;
    }

    res.hi -= a.hi;
  }

  /**
   * Right shifts a typeD integer by a specific number of bits
   * and stores the result as a single-word integer.
   *
   * @param &x double-word input
   * @param shift the number of bits to shift by
   * @return the result of right-shifting
   */
  static inline NativeInt RShiftD(const typeD &x, long shift) {
    return (x.lo >> shift) | (x.hi << (MaxBits() - shift));
  }

  /**
   * Multiplies two single-word integers and stores the result in a
   * typeD data structure. Currently this is hard-coded to 64-bit
   * words on a x86-64 or arm64 processor
   *
   * @param a multiplier
   * @param b multiplicand
   * @param &x result of multiplication
   */
  static inline void MultD(U64BITS a, U64BITS b, typeD &res) {
#if defined(__x86_64__)
    // clang-format off
    __asm__("mulq %[b]"
            : [ lo ] "=a"(res.lo), [ hi ] "=d"(res.hi)
            : [ a ] "%[lo]"(a), [ b ] "rm"(b)
            : "cc");
    // clang-format on
#elif defined(__aarch64__)
    typeD x;
    x.hi = 0;
    x.lo = a;
    U64BITS y(b);
    res.lo = x.lo * y;
    asm("umulh %0, %1, %2\n\t" : "=r"(res.hi) : "r"(x.lo), "r"(y));
    res.hi += x.hi * y;
#elif defined(__arm__) // 32 bit processor
    uint64_t wres(0), wa(a), wb(b);

    wres = wa * wb;  // should give us the lower 64 bits of 32*32
    res.hi = wres >> 32;
    res.lo = (uint32_t)wres && 0xFFFFFFFF;
#elif defined(__EMSCRIPTEN__)  // web assembly
    U64BITS a1 = a >> 32;
    U64BITS a2 = (uint32_t)a;
    U64BITS b1 = b >> 32;
    U64BITS b2 = (uint32_t)b;

    // use schoolbook multiplication
    res.hi = a1 * b1;
    res.lo = a2 * b2;
    U64BITS lowBefore = res.lo;

    U64BITS p1 = a2 * b1;
    U64BITS p2 = a1 * b2;
    U64BITS temp = p1 + p2;
    res.hi += temp >> 32;
    res.lo += U64BITS((uint32_t)temp) << 32;

    // adds the carry to the high word
    if (lowBefore > res.lo) res.hi++;

    // if there is an overflow in temp, add 2^32
    if ((temp < p1) || (temp < p2)) res.hi += (U64BITS)1 << 32;
#else
#error Architecture not supported for MultD()
#endif
  }

#if defined(HAVE_INT128)
  static inline void MultD(U128BITS a, U128BITS b, typeD &res) {
    // TODO: The performance of this function can be improved
    // Instead of 128-bit multiplication, we can use MultD from bigintnat
    // We would need to introduce a struct of 4 64-bit integers in this case
    U128BITS a1 = a >> 64;
    U128BITS a2 = (uint64_t)a;
    U128BITS b1 = b >> 64;
    U128BITS b2 = (uint64_t)b;

    // use schoolbook multiplication
    res.hi = a1 * b1;
    res.lo = a2 * b2;
    U128BITS lowBefore = res.lo;

    U128BITS p1 = a2 * b1;
    U128BITS p2 = a1 * b2;
    U128BITS temp = p1 + p2;
    res.hi += temp >> 64;
    res.lo += U128BITS((uint64_t)temp) << 64;

    // adds the carry to the high word
    if (lowBefore > res.lo) res.hi++;

    // if there is an overflow in temp, add 2^64
    if ((temp < p1) || (temp < p2)) res.hi += (U128BITS)1 << 64;
  }
#endif

  static inline void MultD(U32BITS a, U32BITS b, typeD &res) {
    DNativeInt prod = DNativeInt(a) * DNativeInt(b);
    res.hi = (prod >> MaxBits()) & NATIVEINTMASK;
    res.lo = prod & NATIVEINTMASK;
  }

  /**
   * Multiplies two single-word integers and stores the high word of the
   * result
   *
   * @param a multiplier
   * @param b multiplicand
   * @return the high word of the result
   */
  static inline NativeInt MultDHi(NativeInt a, NativeInt b) {
    typeD x;
    MultD(a, b, x);
    return x.hi;
  }

  /**
   * Converts a double-word integer from typeD representation
   * to DNativeInt.
   *
   * @param &x double-word input
   * @return the result as DNativeInt
   */
  inline DNativeInt GetD(const typeD &x) const {
    return (DNativeInt(x.hi) << MaxBits()) | x.lo;
  }

  static inline std::string toString(uint32_t value) {
    return std::to_string(value);
  }

  static inline std::string toString(uint64_t value) {
    return std::to_string(value);
  }

#if defined(HAVE_INT128)
  static inline std::string toString(unsigned __int128 value) {
    constexpr uint32_t maxChars = 15;  // max number of digits/chars we may have
                                       // in every part after division below

    const uint64_t divisor = std::llrint(pow(10, maxChars));
    uint64_t part3 = value % divisor;
    value /= divisor;
    uint64_t part2 = value % divisor;
    value /= divisor;
    uint64_t part1 = value % divisor;
    value /= divisor;

    std::string ret;
    ret.reserve(64);  // should be more than enough to store the value of a
                      // 128-bit integer

    bool appendNextPart = false;
    if (part1) {
      ret = std::to_string(part1);
      appendNextPart = true;
    }

    if (part2) {
      std::string part2str(std::to_string(part2));
      if (appendNextPart) {
        ret += std::string(maxChars - part2str.size(), '0');
        ret += part2str;
      } else {
        ret = part2str;
        appendNextPart = true;
      }
    } else if (appendNextPart) {
      ret += std::string(maxChars, '0');  // add zeroes only
    }

    if (part3) {
      std::string part3str(std::to_string(part3));
      if (appendNextPart) {
        ret += std::string(maxChars - part3str.size(), '0');
        ret += part3str;
      } else {
        ret = part3str;
      }
    } else if (appendNextPart) {
      ret += std::string(maxChars, '0');
    } else {
      ret = "0";
    }

    return ret;
    /*
     * The following implementation doesn't works as fast as the implementation
     * above, but is much shorter...:
     */
    /*
   {
   // 64 bytes should be more than enough to store the value of a 128-bit
   integer
   // and we will keep the terminating zero at the buffer end
   char retBuff[64] = {0};
   char* ptr = &retBuff[63];
   while( value ) {
    *(--ptr) = '0' + value % 10;
    value /= 10;
    }
    return std::string(ptr);
    }
    */
  }
#endif
};

}  // namespace bigintnat

#endif  // LBCRYPTO_MATH_BIGINTNAT_UBINTNAT_H

\core\include\math\bigintnat\mubintvecnat.h

This file contains the vector manipulation functionality for native integers.

#ifndef LBCRYPTO_MATH_BIGINTNAT_MUBINTVECNAT_H
#define LBCRYPTO_MATH_BIGINTNAT_MUBINTVECNAT_H

#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>

#include "math/interface.h"
#include "utils/inttypes.h"
#include "utils/serializable.h"

#include "utils/blockAllocator/xvector.h"

// the following should be set to 1 in order to have native vector use block
// allocations then determine if you want dynamic or static allocations by
// settingdefining STAIC_POOLS on line 24 of
// xallocator.cpp
#define BLOCK_VECTOR_ALLOCATION 0  // set to 1 to use block allocations
/**
 * @namespace bigintnat
 * The namespace of bigintnat
 */
namespace bigintnat {

/**
 * @brief The class for representing vectors of native integers.
 */

#if 0  // allocator that reports bytes used.
template <class Tp>
struct NAlloc {
    typedef Tp value_type;
    NAlloc() = default;
    template <class T> NAlloc(const NAlloc<T>&) {}
    Tp* allocate(std::size_t n) {
        n *= sizeof(Tp);
        return static_cast<Tp*>(::operator new(n));
    }
    void deallocate(Tp* p, std::size_t n) {
        std::cout << "deallocating " << n*sizeof*p << " bytes\n";
        ::operator delete(p);
    }
};
template <class T, class U>
bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; }
template <class T, class U>
bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; }
#endif

#if 0  // allocator that reports bytes used.
template <class Tp>
struct NAlloc {
    typedef Tp value_type;
    NAlloc() = default;
    template <class T> NAlloc(const NAlloc<T>&) {}
    Tp* allocate(std::size_t n) {
        n *= sizeof(Tp);
        std::cout << "allocating   " << n << " bytes\n";
        return static_cast<Tp*>(::operator new(n));
    }
    void deallocate(Tp* p, std::size_t n) {
        std::cout << "deallocating " << n*sizeof*p << " bytes\n";
        ::operator delete(p);
    }
};
template <class T, class U>
bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; }
template <class T, class U>
bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; }
#endif

构造函数们
template <class IntegerType>
class NativeVector
    : public lbcrypto::BigVectorInterface<NativeVector<IntegerType>,
                                          IntegerType>,
      public lbcrypto::Serializable {
 public:
  typedef IntegerType BVInt;

  // CONSTRUCTORS

  /**
   * Basic constructor.
   */
  NativeVector();

  static inline NativeVector Single(const IntegerType &val,
                                    const IntegerType &modulus) {
    NativeVector vec(1, modulus);
    vec[0] = val;
    return vec;
  }

  /**
   * Basic constructor for specifying the length of the vector.
   *
   * @param length is the length of the native vector, in terms of the number of
   * entries.
   */
  explicit NativeVector(usint length);

  /**
   * Basic constructor for specifying the length of the vector and the modulus.
   *
   * @param length is the length of the native vector, in terms of the number of
   * entries.
   * @param modulus is the modulus of the ring.
   */
  NativeVector(usint length, const IntegerType &modulus);

  /**
   * Basic constructor for copying a vector
   *
   * @param bigVector is the native vector to be copied.
   */
  NativeVector(const NativeVector &bigVector);

  /**
   * Basic move constructor for moving a vector
   *
   * @param &&bigVector is the native vector to be moved.
   */
  NativeVector(NativeVector &&bigVector);  // move copy constructor

  /**
   * Basic constructor for specifying the length of the vector
   * the modulus and an initializer list.
   *
   * @param length is the length of the native vector, in terms of the number of
   * entries.
   * @param modulus is the modulus of the ring.
   * @param rhs is an initializer list of strings
   */

  NativeVector(usint length, const IntegerType &modulus,
               std::initializer_list<std::string> rhs);

  /**
   * Basic constructor for specifying the length of the vector
   * the modulus and an initializer list.
   *
   * @param length is the length of the native vector, in terms of the number of
   * entries.
   * @param modulus is the modulus of the ring.
   * @param rhs is an initializer list of usint
   */
  NativeVector(usint length, const IntegerType &modulus,
               std::initializer_list<uint64_t> rhs);

  /**
   * Destructor.
   */
  virtual ~NativeVector();
赋值函数
  // ASSIGNMENT OPERATORS

  /**
   * Assignment operator to assign value from rhs
   *
   * @param &rhs is the native vector to be assigned from.
   * @return Assigned NativeVector.
   */
  const NativeVector &operator=(const NativeVector &rhs);

  /**
   * Move assignment operator
   *
   * @param &&rhs is the native vector to be moved.
   * @return moved NativeVector object
   */
  NativeVector &operator=(NativeVector &&rhs);

  /**
   * Initializer list for NativeVector.
   *
   * @param &&rhs is the list of strings containing integers to be assigned to
   * the BBV.
   * @return NativeVector object
   */
  const NativeVector &operator=(std::initializer_list<std::string> rhs);

  /**
   * Initializer list for NativeVector.
   *
   * @param &&rhs is the list of integers to be assigned to the BBV.
   * @return NativeVector object
   */
  const NativeVector &operator=(std::initializer_list<uint64_t> rhs);

  /**
   * Assignment operator to assign value val to first entry, 0 for the rest of
   * entries.
   *
   * @param val is the value to be assigned at the first entry.
   * @return Assigned NativeVector.
   */
  inline const NativeVector &operator=(uint64_t val) {
    this->m_data[0] = val;
    for (size_t i = 1; i < GetLength(); ++i) {
      this->m_data[i] = 0;
    }
    return *this;
  }
Accessors
  // ACCESSORS

  /**
   * Sets/gets a value at an index.
   * This method is slower than operator[] as it checks if index out of range
   *
   * @param index is the index to set a value at.
   */
  IntegerType &at(size_t i) {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "NativeVector index out of range");
    }
    return this->m_data[i];
  }

  const IntegerType &at(size_t i) const {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "NativeVector index out of range");
    }
    return this->m_data[i];
  }

  /**
   * operators to get a value at an index.
   * @param idx is the index to get a value at.
   * @return is the value at the index. return nullptr if invalid index.
   */
  IntegerType &operator[](size_t idx) { return (this->m_data[idx]); }

  const IntegerType &operator[](size_t idx) const {
    return (this->m_data[idx]);
  }

  /**
   * Sets the vector modulus.
   *
   * @param value is the value to set.
   * @param value is the modulus value to set.
   */
  void SetModulus(const IntegerType &value);

  /**
   * Sets the vector modulus and changes the values to match the new modulus.
   *
   * @param value is the value to set.
   */
  void SwitchModulus(const IntegerType &value);

  /**
   * Gets the vector modulus.
   *
   * @return the vector modulus.
   */
  const IntegerType &GetModulus() const;

  /**
   * Gets the vector length.
   *
   * @return vector length.
   */
  size_t GetLength() const { return this->m_data.size(); }
模算术函数
  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Vector Modulus operator.
   *
   * @param modulus is the modulus to perform on the current vector entries.
   * @return is the result after the modulus operation on current vector.
   */
  NativeVector Mod(const IntegerType &modulus) const;

  /**
   * Vector Modulus operator. In-place variant.
   *
   * @param modulus is the modulus to perform on the current vector entries.
   * @return is the result after the modulus operation on current vector.
   */
  const NativeVector &ModEq(const IntegerType &modulus);

  /**
   * Scalar modulus addition.
   *
   * After addition modulus operation is performed with the current vector
   * modulus.
   * @return is the result of the modulus addition operation.
   */
  NativeVector ModAdd(const IntegerType &b) const;

  /**
   * Scalar modulus addition. In-place variant.
   *
   * After addition modulus operation is performed with the current vector
   * modulus.
   * @return is the result of the modulus addition operation.
   */
  const NativeVector &ModAddEq(const IntegerType &b);

  /**
   * Scalar modulus addition at a particular index.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  NativeVector ModAddAtIndex(usint i, const IntegerType &b) const;

  /**
   * Scalar modulus addition at a particular index. In-place variant.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  const NativeVector &ModAddAtIndexEq(usint i, const IntegerType &b);

  /**
   * vector modulus addition.
   *
   * @param &b is the vector to add at all locations.
   * @return is the result of the modulus addition operation.
   */
  NativeVector ModAdd(const NativeVector &b) const;

  /**
   * vector modulus addition. In-place variant.
   *
   * @param &b is the vector to add at all locations.
   * @return is the result of the modulus addition operation.
   */
  const NativeVector &ModAddEq(const NativeVector &b);

  /**
   * Scalar modulus subtraction.
   * After substraction modulus operation is performed with the current vector
   * modulus.
   * @param &b is the scalar to subtract from all locations.
   * @return is the result of the modulus substraction operation.
   */
  NativeVector ModSub(const IntegerType &b) const;

  /**
   * Scalar modulus subtraction. In-place variant.
   * After substraction modulus operation is performed with the current vector
   * modulus.
   * @param &b is the scalar to subtract from all locations.
   * @return is the result of the modulus substraction operation.
   */
  const NativeVector &ModSubEq(const IntegerType &b);

  /**
   * Vector Modulus subtraction.
   *
   * @param &b is the vector to subtract.
   * @return is the result of the modulus subtraction operation.
   */
  NativeVector ModSub(const NativeVector &b) const;

  /**
   * Vector Modulus subtraction. In-place variant.
   *
   * @param &b is the vector to subtract.
   * @return is the result of the modulus subtraction operation.
   */
  const NativeVector &ModSubEq(const NativeVector &b);

  /**
   * Scalar modular multiplication.
   * See the comments in the cpp files for details of the implementation.
   *
   * @param &b is the scalar to multiply at all locations.
   * @return is the result of the modulus multiplication operation.
   */
  NativeVector ModMul(const IntegerType &b) const;

  /**
   * Scalar modular multiplication. In-place variant.
   * See the comments in the cpp files for details of the implementation.
   *
   * @param &b is the scalar to multiply at all locations.
   * @return is the result of the modulus multiplication operation.
   */
  const NativeVector &ModMulEq(const IntegerType &b);

  /**
   * Vector modulus multiplication.
   *
   * @param &b is the vector to multiply.
   * @return is the result of the modulus multiplication operation.
   */
  NativeVector ModMul(const NativeVector &b) const;

  /**
   * Vector modulus multiplication. In-place variant.
   *
   * @param &b is the vector to multiply.
   * @return is the result of the modulus multiplication operation.
   */
  const NativeVector &ModMulEq(const NativeVector &b);

  /**
   * Vector multiplication without applying the modulus operation.
   *
   * @param &b is the vector to multiply.
   * @return is the result of the multiplication operation.
   */
  NativeVector MultWithOutMod(const NativeVector &b) const;

  /**
   * Scalar modulus exponentiation.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @return a new vector which is the result of the modulus exponentiation
   * operation.
   */
  NativeVector ModExp(const IntegerType &b) const;

  /**
   * Scalar modulus exponentiation. In-place variant.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @return a new vector which is the result of the modulus exponentiation
   * operation.
   */
  const NativeVector &ModExpEq(const IntegerType &b);

  /**
   * Modulus inverse.
   *
   * @return a new vector which is the result of the modulus inverse operation.
   */
  NativeVector ModInverse() const;

  /**
   * Modulus inverse. In-place variant.
   *
   * @return a new vector which is the result of the modulus inverse operation.
   */
  const NativeVector &ModInverseEq();

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

  /**
   * Perform a modulus by 2 operation.  Returns the least significant bit.
   * In-place variant.
   *
   * @return a new vector which is the return value of the modulus by 2, also
   * the least significant bit.
   */
  const NativeVector &ModByTwoEq();

  /**
   * Multiply and Rounding operation on a BigInteger x. Returns [x*p/q] where []
   * is the rounding operation.
   *
   * @param p is the numerator to be multiplied.
   * @param q is the denominator to be divided.
   * @return the result of multiply and round.
   */
  NativeVector MultiplyAndRound(const IntegerType &p,
                                const IntegerType &q) const;

  /**
   * Multiply and Rounding operation on a BigInteger x. Returns [x*p/q] where []
   * is the rounding operation. In-place variant.
   *
   * @param p is the numerator to be multiplied.
   * @param q is the denominator to be divided.
   * @return the result of multiply and round.
   */
  const NativeVector &MultiplyAndRoundEq(const IntegerType &p,
                                         const IntegerType &q);
  

  

  /**
   * Divide and Rounding operation on a BigInteger x. Returns [x/q] where [] is
   * the rounding operation.
   *
   * @param q is the denominator to be divided.
   * @return the result of divide and round.
   */
  NativeVector DivideAndRound(const IntegerType &q) const;

  /**
   * Divide and Rounding operation on a BigInteger x. Returns [x/q] where [] is
   * the rounding operation. In-place variant.
   *
   * @param q is the denominator to be divided.
   * @return the result of divide and round.
   */
  const NativeVector &DivideAndRoundEq(const IntegerType &q);

  // OTHER FUNCTIONS

  /**
   * Digit vector at a specific index for all entries for a given number base.
   * Warning: only power-of-2 bases are currently supported.
   * Example: for vector (83, 1, 45), index 2 and base 4 we have:
   *
   *                           index:0,1,2,3
   * |83|                           |3,0,1,1|                 |1|
   * |1 | --base 4 decomposition--> |1,0,0,0| --at index 2--> |0|
   * |45|                           |1,3,2,0|                 |2|
   *
   * The return vector is (1,0,2)
   *
   * @param index is the index to return the digit from in all entries.
   * @param base is the base to use for the operation.
   * @return is the digit at a specific index for all entries for a given number
   * base
   */
  NativeVector GetDigitAtIndexForBase(usint index, usint base) const;
输出函数
  // STRINGS & STREAMS

  /**
   * ostream operator to output vector values to console
   *
   * @param os is the std ostream object.
   * @param &ptr_obj is the NativeVector object to be printed.
   * @return std ostream object which captures the vector values.
   */
  template <class IntegerType_c>
  friend std::ostream &operator<<(std::ostream &os,
                                  const NativeVector<IntegerType_c> &ptr_obj) {
    auto len = ptr_obj.m_data.size();
    os << "[";
    for (usint i = 0; i < len; i++) {
      os << ptr_obj.m_data[i];
      os << ((i == (len - 1)) ? "]" : " ");
    }
    os << " modulus: " << ptr_obj.m_modulus;
    return os;
  }
序列化
  // SERIALIZATION

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ::cereal::size_type size = m_data.size();
    ar(size);
    if (size > 0) {
      ar(::cereal::binary_data(m_data.data(), size * sizeof(IntegerType)));
    }
    ar(m_modulus);
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_data));
    ar(::cereal::make_nvp("m", m_modulus));
  }

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ::cereal::size_type size;
    ar(size);
    m_data.resize(size);
    if (size > 0) {
      auto *data =
          reinterpret_cast<IntegerType *>(malloc(size * sizeof(IntegerType)));
      ar(::cereal::binary_data(data, size * sizeof(IntegerType)));
      for (::cereal::size_type i = 0; i < size; i++) {
        m_data[i] = data[i];
      }
      free(data);
    }
    ar(m_modulus);
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_data));
    ar(::cereal::make_nvp("m", m_modulus));
  }

  std::string SerializedObjectName() const { return "NativeVector"; }

  static uint32_t SerializedVersion() { return 1; }
private成员
 private:
  // m_data is a pointer to the vector

#if BLOCK_VECTOR_ALLOCATION != 1
  std::vector<IntegerType> m_data;
#else
  xvector<IntegerType> m_data;
#endif
  // m_modulus stores the internal modulus of the vector.
  IntegerType m_modulus = 0;

  // function to check if the index is a valid index.
  bool IndexCheck(size_t length) const {
    if (length > this->m_data.size()) {
      return false;
    }
    return true;
  }
};

}  // namespace bigintnat
namespace cereal {

//! Serialization for vector of NativeInteger

template <class Archive, class A>
inline void CEREAL_SAVE_FUNCTION_NAME(
    Archive &ar,
    std::vector<bigintnat::NativeIntegerT<uint64_t>, A> const &vector) {
  ar(make_size_tag(
      static_cast<cereal::size_type>(vector.size())));  // number of elements
  for (const auto& v : vector) {
    ar(v.ConvertToInt());
  }
}

#if defined(HAVE_INT128)
template <class Archive, class A>
inline void CEREAL_SAVE_FUNCTION_NAME(
    Archive &ar,
    std::vector<bigintnat::NativeIntegerT<unsigned __int128>, A> const
        &vector) {
  ar(make_size_tag(
      static_cast<cereal::size_type>(vector.size())));  // number of elements
  constexpr unsigned __int128 mask =
      (static_cast<unsigned __int128>(1) << 64) - 1;
  for (const auto& v : vector) {
    uint64_t vec[2];
    unsigned __int128 int128 = v.ConvertToInt();
    vec[0] = int128 & mask;  // least significant word
    vec[1] = int128 >> 64;   // most significant word
    ar(vec);
  }
}
#endif

//! Deserialization for vector of NativeInteger

template <class Archive, class A>
inline void CEREAL_LOAD_FUNCTION_NAME(
    Archive &ar, std::vector<bigintnat::NativeIntegerT<uint64_t>, A> &vector) {
  cereal::size_type size;
  ar(make_size_tag(size));
  vector.resize(static_cast<size_t>(size));
  for (auto &v : vector) {
    uint64_t b;
    ar(b);
    v = b;
  }
}

#if defined(HAVE_INT128)
template <class Archive, class A>
inline void CEREAL_LOAD_FUNCTION_NAME(
    Archive &ar,
    std::vector<bigintnat::NativeIntegerT<unsigned __int128>, A> &vector) {
  cereal::size_type size;
  ar(make_size_tag(size));
  vector.resize(static_cast<size_t>(size));
  for (auto &v : vector) {
    uint64_t vec[2];
    ar(vec);
    v = vec[1];  // most significant word
    v <<= 64;
    v += vec[0];  // least significant word
  }
}
#endif
}  // namespace cereal

#endif  // LBCRYPTO_MATH_BIGINTNAT_MUBINTVECNAT_H

\core\include\math\bigintfxd\ubintfxd.h

This file contains the main class for big integers: BigInteger. Big integers are represented as arrays of native usigned integers. The native integer type is supplied as a template parameter. Currently implementations based on uint8_t, uint16_t, and uint32_t are supported. The second template parameter is the maximum bitwidth for the big integer.

/**
 *@namespace bigintfxd
 * The namespace of bigintfxd
 */
namespace bigintfxd {

using U64BITS = uint64_t;
#if defined(HAVE_INT128)
using U128BITS = unsigned __int128;
#endif

下面的代码利用了模板元编程

/**The following structs are needed for initialization of BigInteger at the
 *preprocessing stage. The structs compute certain values using template
 *metaprogramming approach and mostly follow recursion to calculate value(s).
 */

/**
 * @brief  Struct to find log value of N.
 *Needed in the preprocessing step of BigInteger to determine bitwidth.
 *
 * @tparam N bitwidth.
 */
template <usint N>
struct Log2 {
  static const usint value = 1 + Log2<N / 2>::value;
};

/**
 * @brief Struct to find log value of N.
 *Base case for recursion.
 *Needed in the preprocessing step of BigInteger to determine bitwidth.
 */
template <>
struct Log2<2> {
  static const usint value = 1;
};
/**
 * @brief Struct to find log value of U where U is a primitive datatype.
 *Needed in the preprocessing step of BigInteger to determine bitwidth.
 *
 * @tparam U primitive data type.
 */
template <typename U>
struct LogDtype {
  static const usint value = Log2<8 * sizeof(U)>::value;
};
/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t}
 *
 * @tparam Dtype primitive datatype.
 */
template <typename Dtype>
struct DataTypeChecker {
  static const bool value = false;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t}. sets value true if datatype is unsigned integer 8 bit.
 */
template <>
struct DataTypeChecker<uint8_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t}. sets value true if datatype is unsigned integer 16 bit.
 */
template <>
struct DataTypeChecker<uint16_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t}. sets value true if datatype is unsigned integer 32 bit.
 */
template <>
struct DataTypeChecker<uint32_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t}. sets value true if datatype is unsigned integer 64 bit.
 */
template <>
struct DataTypeChecker<uint64_t> {
  static const bool value = true;
};
/**
 * @brief Struct for calculating bit width from data type.
 * Sets value to the bitwidth of uint_type
 *
 * @tparam uint_type native integer data type.
 */
template <typename uint_type>
struct UIntBitWidth {
  static const int value = 8 * sizeof(uint_type);
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type void for default case
 *
 * @tparam utype primitive integer data type.
 */
template <typename utype>
struct DoubleDataType {
  typedef void T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * Sets T as of type unsigned integer 16 bit if integral datatype is 8bit
 */
template <>
struct DoubleDataType<uint8_t> {
  typedef uint16_t T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 32 bit if integral datatype is 16bit
 */
template <>
struct DoubleDataType<uint16_t> {
  typedef uint32_t T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 64 bit if integral datatype is 32bit
 */
template <>
struct DoubleDataType<uint32_t> {
  typedef uint64_t T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 128 bit if integral datatype is 64bit
 */
template <>
struct DoubleDataType<uint64_t> {
#if defined(HAVE_INT128)
  typedef __uint128_t T;
#else
  typedef uint64_t T;
#endif
};
const double LOG2_10 =
    3.32192809;  //!< @brief A pre-computed constant of Log base 2 of 10.

class BigInteger

/**
 * @brief Main class for big integers represented as an array of native
 * (primitive) unsigned integers
 * @tparam uint_type native unsigned integer type
 * @tparam BITLENGTH maximum bitwidth supported for big integers
 */
template <typename uint_type, usint BITLENGTH>
class BigInteger
    : public lbcrypto::BigIntegerInterface<BigInteger<uint_type, BITLENGTH>> {
 public:

私有成员

 private:
  // array storing the native integers.
  // array size is the ceiling of BITLENGTH/(bits in the integral data type)
  uint_type m_value[(BITLENGTH + 8 * sizeof(uint_type) - 1) /
                    (8 * sizeof(uint_type))];

  // variable that stores the MOST SIGNIFICANT BIT position in the number.
  usshort m_MSB;

  // variable to store the bit width of the integral data type.
  static const uschar m_uintBitLength;

  // variable to store the maximum value of the integral data type.
  static const uint_type m_uintMax;

  // variable to store the log(base 2) of the number of bits in the integral
  // data type.
  static const uschar m_logUintBitLength;

  // variable to store the size of the data array.
  static const usint m_nSize;

  // The maximum number of digits in BigInteger. It is used by the cout(ostream)
  // function for printing the bigbinarynumber.
  static const usint m_numDigitInPrintval;

  /**
   * function to return the ceiling of the number divided by the number of bits
   * in the integral data type.
   * @param Number is the number to be divided.
   * @return the ceiling of Number/(bits in the integral data type)
   */
  static uint_type ceilIntByUInt(const uint_type Number);

  // currently unused array
  static const BigInteger *m_modChain;

  /**
   * function to return the MSB of number.
   * @param x is the number.
   * @return the MSB position in the number x.
   */

  static usint GetMSBUint_type(uint_type x);

  // Duint_type is the data type that has twice as many bits in the integral
  // data type.
  typedef typename DoubleDataType<uint_type>::T Duint_type;

  /**
   * function to return the MSB of number that is of type Duint_type.
   * @param x is the number.
   * @return the MSB position in the number x.
   */
  static usint GetMSBDUint_type(Duint_type x);

  /**
   * function that returns the BigInteger after multiplication by a uint.
   * @param b is the number to be multiplied.
   * @return the BigInteger after the multiplication.
   */
  BigInteger MulByUint(const uint_type b) const;

  /**
   * function that returns the BigInteger after multiplication by a uint.
   * @param b is the number to be multiplied.
   * @return the BigInteger after the multiplication.
   */
  void MulByUintToInt(const uint_type b, BigInteger *ans) const;

  /**
   * function that returns the decimal value from the binary array a.
   * @param a is a pointer to the binary array.
   * @return the decimal value.
   */
  static uint_type UintInBinaryToDecimal(uschar *a);

  /**
   * function that mutiplies by 2 to the binary array.
   * @param a is a pointer to the binary array.
   */
  static void double_bitVal(uschar *a);

  /**
   * function that adds bit b to the binary array.
   * @param a is a pointer to the binary array.
   * @param b is a bit value to be added.
   */
  static void add_bitVal(uschar *a, uschar b);
};

下面是public:

构造和析构函数

  // CONSTRUCTORS

  /**
   * Default constructor.
   */
  BigInteger();

  /**
   * Copy constructor.
   *
   * @param &val is the big binary integer to be copied.
   */
  BigInteger(const BigInteger &val);

  /**
   * Move constructor.
   *
   * @param &&val is the big binary integer to be copied.
   */
  BigInteger(BigInteger &&val);

  /**
   * Constructor from a string.
   *
   * @param &strval is the initial integer represented as a string.
   */
  explicit BigInteger(const std::string &strval);

  /**
   * Constructor from an unsigned integer.
   *
   * @param val is the initial integer represented as a uint64_t.
   */
  BigInteger(uint64_t val);
#if defined(HAVE_INT128)
  BigInteger(U128BITS val);
#endif

  /**
   * Constructors from smaller basic types
   *
   * @param val is the initial integer represented as a basic integer type.
   */
  BigInteger(int val) : BigInteger(uint64_t(val)) {}	// 初始化列表
  BigInteger(uint32_t val) : BigInteger(uint64_t(val)) {}
  BigInteger(long val) : BigInteger(uint64_t(val)) {}
  BigInteger(long long val) : BigInteger(uint64_t(val)) {}

  /**
   * Constructor from a NativeInteger
   *
   * @param &val is the initial integer represented as a native integer.
   */
  template <typename T>
  BigInteger(const bigintnat::NativeIntegerT<T> &val)
      : BigInteger(val.ConvertToInt()) {}

  /**
   * Constructor from double is not permitted
   *
   * @param val
   */
  BigInteger(double val)
      __attribute__((deprecated("Cannot construct from a double")));

  ~BigInteger() {}

赋值操作符

  // ASSIGNMENT OPERATORS

  /**
   * Copy assignment operator
   *
   * @param &val is the big binary integer to be assigned from.
   * @return assigned BigInteger ref.
   */
  const BigInteger &operator=(const BigInteger &val);

  /**
   * Move assignment operator
   *
   * @param &val is the big binary integer to be assigned from.
   * @return assigned BigInteger ref.
   */
  const BigInteger &operator=(BigInteger &&val);

  /**
   * Assignment operator from string
   *
   * @param strval is the string to be assigned from
   * @return the assigned BigInteger ref.
   */
  const BigInteger &operator=(const std::string strval) {
    *this = BigInteger(strval);
    return *this;
  }

  /**
   * Assignment operator from unsigned integer
   *
   * @param val is the unsigned integer to be assigned from.
   * @return the assigned BigInteger ref.
   */
  const BigInteger &operator=(uint64_t val) {
    *this = BigInteger(val);
    return *this;
  }

  /**
   * Assignment operator from native integer
   *
   * @param &val is the native integer to be assigned from.
   * @return the assigned BigInteger ref.
   */
  const BigInteger &operator=(const bigintnat::NativeInteger &val) {
    *this = BigInteger(val);
    return *this;
  }

ACCESSORS

  // ACCESSORS

  /**
   * Basic set method for setting the value of a big binary integer
   *
   * @param strval is the string representation of the big binary integer to be
   * copied.
   */
  void SetValue(const std::string &strval);

  /**
   * Basic set method for setting the value of a big binary integer
   *
   * @param val is the big binary integer representation of the big binary
   * integer to be assigned.
   */
  void SetValue(const BigInteger &val);

  /**
   *  Set this int to 1.
   */
  void SetIdentity() { *this = 1; }

  /**
   * Sets the int value at the specified index.
   *
   * @param index is the index of the int to set in the uint array.
   */
  void SetIntAtIndex(usint idx, uint_type value);

算术运算

  // ARITHMETIC OPERATIONS

  /**
   * Addition operation.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  BigInteger Add(const BigInteger &b) const;

  /**
   * Addition operation. In-place variant.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  const BigInteger &AddEq(const BigInteger &b);

  /**
   * Subtraction operation.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  BigInteger Sub(const BigInteger &b) const;

  /**
   * Subtraction operation. In-place variant.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  const BigInteger &SubEq(const BigInteger &b);

  /**
   * Operator for unary minus
   * @return
   */
  BigInteger operator-() const { return BigInteger(0).Sub(*this); }

  /**
   * Multiplication operation.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  BigInteger Mul(const BigInteger &b) const;

  /**
   * Multiplication operation. In-place variant.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  const BigInteger &MulEq(const BigInteger &b);

  /**
   * Division operation.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  BigInteger DividedBy(const BigInteger &b) const;

  /**
   * Division operation. In-place variant.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  const BigInteger &DividedByEq(const BigInteger &b);

  /**
   * Exponentiation operation. Returns x^p.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  BigInteger Exp(usint p) const;

  /**
   * Exponentiation operation. Returns x^p. In-place variant.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  const BigInteger &ExpEq(usint p);

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  BigInteger MultiplyAndRound(const BigInteger &p, const BigInteger &q) const;

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const BigInteger &MultiplyAndRoundEq(const BigInteger &p,
                                       const BigInteger &q);

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  BigInteger DivideAndRound(const BigInteger &q) const;

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const BigInteger &DivideAndRoundEq(const BigInteger &q);

  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Naive modulus operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  BigInteger Mod(const BigInteger &modulus) const;

  /**
   * Naive modulus operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  const BigInteger &ModEq(const BigInteger &modulus);

  /**
   * Pre-computes the mu factor that is used in Barrett modulo reduction
   *
   * @return the value of mu
   */
  BigInteger ComputeMu() const;

  /**
   * Barrett modulus operation.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  BigInteger Mod(const BigInteger &modulus, const BigInteger &mu) const;

  /**
   * Barrett modulus operation. In-place variant.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  const BigInteger &ModEq(const BigInteger &modulus, const BigInteger &mu);

  /**
   * Modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  BigInteger ModAdd(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const BigInteger &ModAddEq(const BigInteger &b, const BigInteger &modulus);

  /**
   * Modulus addition where operands are < modulus.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  BigInteger ModAddFast(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus addition where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const BigInteger &ModAddFastEq(const BigInteger &b,
                                 const BigInteger &modulus);

  /**
   * Barrett modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  BigInteger ModAdd(const BigInteger &b, const BigInteger &modulus,
                    const BigInteger &mu) const;

  /**
   * Barrett modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  const BigInteger &ModAddEq(const BigInteger &b, const BigInteger &modulus,
                             const BigInteger &mu);

  /**
   * Modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  BigInteger ModSub(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const BigInteger &ModSubEq(const BigInteger &b, const BigInteger &modulus);

  /**
   * Modulus subtraction where operands are < modulus.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  BigInteger ModSubFast(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus subtraction where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const BigInteger &ModSubFastEq(const BigInteger &b,
                                 const BigInteger &modulus);

  /**
   * Barrett modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  BigInteger ModSub(const BigInteger &b, const BigInteger &modulus,
                    const BigInteger &mu) const;

  /**
   * Barrett modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  const BigInteger &ModSubEq(const BigInteger &b, const BigInteger &modulus,
                             const BigInteger &mu);

  /**
   * Modulus multiplication operation.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  BigInteger ModMul(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus multiplication operation. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const BigInteger &ModMulEq(const BigInteger &b, const BigInteger &modulus);

  /**
   * Barrett modulus multiplication.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  BigInteger ModMul(const BigInteger &b, const BigInteger &modulus,
                    const BigInteger &mu) const;

  /**
   * Barrett modulus multiplication. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const BigInteger &ModMulEq(const BigInteger &b, const BigInteger &modulus,
                             const BigInteger &mu);

  /**
   * Modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  BigInteger ModMulFast(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus multiplication that assumes the operands are < modulus. In-place
   * variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const BigInteger &ModMulFastEq(const BigInteger &b,
                                 const BigInteger &modulus);

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  BigInteger ModMulFast(const BigInteger &b, const BigInteger &modulus,
                        const BigInteger &mu) const;

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   * In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const BigInteger &ModMulFastEq(const BigInteger &b, const BigInteger &modulus,
                                 const BigInteger &mu);

  BigInteger ModMulFastConst(const BigInteger &b, const BigInteger &modulus,
                             const BigInteger &bInv) const {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConst is not implemented for backend 2");
  }

  const BigInteger &ModMulFastConstEq(const BigInteger &b,
                                      const BigInteger &modulus,
                                      const BigInteger &bInv) {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConstEq is not implemented for backend 2");
  }

  /**
   * Modulus exponentiation operation. Square-and-multiply algorithm is used.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  BigInteger ModExp(const BigInteger &b, const BigInteger &modulus) const;

  /**
   * Modulus exponentiation operation. Square-and-multiply algorithm is used.
   * In-place variant.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  const BigInteger &ModExpEq(const BigInteger &b, const BigInteger &modulus);

  /**
   * Modulus inverse operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  BigInteger ModInverse(const BigInteger &modulus) const;

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  const BigInteger &ModInverseEq(const BigInteger &modulus);

移位运算

  // SHIFT OPERATIONS

  /**
   * Left shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  BigInteger LShift(usshort shift) const;

  /**
   * Left shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const BigInteger &LShiftEq(usshort shift);

  /**
   * Right shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  BigInteger RShift(usshort shift) const;

  /**
   * Right shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const BigInteger &RShiftEq(usshort shift);

比较运算

  // COMPARE

  /**
   * Compares the current BigInteger to BigInteger a.
   *
   * @param a is the BigInteger to be compared with.
   * @return  -1 for strictly less than, 0 for equal to and 1 for strictly
   * greater than conditons.
   */
  int Compare(const BigInteger &a) const;

转换类型

  // CONVERTERS

  /**
   * Converts the value to an int.
   *
   * @return the int representation of the value as uint64_t.
   */
  template <typename T = bigintnat::BasicInteger>
  T ConvertToInt() const {
    T result = 0;
    // set num to number of equisized chunks
    // usint num = bigintnat::NativeIntegerT<T>::MaxBits() / m_uintBitLength;
    usint num = bigintnat::NativeIntegerT<T>().MaxBits() / m_uintBitLength;
    usint ceilInt = m_nSize - ceilIntByUInt(m_MSB);
    // copy the values by shift and add
    for (usint i = 0; i < num && (m_nSize - i - 1) >= ceilInt; i++) {
      result += ((T)this->m_value[m_nSize - i - 1] << (m_uintBitLength * i));
    }
    if (this->m_MSB > bigintnat::NativeIntegerT<T>::MaxBits()) {
      PALISADE_THROW(
          lbcrypto::math_error,
          std::string("MSB cannot be bigger than ") +
              std::to_string(bigintnat::NativeIntegerT<T>::MaxBits()));
    }
    return result;
  }

  /**
   * Converts the value to an double.
   *
   * @return double representation of the value.
   */
  double ConvertToDouble() const;

  /**
   * Convert a value from an int to a BigInteger.
   *
   * @param m the value to convert from.
   * @return int represented as a big binary int.
   */
  static BigInteger intToBigInteger(usint m);

  /**
   * Convert a string representation of a binary number to a decimal BigInteger.
   *
   * @param bitString the binary num in string.
   * @return the binary number represented as a big binary int.
   */
  static BigInteger FromBinaryString(const std::string &bitString);

其它函数

  // OTHER FUNCTIONS

  /**
   * Returns the MSB location of the value.
   *
   * @return the index of the most significant bit.
   */
  usint GetMSB() const;

  /**
   * Get the number of digits using a specific base - support for arbitrary base
   * may be needed.
   *
   * @param base is the base with which to determine length in.
   * @return the length of the representation in a specific base.
   */
  usint GetLengthForBase(usint base) const { return GetMSB(); }

  /**
   * Get a specific digit at "digit" index; big integer is seen as an array of
   * digits, where a 0 <= digit < base Warning: only power-of-2 bases are
   * currently supported. Example: for number 83, index 2 and base 4 we have:
   *
   *                         index:0,1,2,3
   * 83 --base 4 decomposition--> (3,0,1,1) --at index 2--> 1
   *
   * The return number is 1.
   *
   * @param index is the "digit" index of the requested digit
   * @param base is the base with which to determine length in.
   * @return is the requested digit
   */
  usint GetDigitAtIndexForBase(usint index, usint base) const;

  /**
   * Tests whether the BigInteger is a power of 2.
   *
   * @param m_numToCheck is the value to check.
   * @return true if the input is a power of 2, false otherwise.
   */
  bool CheckIfPowerOfTwo(const BigInteger &m_numToCheck);

  /**
   * Gets the bit at the specified index.
   *
   * @param index is the index of the bit to get.
   * @return resulting bit.
   */
  uschar GetBitAtIndex(usint index) const;

  /**
   * A zero allocator that is called by the Matrix class. It is used to
   * initialize a Matrix of BigInteger objects.
   */
  static BigInteger Allocator() { return 0; }

toString

  // STRINGS & STREAMS

  /**
   * Stores the based 10 equivalent/Decimal value of the BigInteger in a string
   * object and returns it.
   *
   * @return value of this BigInteger in base 10 represented as a string.
   */
  const std::string ToString() const;

  static const std::string IntegerTypeName() { return "UBFIXINT"; }

  /**
   * Delivers value of the internal limb storage
   * Used primarily for debugging
   * @return STL vector of uint_type
   */
  std::string GetInternalRepresentation(void) const {
    std::string ret("");
    size_t ceilInt = ceilIntByUInt(this->m_MSB);  // max limb used

    for (size_t i = m_nSize - 1; i >= (size_t)(m_nSize - ceilInt); i--) {
      ret += std::to_string(m_value[i]);
      if (i != (size_t)(m_nSize - ceilInt)) ret += " ";
    }
    return ret;
  }

  /**
   * Console output operation.
   *
   * @param os is the std ostream object.
   * @param ptr_obj is BigInteger to be printed.
   * @return is the ostream object.
   */
  template <typename uint_type_c, usint BITLENGTH_c>
  friend std::ostream &operator<<(
      std::ostream &os, const BigInteger<uint_type_c, BITLENGTH_c> &ptr_obj) {
    usint counter;
    // initiate to object to be printed
    auto print_obj = new BigInteger<uint_type_c, BITLENGTH_c>(ptr_obj);
    // print_VALUE array stores the decimal value in the array
    uschar *print_VALUE = new uschar[ptr_obj.m_numDigitInPrintval];
    for (size_t i = 0; i < ptr_obj.m_numDigitInPrintval; i++) {
      // reset to zero
      *(print_VALUE + i) = 0;
    }
    // starts the conversion from base r to decimal value
    for (size_t i = print_obj->m_MSB; i > 0; i--) {
      // print_VALUE = print_VALUE*2
      BigInteger<uint_type_c, BITLENGTH_c>::double_bitVal(print_VALUE);
      // adds the bit value to the print_VALUE
      BigInteger<uint_type_c, BITLENGTH_c>::add_bitVal(
          print_VALUE, print_obj->GetBitAtIndex(i));
    }
    // find the first occurence of non-zero value in print_VALUE
    for (counter = 0; counter < ptr_obj.m_numDigitInPrintval - 1; counter++) {
      if (static_cast<int>(print_VALUE[counter]) != 0) {
        break;
      }
    }
    // start inserting values into the ostream object
    for (; counter < ptr_obj.m_numDigitInPrintval; counter++) {
      os << static_cast<int>(print_VALUE[counter]);
    }
    // deallocate the memory since values are inserted into the ostream object
    delete[] print_VALUE;
    delete print_obj;
    return os;
  }

序列化

  // SERIALIZATION

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::binary_data(m_value, sizeof(m_value)));
    ar(::cereal::binary_data(&m_MSB, sizeof(m_MSB)));
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_value));
    ar(::cereal::make_nvp("m", m_MSB));
  }

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::binary_data(m_value, sizeof(m_value)));
    ar(::cereal::binary_data(&m_MSB, sizeof(m_MSB)));
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_value));
    ar(::cereal::make_nvp("m", m_MSB));
  }

  std::string SerializedObjectName() const { return "FXDInteger"; }

  static uint32_t SerializedVersion() { return 1; }

protected成员

 protected:
  /**
   * Converts the string v into base-r integer where r is equal to 2^bitwidth of
   * integral data type.
   *
   * @param v The input string
   */
  void AssignVal(const std::string &v);

  /**
   * Sets the MSB to the correct value from the BigInteger.
   */
  void SetMSB();

  /**
   * Sets the MSB to the correct value from the BigInteger.
   * @param guessIdxChar is the hint of the MSB position.
   */
  void SetMSB(usint guessIdxChar);

extern templete

A template specialization can be explicitly declared as a way to suppress multiple instantiations.
This is basically a way of avoiding significant redundant work by the compiler and linker.
这基本上是一种避免编译器和链接器进行大量冗余工作的方法。

extern template class BigInteger<integral_dtype, BigIntegerBitLength>;	
// 类型定义在math/backend.h中

}  // namespace bigintfxd

\core\include\math\bigintfxd\mubintvecfxd.h

#include <iostream>
#include <string>

#include "utils/inttypes.h"
#include "utils/serializable.h"

#include "math/bigintfxd/ubintfxd.h"

/**
 * @namespace bigintfxd
 * The namespace of bigintfxd
 */
namespace bigintfxd {

class BigVectorImpl

私有成员

 private:
  // m_data is a pointer to the vector
  IntegerType *m_data;
  // m_length stores the length of the vector
  usint m_length;
  // m_modulus stores the internal modulus of the vector.
  IntegerType m_modulus = 0;

  // function to check if the index is a valid index.
  bool IndexCheck(size_t length) const {
    if (length > this->m_length) {
      return false;
    }
    return true;
  }
};
/**
 * @brief The class for representing vectors of big binary integers.
 */
template <class IntegerType>
class BigVectorImpl
    : public lbcrypto::BigVectorInterface<BigVectorImpl<IntegerType>,
                                          IntegerType>,
      public lbcrypto::Serializable {
 public:

构造和析构函数

  // CONSTRUCTORS

  /**
   * Basic constructor.
   */
  BigVectorImpl();

  static inline BigVectorImpl Single(const IntegerType &val,
                                     const IntegerType &modulus) {
    BigVectorImpl vec(1, modulus);
    vec[0] = val;
    return vec;
  }

  /**
   * Basic constructor for specifying the length of the vector and the modulus.
   *
   * @param length is the length of the big binary vector, in terms of the
   * number of entries.
   * @param modulus is the modulus of the ring.
   */
  explicit BigVectorImpl(usint length, const IntegerType &modulus = 0);

  /**
   * Basic constructor for copying a vector
   *
   * @param bigVector is the big binary vector to be copied.
   */
  BigVectorImpl(const BigVectorImpl &bigVector);

  /**
   * Basic move constructor for moving a vector
   *
   * @param &&bigVector is the big binary vector to be moved.
   */
  BigVectorImpl(BigVectorImpl &&bigVector);  // move copy constructor

  /**
   * Basic constructor for specifying the length of the vector
   * the modulus and an initializer list.
   *
   * @param length is the length of the big binary vector, in terms of the
   * number of entries.
   * @param modulus is the modulus of the ring.
   * @param rhs is an initializer list of strings
   */

  BigVectorImpl(usint length, const IntegerType &modulus,
                std::initializer_list<std::string> rhs);

  /**
   * Basic constructor for specifying the length of the vector
   * the modulus and an initializer list.
   *
   * @param length is the length of the big binary vector, in terms of the
   * number of entries.
   * @param modulus is the modulus of the ring.
   * @param rhs is an initializer list of usint
   */
  BigVectorImpl(usint length, const IntegerType &modulus,
                std::initializer_list<uint64_t> rhs);

  /**
   * Destructor.
   */
  virtual ~BigVectorImpl();

赋值操作符

  // ASSIGNMENT OPERATORS

  /**
   * Assignment operator to assign value from rhs
   *
   * @param &rhs is the big binary vector to be assigned from.
   * @return Assigned BigVectorImpl.
   */
  const BigVectorImpl &operator=(const BigVectorImpl &rhs);

  /**
   * Move assignment operator
   *
   * @param &&rhs is the big binary vector to be moved.
   * @return moved BigVectorImpl object
   */
  const BigVectorImpl &operator=(BigVectorImpl &&rhs);

  /**
   * Initializer list for BigVectorImpl.
   *
   * @param &&rhs is the list of strings containing integers to be assigned to
   * the BBV.
   * @return BigVectorImpl object
   */
  const BigVectorImpl &operator=(std::initializer_list<std::string> rhs);

  /**
   * Initializer list for BigVectorImpl.
   *
   * @param &&rhs is the list of integers to be assigned to the BBV.
   * @return BigVectorImpl object
   */
  const BigVectorImpl &operator=(std::initializer_list<uint64_t> rhs);

  /**
   * Assignment operator to assign value val to first entry, 0 for the rest of
   * entries.
   *
   * @param val is the value to be assigned at the first entry.
   * @return Assigned BigVectorImpl.
   */
  const BigVectorImpl &operator=(uint64_t val) {
    this->m_data[0] = val;
    if (this->m_modulus != 0) {
      this->m_data[0] %= this->m_modulus;
    }
    for (size_t i = 1; i < GetLength(); ++i) {
      this->m_data[i] = 0;
    }
    return *this;
  }

ACCESSORS

  // ACCESSORS

  /**
   * Sets/gets a value at an index.
   * This method is slower than operator[] as it checks if index out of range
   *
   * @param index is the index to set a value at.
   */
  IntegerType &at(size_t i) {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "BigVector index out of range");
    }
    return this->m_data[i];
  }

  const IntegerType &at(size_t i) const {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "BigVector index out of range");
    }
    return this->m_data[i];
  }

  /**
   * operators to get a value at an index.
   * @param idx is the index to get a value at.
   * @return is the value at the index.
   */
  IntegerType &operator[](size_t idx) { return (this->m_data[idx]); }

  const IntegerType &operator[](size_t idx) const {
    return (this->m_data[idx]);
  }

  /**
   * Sets the vector modulus.
   *
   * @param value is the value to set.
   * @param value is the modulus value to set.
   */
  void SetModulus(const IntegerType &value);

  /**
   * Sets the vector modulus and changes the values to match the new modulus.
   *
   * @param value is the value to set.
   */
  void SwitchModulus(const IntegerType &value);

  /**
   * Gets the vector modulus.
   *
   * @return the vector modulus.
   */
  const IntegerType &GetModulus() const { return this->m_modulus; }

  /**
   * Gets the vector length.
   *
   * @return vector length.
   */
  size_t GetLength() const { return this->m_length; }

模算术

  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Vector modulus operator.
   *
   * @param &modulus is the modulus to perform on the current vector entries.
   * @return is the result of the modulus operation on current vector.
   */
  BigVectorImpl Mod(const IntegerType &modulus) const;

  /**
   * Vector modulus operator. In-place variant.
   *
   * @param &modulus is the modulus to perform on the current vector entries.
   * @return is the result of the modulus operation on current vector.
   */
  const BigVectorImpl &ModEq(const IntegerType &modulus);

  /**
   * Scalar-to-vector modulus addition operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus addition operation.
   */
  BigVectorImpl ModAdd(const IntegerType &b) const;

  /**
   * Scalar-to-vector modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus addition operation.
   */
  const BigVectorImpl &ModAddEq(const IntegerType &b);

  /**
   * Scalar modulus addition at a particular index.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  BigVectorImpl ModAddAtIndex(usint i, const IntegerType &b) const;

  /**
   * Scalar modulus addition at a particular index. In-place variant.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  const BigVectorImpl &ModAddAtIndexEq(usint i, const IntegerType &b);

  /**
   * Vector component wise modulus addition.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus addition operation.
   */
  BigVectorImpl ModAdd(const BigVectorImpl &b) const;

  /**
   * Vector component wise modulus addition. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus addition operation.
   */
  const BigVectorImpl &ModAddEq(const BigVectorImpl &b);

  /**
   * Scalar-from-vector modulus subtraction operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus subtraction operation.
   */
  BigVectorImpl ModSub(const IntegerType &b) const;

  /**
   * Scalar-from-vector modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus subtraction operation.
   */
  const BigVectorImpl &ModSubEq(const IntegerType &b);

  /**
   * Vector component wise modulus subtraction.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus subtraction operation.
   */
  BigVectorImpl ModSub(const BigVectorImpl &b) const;

  /**
   * Vector component wise modulus subtraction. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus subtraction operation.
   */
  const BigVectorImpl &ModSubEq(const BigVectorImpl &b);

  /**
   * Scalar-to-vector modulus multiplication operation.
   * Generalized Barrett modulo reduction algorithm.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus multiplication operation.
   */
  BigVectorImpl ModMul(const IntegerType &b) const;

  /**
   * Scalar-to-vector modulus multiplication operation. In-place variant.
   * Generalized Barrett modulo reduction algorithm.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus multiplication operation.
   */
  const BigVectorImpl &ModMulEq(const IntegerType &b);

  /**
   * Vector component wise modulus multiplication.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus multiplication
   * operation.
   */
  BigVectorImpl ModMul(const BigVectorImpl &b) const;

  /**
   * Vector component wise modulus multiplication. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus multiplication
   * operation.
   */
  const BigVectorImpl &ModMulEq(const BigVectorImpl &b);

  /**
   * Scalar modulus exponentiation operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus exponentiation operation.
   */
  BigVectorImpl ModExp(const IntegerType &b) const;

  /**
   * Scalar modulus exponentiation operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus exponentiation operation.
   */
  const BigVectorImpl &ModExpEq(const IntegerType &b);

  /**
   * Modulus inverse operation.
   *
   * @return is the result of the component wise modulus inverse operation.
   */
  BigVectorImpl ModInverse() const;

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @return is the result of the component wise modulus inverse operation.
   */
  const BigVectorImpl &ModInverseEq();

  /**
   * Modulus 2 operation, also a least significant bit.
   *
   * @return is the result of the component wise modulus 2 operation, also a
   * least significant bit.
   */
  BigVectorImpl ModByTwo() const;

  /**
   * Modulus 2 operation, also a least significant bit. In-place variant.
   *
   * @return is the result of the component wise modulus 2 operation, also a
   * least significant bit.
   */
  const BigVectorImpl &ModByTwoEq();

  /**
   * Vector multiplication without applying the modulus operation.
   *
   * @param &b is the vector to multiply.
   * @return is the result of the multiplication operation.
   */
  BigVectorImpl MultWithOutMod(const BigVectorImpl &b) const;

  /**
   * Vector multiplication without applying the modulus operation. In-place
   * variant.
   *
   * @param &b is the vector to multiply.
   * @return is the result of the multiplication operation.
   */
  const BigVectorImpl &MultWithOutModEq(const BigVectorImpl &b);

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  BigVectorImpl MultiplyAndRound(const IntegerType &p,
                                 const IntegerType &q) const;

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const BigVectorImpl &MultiplyAndRoundEq(const IntegerType &p,
                                          const IntegerType &q);

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  BigVectorImpl DivideAndRound(const IntegerType &q) const;

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const BigVectorImpl &DivideAndRoundEq(const IntegerType &q);

  // OTHER FUNCTIONS

  /**
   * Digit vector at a specific index for all entries for a given number base.
   * Warning: only power-of-2 bases are currently supported.
   * Example: for vector (83, 1, 45), index 2 and base 4 we have:
   *
   *                           index:0,1,2,3
   * |83|                           |3,0,1,1|                 |1|
   * |1 | --base 4 decomposition--> |1,0,0,0| --at index 2--> |0|
   * |45|                           |1,3,2,0|                 |2|
   *
   * The return vector is (1,0,2)
   *
   * @param index is the index to return the digit from in all entries.
   * @param base is the base to use for the operation.
   * @return is the digit at a specific index for all entries for a given number
   * base
   */
  BigVectorImpl GetDigitAtIndexForBase(usint index, usint base) const;

  // STRINGS & STREAMS

  /**
   * ostream operator to output vector values to console
   *
   * @param os is the std ostream object.
   * @param &ptr_obj is the BigVectorImpl object to be printed.
   * @return std ostream object which captures the vector values.
   */
  template <class IntegerType_c>
  friend std::ostream &operator<<(std::ostream &os,
                                  const BigVectorImpl<IntegerType_c> &ptr_obj) {
    auto len = ptr_obj.m_length;
    os << "[";
    for (usint i = 0; i < len; i++) {
      os << ptr_obj.m_data[i];
      os << ((i == (len - 1)) ? "]" : " ");
    }
    os << " modulus: " << ptr_obj.m_modulus;
    return os;
  }

  // SERIALIZATION

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("l", m_length));
    ar(::cereal::binary_data(m_data, sizeof(IntegerType) * m_length));
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("l", m_length));
    for (size_t i = 0; i < m_length; i++) {
      ar(m_data[i]);
    }
  }

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("l", m_length));
    m_data = new IntegerType[m_length]();
    ar(::cereal::binary_data(m_data, sizeof(IntegerType) * m_length));
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("l", m_length));
    m_data = new IntegerType[m_length]();
    for (size_t i = 0; i < m_length; i++) {
      ar(m_data[i]);
    }
  }

  std::string SerializedObjectName() const { return "FXDInteger"; }

  static uint32_t SerializedVersion() { return 1; }

extern templete

extern template class BigVectorImpl<
    BigInteger<integral_dtype, BigIntegerBitLength>>;

}  // namespace bigintfxd

\core\include\math\bigintdyn\ubintdyn.h

This file contains the main class for unsigned big integers: ubint. Big integers are represented as arrays of machine native unsigned integers. The native integer type is supplied as a template parameter. Currently implementation based on uint32_t and uint64_t is supported. a native double the base integer size is also needed.

#define NO_BARRETT  // currently barrett is slower than mod

#include <fstream>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <vector>
#include "math/nbtheory.h"
#include "utils/inttypes.h"
#include "utils/memory.h"
#include "utils/serializable.h"
#ifdef UBINT_64

#undef int128_t
#define int128_t our_int128_t
#undef uint128_t
#define uint128_t our_uint128_t

typedef __int128 int128_t;
typedef unsigned __int128 uint128_t;

#define UINT128_MAX ((uint128_t)-1)

#endif  // UBINT_64
/**
 *@namespace bigintdyn
 * The namespace of this code
 */
namespace bigintdyn {
/**The following structs are needed for initialization of ubint at
 *the preprocessing stage.  The structs compute certain values using
 *template metaprogramming approach and mostly follow recursion to
 *calculate value(s).
 */

/**
 * @brief  Struct to find log value of N.
 *Needed in the preprocessing step of ubint to determine bitwidth.
 *
 * @tparam N bitwidth.
 */

template <usint N>
struct Log2 {
  static const usint value = 1 + Log2<N / 2>::value;
};

/**
 * @brief Struct to find log 2 value of N.
 *Base case for recursion.
 *Needed in the preprocessing step of ubint to determine bitwidth.
 */
template <>
struct Log2<2> {
  static const usint value = 1;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}
 *
 * @tparam Dtype primitive datatype.
 */
template <typename Dtype>
struct DataTypeChecker {
  static const bool value = false;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}. sets value true if datatype is unsigned
 * integer 8 bit.
 */
template <>
struct DataTypeChecker<uint8_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}. sets value true if datatype is unsigned
 * integer 16 bit.
 */
template <>
struct DataTypeChecker<uint16_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}. sets value true if datatype is unsigned
 * integer 32 bit.
 */
template <>
struct DataTypeChecker<uint32_t> {
  static const bool value = true;
};

/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}. sets value true if datatype is unsigned
 * integer 64 bit.
 */
template <>
struct DataTypeChecker<uint64_t> {
  static const bool value = true;
};

#ifdef UBINT_64
/**
 * @brief Struct for validating if Dtype is amongst {uint8_t, uint16_t,
 * uint32_t, uint64_t, uint128_t}. sets value true if datatype is unsigned
 * integer 64 bit.
 */
template <>
struct DataTypeChecker<uint128_t> {
  static const bool value = true;
};
#endif
/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type void for default case
 *
 * @tparam utype primitive integer data type.
 */
template <typename utype>
struct DoubleDataType {
  typedef void T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * Sets T as of type unsigned integer 16 bit if limb datatype is 8bit
 */
template <>
struct DoubleDataType<uint8_t> {
  typedef uint16_t T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 32 bit if limb datatype is 16bit
 */
template <>
struct DoubleDataType<uint16_t> {
  typedef uint32_t T;
};

/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 64 bit if limb datatype is 32bit
 */
template <>
struct DoubleDataType<uint32_t> {
  typedef uint64_t T;
};

#ifdef UBINT_64
/**
 * @brief Struct to determine a datatype that is twice as big(bitwise) as utype.
 * sets T as of type unsigned integer 128 bit if limb datatype is 64bit
 */
template <>
struct DoubleDataType<uint64_t> {
  typedef uint128_t T;
};
#endif

/**
 * @brief Struct to determine a datatype that is the signed version of utype.
 * sets T as of type void for default case
 *
 * @tparam utype primitive integer data type.
 */
template <typename utype>
struct SignedDataType {
  typedef void T;
};

/**
 * @brief Struct to determine a datatype that is the signed version of utype.
 * Sets T as of type signed integer 8 bit if limb datatype is 8bit
 */
template <>
struct SignedDataType<uint8_t> {
  typedef int8_t T;
};

/**
 * @brief Struct to determine a datatype that is the signed version of utype.
 * sets T as of type signed integer 16 bit if limb datatype is 16bit
 */
template <>
struct SignedDataType<uint16_t> {
  typedef int16_t T;
};

/**
 * @brief Struct to determine a datatype that is the signed version of utype.
 * sets T as of type signed integer 32 bit if limb datatype is 32bit
 */
template <>
struct SignedDataType<uint32_t> {
  typedef int32_t T;
};

/**
 * @brief Struct to determine a datatype that is the signed version of utype.
 * sets T as of type signed integer 64 bit if limb datatype is 64bit
 */
template <>
struct SignedDataType<uint64_t> {
  typedef int64_t T;
};

/**
 * @brief Struct to determine a signed datatype that is twice as big(bitwise) as
 * utype. sets T as of type void for default case
 *
 * @tparam utype primitive integer data type.
 */
template <typename utype>
struct SignedDoubleDataType {
  typedef void T;
};

/**
 * @brief Struct to determine a signed datatype that is twice as big(bitwise) as
 * utype. Sets T as of type unsigned integer 16 bit if limb datatype is 8bit
 */
template <>
struct SignedDoubleDataType<uint8_t> {
  typedef int16_t T;
};

/**
 * @brief Struct to determine a signed datatype that is twice as big(bitwise) as
 * utype. sets T as of type unsigned integer 32 bit if limb datatype is 16bit
 */
template <>
struct SignedDoubleDataType<uint16_t> {
  typedef int32_t T;
};

/**
 * @brief Struct to determine a signed datatype that is twice as big(bitwise) as
 * utype. sets T as of type unsigned integer 64 bit if limb datatype is 32bit
 */
template <>
struct SignedDoubleDataType<uint32_t> {
  typedef int64_t T;
};

#ifdef UBINT_64
/**
 * @brief Struct to determine a signed datatype that is twice as big(bitwise) as
 * utype. sets T as of type unsigned integer 128 bit if limb datatype is 64bit
 */
template <>
struct SignedDoubleDataType<uint64_t> {
  typedef int128_t T;
};
#endif
const double LOG2_10 =
    3.32192809;  //!< @brief A pre-computed constant of Log base 2 of 10.

class ubint

私有成员变量

 private:
  // vector storing the native integers. stored little endian
  vector<limb_t> m_value;

 private:
  // variable that stores the MOST SIGNIFICANT BIT position in the
  uint32_t m_MSB;

  // variable to store the bitlength of the limb data type.
  static const usint m_limbBitLength;

  // variable to store the maximum value of the limb data type.
  static const limb_t m_MaxLimb;

  // variable to store the log(base 2) of the number of bits in the limb data
  // type.
  static const usint m_log2LimbBitLength;

  // variable to store the size of the data array.
  static const usint m_nSize;

  // The maximum number of digits in biginteger. It is used by the cout(ostream)
  // function for printing the bignumber. Todo remove this limitation
  static const usint m_numDigitInPrintval =
      1500;  // todo get rid of m_numDigitInPrintval

  /**
   * function to return the ceiling of the input number divided by
   * the number of bits in the limb data type.  DBC this is to
   * determine how many limbs are needed for an input bitsize.
   * @param Number is the number to be divided.
   * @return the ceiling of Number/(bits in the limb data type)
   */
  static usint ceilIntByUInt(
      const limb_t Number);  // todo rename to MSB2NLimbs()

  // currently unused array
  static const ubint *m_modChain;
//
// Definition starts here
//
template <typename limb_t>
class ubint : public lbcrypto::BigIntegerInterface<ubint<limb_t>> {
 public:

构造和析构函数

  // CONSTRUCTORS

  /**
   * Default constructor.
   */
  ubint();

  /**
   * Copy constructor.
   *
   * @param &val is the ubint to be copied.
   */
  ubint(const ubint &val);

  /**
   * Move constructor.
   *
   * @param &&val is the ubint to be copied.
   */
  ubint(ubint &&val);

  /**
   * Constructor from a string.
   *
   * @param &strval is the initial integer represented as a string.
   */
  explicit ubint(const std::string &strval);

  /**
   * Constructor from an unsigned integer.
   *
   * @param val is the initial integer represented as a uint64_t.
   */
  ubint(const uint64_t val);
#if defined(HAVE_INT128)
  ubint(unsigned __int128 val);
#endif

  /**
   * Constructors from smaller basic types
   *
   * @param val is the initial integer represented as a basic integer type.
   */
  ubint(int val) : ubint(uint64_t(val)) {}
  ubint(uint32_t val) : ubint(uint64_t(val)) {}
  ubint(long val) : ubint(uint64_t(val)) {}
  ubint(long long val) : ubint(uint64_t(val)) {}

  /**
   * Constructor from a NativeInteger
   *
   * @param &val is the initial integer represented as a native integer.
   */
  template <typename T>
  ubint(const bigintnat::NativeIntegerT<T> &val) : ubint(val.ConvertToInt()) {}

  /**
   * Constructor from double is not permitted
   *
   * @param val
   */
  ubint(double val)
      __attribute__((deprecated("Cannot construct from a double")));

  /**
   * Destructor.
   */
  ~ubint();

赋值操作符

  // ASSIGNMENT OPERATORS

  /**
   * Copy assignment operator
   *
   * @param &val is the ubint to be assigned from.
   * @return assigned ubint ref.
   */
  const ubint &operator=(const ubint &val);

  // TODO move assignment operator?

  /**
   * Assignment operator from string
   *
   * @param strval is the string to be assigned from
   * @return the assigned ubint ref.
   */
  const ubint &operator=(const std::string strval) {
    *this = ubint(strval);
    return *this;
  }

  /**
   * Assignment operator from unsigned integer
   *
   * @param val is the unsigned integer to be assigned from.
   * @return the assigned ubint ref.
   */
  const ubint &operator=(const uint64_t val) {
    *this = ubint(val);
    return *this;
  }

  /**
   * Assignment operator from native integer
   *
   * @param &val is the native integer to be assigned from.
   * @return the assigned ubint ref.
   */
  const ubint &operator=(const bigintnat::NativeInteger &val) {
    *this = ubint(val);
    return *this;
  }

ACCESSORS

  // ACCESSORS

  /**
   * Basic set method for setting the value of a ubint
   *
   * @param strval is the string representation of the ubint to be copied.
   */
  void SetValue(const std::string &strval);

  /**
   * Basic set method for setting the value of a ubint
   *
   * @param val is the ubint representation of the ubint to be assigned.
   */
  void SetValue(const ubint &val);

  /**
   *  Set this int to 1.
   */
  inline void SetIdentity() { *this = 1; }

模运算

  // ARITHMETIC OPERATIONS

  /**
   * Addition operation.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  ubint Add(const ubint &b) const;

  /**
   * Addition operation. In-place variant.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  const ubint &AddEq(const ubint &b);

  /**
   * Subtraction operation.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  ubint Sub(const ubint &b) const;

  /**
   * Subtraction operation. In-place variant.
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  const ubint &SubEq(const ubint &b);

  // this is a negation operator which really doesn't make sense for an unsinged
  ubint operator-() const { return ubint(0).Sub(*this); }

  /**
   * Multiplication operation.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  ubint Mul(const ubint &b) const;

  /**
   * Multiplication operation. In-place variant.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  const ubint &MulEq(const ubint &b);

  /**
   * Division operation.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  ubint DividedBy(const ubint &b) const;

  /**
   * Division operation. In-place variant.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  const ubint &DividedByEq(const ubint &b);

  /**
   * Exponentiation operation. Returns x^p.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  ubint Exp(usint p) const;

  /**
   * Exponentiation operation. Returns x^p. In-place variant.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  const ubint &ExpEq(usint p);

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  ubint MultiplyAndRound(const ubint &p, const ubint &q) const;

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const ubint &MultiplyAndRoundEq(const ubint &p, const ubint &q);

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  ubint DivideAndRound(const ubint &q) const;

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const ubint &DivideAndRoundEq(const ubint &q);

  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Naive modulus operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  ubint Mod(const ubint &modulus) const;

  /**
   * Naive modulus operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  const ubint &ModEq(const ubint &modulus);

  /**
   * Pre-computes the mu factor that is used in Barrett modulo reduction
   *
   * @return the value of mu
   */
  ubint ComputeMu() const;

  /**
   * Barrett modulus operation.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  ubint Mod(const ubint &modulus, const ubint &mu) const;

  /**
   * Barrett modulus operation. In-place variant.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  const ubint &ModEq(const ubint &modulus, const ubint &mu);

  /**
   * Modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  ubint ModAdd(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const ubint &ModAddEq(const ubint &b, const ubint &modulus);

  /**
   * Modulus addition where operands are < modulus.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  ubint ModAddFast(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus addition where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const ubint &ModAddFastEq(const ubint &b, const ubint &modulus);

  /**
   * Barrett modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  ubint ModAdd(const ubint &b, const ubint &modulus, const ubint &mu) const;

  /**
   * Barrett modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  const ubint &ModAddEq(const ubint &b, const ubint &modulus, const ubint &mu);

  /**
   * Modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  ubint ModSub(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const ubint &ModSubEq(const ubint &b, const ubint &modulus);

  /**
   * Modulus subtraction where operands are < modulus.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  ubint ModSubFast(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus subtraction where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const ubint &ModSubFastEq(const ubint &b, const ubint &modulus);

  /**
   * Barrett modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  ubint ModSub(const ubint &b, const ubint &modulus, const ubint &mu) const;

  /**
   * Barrett modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  const ubint &ModSubEq(const ubint &b, const ubint &modulus, const ubint &mu);

  /**
   * Modulus multiplication operation.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  ubint ModMul(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus multiplication operation. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const ubint &ModMulEq(const ubint &b, const ubint &modulus);

  /**
   * Barrett modulus multiplication.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  ubint ModMul(const ubint &b, const ubint &modulus, const ubint &mu) const;

  /**
   * Barrett modulus multiplication. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const ubint &ModMulEq(const ubint &b, const ubint &modulus, const ubint &mu);

  /**
   * Modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  ubint ModMulFast(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus multiplication that assumes the operands are < modulus. In-place
   * variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const ubint &ModMulFastEq(const ubint &b, const ubint &modulus);

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  ubint ModMulFast(const ubint &b, const ubint &modulus, const ubint &mu) const;

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   * In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const ubint &ModMulFastEq(const ubint &b, const ubint &modulus,
                            const ubint &mu);

  ubint ModMulFastConst(const ubint &b, const ubint &modulus,
                        const ubint &bInv) const {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConst is not implemented for backend 4");
  }

  const ubint &ModMulFastConstEq(const ubint &b, const ubint &modulus,
                                 const ubint &bInv) {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConstEq is not implemented for backend 4");
  }

  /**
   * Modulus exponentiation operation. Square-and-multiply algorithm is used.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  ubint ModExp(const ubint &b, const ubint &modulus) const;

  /**
   * Modulus exponentiation operation. Square-and-multiply algorithm is used.
   * In-place variant.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  const ubint &ModExpEq(const ubint &b, const ubint &modulus);

  /**
   * Modulus inverse operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  ubint ModInverse(const ubint &modulus) const;

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  const ubint &ModInverseEq(const ubint &modulus);

移位运算

  // SHIFT OPERATIONS

  /**
   * Left shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  ubint LShift(usshort shift) const;

  /**
   * Left shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const ubint &LShiftEq(usshort shift);

  /**
   * Right shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  ubint RShift(usshort shift) const;

  /**
   * Right shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const ubint &RShiftEq(usshort shift);

比较运算

  // COMPARE

  /**
   * Compares the current ubint to ubint a.
   *
   * @param a is the ubint to be compared with.
   * @return  -1 for strictly less than, 0 for equal to and 1 for strictly
   * greater than conditons.
   */
  int Compare(const ubint &a) const;

转换函数

  // CONVERTERS

  /**
   * Converts the value to a native integer.
   * @return the int representation of the value as usint.
   */
  template <typename T = bigintnat::BasicInteger>
  T ConvertToInt() const {
    T result = 0;
    if (m_value.size() == 0) {
      PALISADE_THROW(lbcrypto::not_available_error,
                     "ConvertToInt() on uninitialized bint");
    }
    if (sizeof(limb_t) >= sizeof(T)) {
      result = m_value[0];
      result = (T)m_value[0];
    } else {
      // Case where limb_t is less bits than uint64_t
      uint32_t msbTest = sizeof(T) * 8;
      if (msbTest > m_MSB) {
        msbTest = m_MSB;
      }
      usint ceilInt = ceilIntByUInt(msbTest);
      // copy the values by shift and add
      for (usint i = 0; i < ceilInt; i++) {
        T tmp = this->m_value[i];
        tmp <<= (m_limbBitLength * i);
        result += tmp;
      }
    }
    return result;
  }

  /**
   * Converts the value to a float
   * if the ubint is uninitialized error is thrown
   * if the ubint is larger than the max value representable
   * or if conversion fails, and error is reported to cerr
   *
   * @return float representation of the value.
   */
  float ConvertToFloat() const;

  /**
   * Converts the value to an double.
   * if the ubint is uninitialized error is thrown
   * if the ubint is larger than the max value representable
   * error is thrown
   * if conversion fails error is thrown
   *
   * @return double representation of the value.
   */
  double ConvertToDouble() const;

  /**
   * Converts the value to an long double.
   * if the ubint is uninitialized error is thrown
   * if the ubint is larger than the max value representable
   * error is thrown
   * if conversion fails error is thrown
   *
   * @return long double representation of the value.
   */
  long double ConvertToLongDouble() const;

  /**
   * Convert a value from an unsigned int to a ubint.
   *
   * @param m the value to convert from.
   * @return int represented as a ubint.
   */
  static ubint UsintToUbint(usint m);

  /**
   * Convert a string representation of a binary number to a ubint.
   * Note: needs renaming to a generic form since the variable type name is
   * embedded in the function name. Suggest FromBinaryString()
   * @param bitString the binary num in string.
   * @return the  number represented as a ubint.
   */
  static ubint FromBinaryString(const std::string &bitString);

其他函数

  // OTHER FUNCTIONS

  /**
   * Returns the MSB location of the value.
   *
   * @return the index of the most significant bit.
   */
  usint GetMSB() const;

  /**
   * Returns the size of the underlying vector of Limbs
   *
   * @return the size
   */
  usint GetNumberOfLimbs() const;

  /**
   * Tests whether the ubint is a power of 2.
   *
   * @param m_numToCheck is the value to check.
   * @return true if the input is a power of 2, false otherwise.
   */
  bool isPowerOfTwo(const ubint &m_numToCheck);

  /**
   * Get the number of digits using a specific base - support for arbitrary base
   * may be needed.
   *
   * @param base is the base with which to determine length in.
   * @return the length of the representation in a specific base.
   */
  usint GetLengthForBase(usint base) const { return GetMSB(); }

  /**
   * Get the number of digits using a specific base.
   * Warning: only power-of-2 bases are currently supported.
   * Example: for number 83, index 2 and base 4 we have:
   *
   *                         index:0,1,2,3
   * 83 --base 4 decomposition--> (3,0,1,1) --at index 2--> 1
   *
   * The return number is 1.
   *
   * @param index is the location to return value from in the specific base.
   * @param base is the base with which to determine length in.
   * @return the length of the representation in a specific base.
   */
  usint GetDigitAtIndexForBase(usint index, usint base) const;

  /**
   * Gets the state of the ubint from the internal value.
   */
  const std::string GetState() const;

  /**
   * function that returns the ubint after multiplication by b.
   * @param b is the number to be multiplied.
   * @return the ubint after the multiplication.
   */
  inline ubint MulIntegerByLimb(limb_t b) const;  // todo rename to ubint

  /**
   * Gets the bit at the specified index.
   *
   * @param index is the index of the bit to get.
   * @return resulting bit.
   */
  uschar GetBitAtIndex(usint index) const;

  /**
   * A zero allocator that is called by the Matrix class. It is used to
   * initialize a Matrix of ubint objects.
   */
  static ubint Allocator() { return 0; }

输出

  // STRINGS & STREAMS

  /**
   * Stores the based 10 equivalent/Decimal value of the ubint in a string
   * object and returns it.
   *
   * @return value of this ubint in base 10 represented as a string.
   */
  const std::string ToString() const;

 public:
#ifdef UBINT_32
  static const std::string IntegerTypeName() { return "UBDYNINT_32"; }
#endif
#ifdef UBINT_64
  static const std::string IntegerTypeName() { return "UBDYNINT_64"; }
#endif

  /**
   * Delivers value of the internal limb storage
   * Used primarily for debugging
   * @return STL vector of uint_type
   */
  std::string GetInternalRepresentation() const {
    std::string ret("");
    for (size_t i = 0; i < m_value.size(); i++) {
      ret += std::to_string(m_value[i]);
      if (i < (m_value.size() - 1)) {
        ret += " ";
      }
    }
    return ret;
  }

  /**
   * ostream output << operator
   * Algorithm used is double and add
   * http://www.wikihow.com/Convert-from-Binary-to-Decimal
   *
   * @param os is the std ostream object.
   * @param ptr_obj is ubint to be printed.
   * @return is the returned ostream object.
   */
  friend std::ostream &operator<<(std::ostream &os, const ubint &ptr_obj) {
    // todo: get rid of m_numDigitInPrintval and make dynamic

    // initiate to object to be printed
    // todo smartpointer
    uschar *print_VALUE = new uschar[ptr_obj.m_numDigitInPrintval]();
    // starts the conversion from base r to decimal value
    for (usint i = ptr_obj.m_MSB; i > 0; i--) {
      ubint::double_bitVal(print_VALUE);
      // adds the bit value to the print_VALUE (print_VALUE *= 2)
      ubint::add_bitVal(print_VALUE, ptr_obj.GetBitAtIndex(i));
    }

    // find the first occurence of non-zero value in print_VALUE
    bool print = false;
    for (usint counter = 0; counter < ptr_obj.m_numDigitInPrintval; counter++) {
      if (print_VALUE[counter] != 0) {
        print = true;
      }
      if (print) {
        os << static_cast<int>(print_VALUE[counter]);
      }
    }
    // Print 0 value
    if (!print) {
      os << 0;
    }
    delete[] print_VALUE;
    return os;
  }

  /**
   * documentation function, prints sizes of constats.
   */
  void PrintIntegerConstants();

  // SERIALIZATION

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", m_value));
    ar(::cereal::make_nvp("m", m_MSB));
    ar(::cereal::make_nvp("s", m_state));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("v", m_value));
    ar(::cereal::make_nvp("m", m_MSB));
    ar(::cereal::make_nvp("s", m_state));
  }

  std::string SerializedObjectName() const { return "DYNInteger"; }

  static uint32_t SerializedVersion() { return 1; }

 protected:
  /**
   * Converts the string v into base-r integer where r is equal to 2^bitwidth of
   * limb data type.
   *
   * @param v The input string
   */
  void AssignVal(const std::string &v);

  /**
   * Sets the MSB to the correct value as computed from the internal value.
   */
  void SetMSB();

  /**
   * Sets the MSB to the correct value from the ubint.
   * @param guessIdxChar is the hint of the MSB position.
   */
  void SetMSB(usint guessIdxChar);

私有成员函数

 private:
  /**
   * Normalize limb storage of the ubint by making sure the most
   * significant limb is non-zero (all higher zero limbs are
   * removed).
   *
   * @return resulting bit.
   */
  void NormalizeLimbs(void);

  /**
   * Sets the limb value at the specified index.
   *
   * @param index is the index of the limb to set in the ubint storage.
   * //todo should be renamed SetLimbAtIndex();
   */
  void SetIntAtIndex(usint idx, limb_t value);

  /**
   * helper function for Div
   * @param defined in ubint.cpp
   */

  int divqr_vect(ubint &q, ubint &r, const ubint &u, const ubint &v) const;

  int divr_vect(ubint &r, const ubint &u, const ubint &v) const;

  int divq_vect(ubint &q, const ubint &u, const ubint &v) const;
 private:
  /**
   * function to return the MSB of number.
   * @param x is the number.
   * @return the MSB position in the number x.Note MSB(1) is 1 NOT zero!!!!!
   */

  inline static usint GetMSBlimb_t(limb_t x) { return lbcrypto::GetMSB64(x); }

  // Dlimb_t is the data type that has twice as many bits in the limb data type.
  typedef typename DoubleDataType<limb_t>::T Dlimb_t;

  // Slimb_t is the data type that as many bits in the limb data type but is
  // signed.
  typedef typename SignedDataType<limb_t>::T Slimb_t;

  // Slimb_t is the data type that as many bits in the limb data type but is
  // signed.
  typedef typename SignedDoubleDataType<limb_t>::T Sdlimb_t;

  // enum definition to represent the state of the ubint.
  enum State { INITIALIZED, GARBAGE };

  /**
   * function to return the MSB of number that is of type Dlimb_t.
   * @param x is the number.
   * @return the MSB position in the number x. Note MSB(1) is 1 NOT zero!!!!!
   */
  inline static usint GetMSBDlimb_t(Dlimb_t x) { return lbcrypto::GetMSB64(x); }

  // enum to store the state of the
  State m_state;

  /**
   * function that returns the decimal value from the binary array a.
   * @param a is a pointer to the binary array.
   * @return the decimal value.
   */
  static limb_t UintInBinaryToDecimal(uschar *a);

  /**
   * function that mutiplies by 2 to the binary array.
   * @param a is a pointer to the binary array.
   */
  static void double_bitVal(uschar *a);

  /**
   * function that adds bit b to the binary array.
   * @param a is a pointer to the binary array.
   * @param b is a bit value to be added.
   */
  static void add_bitVal(uschar *a, uschar b);
};

类外

#if 0
// stream helper function for vector of objects
template <typename limb_t>
inline std::ostream &operator<<(std::ostream &os,
                                const std::vector<limb_t> &v) {
  os << "[";
  for (const auto &itr : v) {
    os << " " << itr;
  }
  os << " ]";
  return os;
}
#endif
}  // namespace bigintdyn

\core\include\math\bigintdyn\mubintvecdyn.h

This file contains mubintvecdyn, a <vector> of buintdyn, with associated modulus and modulo math operators.

#include <initializer_list>
#include <iostream>
#include <string>
#include <vector>

#include "math/bigintfxd/mubintvecfxd.h"
#include "utils/inttypes.h"
#include "utils/serializable.h"
/**
 * @namespace bigintdyn
 * The namespace of bigintdyn
 */
namespace bigintdyn {
/**
 * @brief The class for representing vectors of ubint with associated modulo
 * math
 */

class mubintvec

私有成员

 private:
  ubint_el_t m_modulus;

  enum State { INITIALIZED, GARBAGE };

  // enum to store the state of the
  State m_modulus_state;

  std::vector<ubint_el_t> m_data;

  bool IndexCheck(size_t length) const {
    if (length > m_data.size()) {
      return false;
    }
    return true;
  }
};
}  // namespace bigintdyn
template <class ubint_el_t>
class mubintvec 
    : public lbcrypto::BigVectorInterface<mubintvec<ubint_el_t>, ubint_el_t>,
      public lbcrypto::Serializable {
 public:

构造和析构函数

  // CONSTRUCTORS

  /**
   * Basic constructor.
   */
  mubintvec();

  static mubintvec Single(const ubint_el_t &val, const ubint_el_t &modulus) {
    mubintvec vec(1);
    vec.m_data[0] = val;
    vec.SetModulus(modulus);
    return vec;
  }

  /**
   * Basic constructor for specifying the length of the vector.
   *
   * @param length initial size in terms of the number of entries.
   */
  explicit mubintvec(usint length);

  /**
   * Basic constructor for specifying the length and modulus of the vector.
   *
   * @param length initial size in terms of the number of entries.
   * @param modulus usint associated with entries in the vector.
   */
  explicit mubintvec(const usint length, const usint &modulus);

  /**
   * Basic constructor for specifying the length of the vector with modulus
   *
   * @param length initial size in terms of the number of entries.
   * @param modulus ubint associated with entries in the vector.
   */
  explicit mubintvec(const usint length, const ubint_el_t &modulus);

  /**
   * Basic constructor for specifying the length and modulus of the vector.
   *
   * @param length initial size in terms of the number of entries.
   * @param modulus string associated with entries in the vector.
   */
  explicit mubintvec(const usint length, const std::string &modulus);

  /**
   * Copy constructor for copying a vector
   *
   * @param rhs is the mubintvec to be copied.
   */
  explicit mubintvec(const mubintvec &rhs);

  /**
   * Move constructor for moving a vector
   *
   * @param &&rhs is the mubintvec to be moved.
   */
  mubintvec(mubintvec &&rhs);

  /**
   * Basic constructor for specifying the length of the vector with
   * modulus with initializer lists
   *
   * @param length initial size in terms of the number of entries.
   * @param modulus ubint associated with entries in the vector.
   * @param rhs initialier list of strings
   */
  explicit mubintvec(const usint length, const ubint_el_t &modulus,
                     std::initializer_list<std::string> rhs);

  /**
   * Basic constructor for specifying the length of the vector with
   * modulus with initializer lists
   *
   * @param length initial size in terms of the number of entries.
   * @param modulus ubint associated with entries in the vector.
   * @param rhs initialier list of usints
   */
  explicit mubintvec(const usint length, const ubint_el_t &modulus,
                     std::initializer_list<uint64_t> rhs);

  // constructor specifying the mubintvec as a vector of strings and modulus
  explicit mubintvec(const std::vector<std::string> &s,
                     const ubint_el_t &modulus);

  // constructor specifying the mubintvec as a vector of strings and modulus
  explicit mubintvec(const std::vector<std::string> &s,
                     const std::string &modulus);

  /**
   * Destructor.
   */
  virtual ~mubintvec();

赋值操作

  // ASSIGNMENT OPERATORS

  /**
   * Assignment operator
   *
   * @param &rhs is the mubintvec to be assigned from.
   * @return assigned mubintvec ref.
   */
  const mubintvec &operator=(const mubintvec &rhs);

  /**
   * move assignment contructor
   *
   * @param &rhs is the mubintvec to move
   * @return the return value.
   */
  const mubintvec &operator=(mubintvec &&rhs);

  /**
   * Initializer list for mubintvec.
   *
   * @param &&rhs is the list of strings to be assigned to the mubintvec.
   * @return mubintvec object
   * note if  modulus is set then mod(input) is stored
   * note modulus remains unchanged.
   */
  const mubintvec &operator=(std::initializer_list<std::string> rhs);

  /**
   * Initializer list for mubintvec.
   *
   * @param &&rhs is the list of usints to be assigned to the mubintvec.
   * @return mubintvec object
   * note if  modulus is set then mod(input) is stored
   * note modulus remains unchanged.
   */
  const mubintvec &operator=(std::initializer_list<uint64_t> rhs);

  /**
   * @param &&rhs is the usint value to assign to the zeroth entry
   * @return resulting mubintvec
   * note that modulus remains untouched.
   */
  const mubintvec &operator=(uint64_t val) {
    this->m_data[0] = val;
    for (size_t i = 1; i < GetLength(); ++i) {
      this->m_data[i] = 0;
    }
    return *this;
  }

  /**
   * @param &&rhs is the ubint value to assign to the zeroth entry
   * @return resulting mubintvec
   */
  const mubintvec &operator=(const ubint_el_t &val) {
    this->m_data[0] = val;
    for (size_t i = 1; i < this->m_data.size(); ++i) {
      this->m_data[i] = 0;
    }
    return *this;
  }

  size_t GetLength() const { return m_data.size(); }

ACCESSORS

  // ACCESSORS

  /**
   * Sets/gets a value at an index.
   * This method is slower than operator[] as it checks if index out of range
   *
   * @param index is the index to set a value at.
   */
  ubint_el_t &at(size_t i) {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "index out of range");
    }
    return this->m_data[i];
  }

  const ubint_el_t &at(size_t i) const {
    if (!this->IndexCheck(i)) {
      PALISADE_THROW(lbcrypto::math_error, "index out of range");
    }
    return this->m_data[i];
  }

  ubint_el_t &operator[](size_t i) { return this->m_data[i]; }

  const ubint_el_t &operator[](size_t i) const { return this->m_data[i]; }

  /**
   * checks the vector modulus state.
   * always returns true
   */
  bool isModulusSet(void) const { return true; }

  /**
   * Sets the vector modulus.
   *
   * @param value is the value to set.
   */
  void SetModulus(const usint &value);

  /**
   * Sets the vector modulus.
   *
   * @param value is the value to set.
   */
  void SetModulus(const ubint_el_t &value);

  /**
   * Sets the vector modulus.
   *
   * @param value is the value to set.
   */
  void SetModulus(const std::string &value);

  /**
   * Sets the vector modulus to the same as another mubintvec
   *
   * @param value is the vector whose modulus to use.
   */
  void SetModulus(const mubintvec &value);

  /**
   * Sets the vector modulus and changes the values to match the new modulus.
   *
   * @param value is the value to set.
   */
  void SwitchModulus(const ubint_el_t &value);

  /**
   * Gets the vector modulus.
   *
   * @return the vector modulus.
   */
  const ubint_el_t &GetModulus() const;

模算术

  // MODULUS ARITHMETIC OPERATIONS

  /**
   * Vector modulus operator.
   * Side effect it resets the vector modulus to modulus
   *
   * @param &modulus is the modulus to perform on the current vector entries.
   * @return is the result of the modulus operation on current vector.
   */
  mubintvec Mod(const ubint_el_t &modulus) const;

  /**
   * Vector modulus operator. In-place variant.
   * Side effect it resets the vector modulus to modulus
   *
   * @param &modulus is the modulus to perform on the current vector entries.
   * @return is the result of the modulus operation on current vector.
   */
  const mubintvec &ModEq(const ubint_el_t &modulus);

  /**
   * Scalar-to-vector modulus addition operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus addition operation.
   */
  mubintvec ModAdd(const ubint_el_t &b) const;

  /**
   * Scalar-to-vector modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus addition operation.
   */
  const mubintvec &ModAddEq(const ubint_el_t &b);

  /**
   * Scalar modulus addition at a particular index.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  mubintvec ModAddAtIndex(usint i, const ubint_el_t &b) const;

  /**
   * Scalar modulus addition at a particular index. In-place variant.
   *
   * @param i is the index of the entry to add.
   * @param &b is the scalar to add.
   * @return is the result of the modulus addition operation.
   */
  const mubintvec &ModAddAtIndexEq(usint i, const ubint_el_t &b);

  /**
   * Vector component wise modulus addition.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus addition operation.
   */
  mubintvec ModAdd(const mubintvec &b) const;

  /**
   * Vector component wise modulus addition. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus addition operation.
   */
  const mubintvec &ModAddEq(const mubintvec &b);

  /**
   * Scalar-from-vector modulus subtraction operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus subtraction operation.
   */
  mubintvec ModSub(const ubint_el_t &b) const;

  /**
   * Scalar-from-vector modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus subtraction operation.
   */
  const mubintvec &ModSubEq(const ubint_el_t &b);

  /**
   * Vector component wise modulus subtraction.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus subtraction operation.
   */
  mubintvec ModSub(const mubintvec &b) const;

  /**
   * Vector component wise modulus subtraction. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus subtraction operation.
   */
  const mubintvec &ModSubEq(const mubintvec &b);

  /**
   * Scalar-to-vector modulus multiplication operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus multiplication operation.
   */
  mubintvec ModMul(const ubint_el_t &b) const;

  /**
   * Scalar-to-vector modulus multiplication operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus multiplication operation.
   */
  const mubintvec &ModMulEq(const ubint_el_t &b);

  /**
   * Vector component wise modulus multiplication.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus multiplication
   * operation.
   */
  mubintvec ModMul(const mubintvec &b) const;

  /**
   * Vector component wise modulus multiplication. In-place variant.
   *
   * @param &b is the vector to perform operation with.
   * @return is the result of the component wise modulus multiplication
   * operation.
   */
  const mubintvec &ModMulEq(const mubintvec &b);

  /**
   * Scalar modulus exponentiation operation.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus exponentiation operation.
   */
  mubintvec ModExp(const ubint_el_t &b) const;

  /**
   * Scalar modulus exponentiation operation. In-place variant.
   *
   * @param &b is the scalar to perform operation with.
   * @return is the result of the modulus exponentiation operation.
   */
  const mubintvec &ModExpEq(const ubint_el_t &b);

  /**
   * Modulus inverse operation.
   *
   * @return is the result of the component wise modulus inverse operation.
   */
  mubintvec ModInverse() const;

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @return is the result of the component wise modulus inverse operation.
   */
  const mubintvec &ModInverseEq();

  /**
   * Modulus 2 operation, also a least significant bit.
   *
   * @return is the result of the component wise modulus 2 operation, also a
   * least significant bit.
   */
  mubintvec ModByTwo() const;

  /**
   * Modulus 2 operation, also a least significant bit. In-place variant.
   *
   * @return is the result of the component wise modulus 2 operation, also a
   * least significant bit.
   */
  const mubintvec &ModByTwoEq();

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  mubintvec MultiplyAndRound(const ubint_el_t &p, const ubint_el_t &q) const;

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const mubintvec &MultiplyAndRoundEq(const ubint_el_t &p, const ubint_el_t &q);

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  mubintvec DivideAndRound(const ubint_el_t &q) const;

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const mubintvec &DivideAndRoundEq(const ubint_el_t &q);

其他函数

  // OTHER FUNCTIONS

  /**
   * Digit vector at a specific index for all entries for a given number base.
   * Warning: only power-of-2 bases are currently supported.
   * Example: for vector (83, 1, 45), index 2 and base 4 we have:
   *
   *                           index:0,1,2,3
   * |83|                           |3,0,1,1|                 |1|
   * |1 | --base 4 decomposition--> |1,0,0,0| --at index 2--> |0|
   * |45|                           |1,3,2,0|                 |2|
   *
   * The return vector is (1,0,2)
   *
   * @param index is the index to return the digit from in all entries.
   * @param base is the base to use for the operation.
   * @return is the digit at a specific index for all entries for a given number
   * base
   */
  mubintvec GetDigitAtIndexForBase(usint index, usint base) const;

输出和序列化

  // STRINGS & STREAMS

  /**
   * ostream output << operator.
   *
   * @param os is the std ostream object.
   * @param ptr_obj is mubintvec to be printed.
   * @return is the ostream object.
   */
  friend std::ostream &operator<<(std::ostream &os, const mubintvec &ptr_obj) {
#if 0  // old way
    os << std::endl;
    for (usint i = 0; i < ptr_obj.m_data.size(); i++) {
      os << ptr_obj.m_data[i] << std::endl;
    }
    os << "modulus: " << ptr_obj.m_modulus;
    os << std::endl;
#else
    auto len = ptr_obj.m_data.size();
    os << "[";
    for (usint i = 0; i < len; i++) {
      os << ptr_obj.m_data[i];
      os << ((i == (len - 1)) ? "]" : " ");
    }
    os << " modulus: " << ptr_obj.m_modulus;
#endif
    return os;
  }

  // SERIALIZATION

  template <class Archive>
  void save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("d", m_data));
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("ms", m_modulus_state));
  }

  template <class Archive>
  void load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ar(::cereal::make_nvp("d", m_data));
    ar(::cereal::make_nvp("m", m_modulus));
    ar(::cereal::make_nvp("ms", m_modulus_state));
  }

  std::string SerializedObjectName() const { return "ExpVector"; }

  static uint32_t SerializedVersion() { return 1; }

\core\include\math\bigintntl\ubintntl.h

This file contains the C++ code for implementing the main class for big integers: gmpint which replaces BBI and uses NTL
使用NTL实现

#include "config_core.h"
#ifdef WITH_NTL

#include <NTL/ZZ.h>
#include <NTL/ZZ_limbs.h>

#include <exception>
#include <fstream>
#include <functional>
#include <iostream>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>
#include <typeinfo>
#include <vector>

#include "utils/exception.h"
#include "utils/inttypes.h"
#include "utils/memory.h"

#include "utils/debug.h"

/**
 *@namespace NTL
 * The namespace of this code
 */
namespace NTL {
// log2 constants
/**
 * @brief  Struct to find log value of N.
 *Needed in the preprocessing step of ubint to determine bitwidth.
 *
 * @tparam N bitwidth.
 */
template <usint N>
struct Log2 {
  static const usint value = 1 + Log2<N / 2>::value;
};

/**
 * @brief Struct to find log 2 value of N.
 *Base case for recursion.
 *Needed in the preprocessing step of ubint to determine bitwidth.
 */
template <>
struct Log2<2> {
  static const usint value = 1;
};

类 myZZ

class myZZ : public NTL::ZZ, public lbcrypto::BigIntegerInterface<myZZ> {
 public:
  // CONSTRUCTORS

  /**
   * Default constructor.
   */
  myZZ();

  /**
   * Copy constructor.
   *
   * @param &val is the ZZ to be copied.
   */
  myZZ(const NTL::ZZ &val);

  /**
   * Move constructor.
   *
   * @param &&val is the ZZ to be copied.
   */
  myZZ(NTL::ZZ &&val);

  // TODO: figure out how to do && for wrapper
  // myZZ(NTL::myZZ_p &&a);

  /**
   * Constructor from a string.
   *
   * @param &strval is the initial integer represented as a string.
   */
  explicit myZZ(const std::string &strval);

  /**
   * Constructor from an unsigned integer.
   *
   * @param val is the initial integer represented as a uint64_t.
   */
  myZZ(uint64_t val);
#if defined(HAVE_INT128)
  myZZ(unsigned __int128 val);
#endif

  /**
   * Constructors from smaller basic types
   *
   * @param val is the initial integer represented as a basic integer type.
   */
  myZZ(int val) : myZZ(uint64_t(val)) {}
  myZZ(uint32_t val) : myZZ(uint64_t(val)) {}
  myZZ(long val) : myZZ(uint64_t(val)) {}
  myZZ(long long val) : myZZ(uint64_t(val)) {}

  /**
   * Constructor from a NativeInteger
   *
   * @param &val is the initial integer represented as a native integer.
   */
  template <typename T>
  myZZ(const bigintnat::NativeIntegerT<T> &val) : myZZ(val.ConvertToInt()) {}

  /**
   * Constructor from double is not permitted
   *
   * @param val
   */
  myZZ(double val)
      __attribute__((deprecated("Cannot construct from a double")));

  // ASSIGNMENT OPERATORS

  /**
   * Copy assignment operator
   *
   * @param &val is the myZZ to be assigned from.
   * @return assigned myZZ ref.
   */
  const myZZ &operator=(const myZZ &val);

  // TODO move assignment operator?

  /**
   * Assignment operator from string
   *
   * @param strval is the string to be assigned from
   * @return the assigned myZZ ref.
   */
  inline const myZZ &operator=(std::string strval) {
    *this = myZZ(strval);
    return *this;
  }

  /**
   * Assignment operator from unsigned integer
   *
   * @param val is the unsigned integer to be assigned from.
   * @return the assigned myZZ ref.
   */
  const myZZ &operator=(uint64_t val) {
    *this = myZZ(val);
    return *this;
  }

  // ACCESSORS

  /**
   * Basic set method for setting the value of a myZZ
   *
   * @param strval is the string representation of the ubint to be copied.
   */
  void SetValue(const std::string &strval);

  /**
   * Basic set method for setting the value of a myZZ
   *
   * @param a is the unsigned big int representation to be assigned.
   */
  void SetValue(const myZZ &val);

  void SetIdentity() { *this = 1; }

  // ARITHMETIC OPERATIONS

  /**
   * Addition operation.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  myZZ Add(const myZZ &b) const {
    return *static_cast<const ZZ *>(this) + static_cast<const ZZ &>(b);
  }

  /**
   * Addition operation. In-place variant.
   *
   * @param &b is the value to add.
   * @return result of the addition operation.
   */
  const myZZ &AddEq(const myZZ &b) {
    *static_cast<ZZ *>(this) += static_cast<const ZZ &>(b);
    return *this;
  }

  /**
   * Subtraction operation.
   * Note that in Sub we return 0, if a<b
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  myZZ Sub(const myZZ &b) const {
    return (*this < b)
               ? ZZ(0)
               : (*static_cast<const ZZ *>(this) - static_cast<const ZZ &>(b));
  }

  /**
   * Subtraction operation. In-place variant.
   * Note that in Sub we return 0, if a<b
   *
   * @param &b is the value to subtract.
   * @return is the result of the subtraction operation.
   */
  const myZZ &SubEq(const myZZ &b) {
    if (*this < b) {
      *this = ZZ(0);
    } else {
      *static_cast<ZZ *>(this) -= static_cast<const ZZ &>(b);
    }
    return *this;
  }

  /**
   * Multiplication operation.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  myZZ Mul(const myZZ &b) const {
    return *static_cast<const ZZ *>(this) * static_cast<const ZZ &>(b);
  }

  /**
   * Multiplication operation. In-place variant.
   *
   * @param &b is the value to multiply with.
   * @return is the result of the multiplication operation.
   */
  const myZZ &MulEq(const myZZ &b) {
    *static_cast<ZZ *>(this) *= static_cast<const ZZ &>(b);
    return *this;
  }

  /**
   * Division operation.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  myZZ DividedBy(const myZZ &b) const {
    return *static_cast<const ZZ *>(this) / static_cast<const ZZ &>(b);
  }

  /**
   * Division operation. In-place variant.
   *
   * @param &b is the value to divide by.
   * @return is the result of the division operation.
   */
  const myZZ &DividedByEq(const myZZ &b) {
    *static_cast<ZZ *>(this) /= static_cast<const ZZ &>(b);
    return *this;
  }

  /**
   * Exponentiation operation. Returns x^p.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  myZZ Exp(const usint p) const { return power(*this, p); }

  /**
   * Exponentiation operation. Returns x^p. In-place variant.
   *
   * @param p the exponent.
   * @return is the result of the exponentiation operation.
   */
  const myZZ &ExpEq(const usint p) {
    *this = power(*this, p);
    return *this;
  }

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  myZZ MultiplyAndRound(const myZZ &p, const myZZ &q) const;

  /**
   * Multiply and Rounding operation. Returns [x*p/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &p is the numerator to be multiplied.
   * @param &q is the denominator to be divided.
   * @return is the result of multiply and round operation.
   */
  const myZZ &MultiplyAndRoundEq(const myZZ &p, const myZZ &q);

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  myZZ DivideAndRound(const myZZ &q) const;

  /**
   * Divide and Rounding operation. Returns [x/q] where [] is the rounding
   * operation. In-place variant.
   *
   * @param &q is the denominator to be divided.
   * @return is the result of divide and round operation.
   */
  const myZZ &DivideAndRoundEq(const myZZ &q);

  // MODULAR ARITHMETIC OPERATIONS

  /**
   * Naive modulus operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  myZZ Mod(const myZZ &modulus) const {
    return *static_cast<const ZZ *>(this) % static_cast<const ZZ &>(modulus);
  }

  /**
   * Naive modulus operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus operation.
   */
  const myZZ &ModEq(const myZZ &modulus) {
    *static_cast<ZZ *>(this) %= static_cast<const ZZ &>(modulus);
    return *this;
  }

  /**
   * Pre-computes the mu factor that is used in Barrett modulo reduction
   *
   * @return the value of mu
   */
  myZZ ComputeMu() const {
    myZZ temp(1);
    temp <<= (2 * this->GetMSB() + 3);
    return temp.DividedBy(*this);
    return temp;
  }

  /**
   * Barrett modulus operation.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  myZZ Mod(const myZZ &modulus, const myZZ &mu) const {
    return *static_cast<const ZZ *>(this) % static_cast<const ZZ &>(modulus);
  }

  /**
   * Barrett modulus operation. In-place variant.
   * Implements generalized Barrett modular reduction algorithm. Uses one
   * precomputed value of mu.
   *
   * @param &modulus is the modulus to perform.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus operation.
   */
  const myZZ &ModEq(const myZZ &modulus, const myZZ &mu) {
    *static_cast<ZZ *>(this) %= static_cast<const ZZ &>(modulus);
    return *this;
  }

  /**
   * Modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  myZZ ModAdd(const myZZ &b, const myZZ &modulus) const {
    return AddMod(this->Mod(modulus), b.Mod(modulus), modulus);
  }

  /**
   * Modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const myZZ &ModAddEq(const myZZ &b, const myZZ &modulus) {
    AddMod(*this, this->Mod(modulus), b.Mod(modulus), modulus);
    return *this;
  }

  /**
   * Modulus addition where operands are < modulus.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  myZZ ModAddFast(const myZZ &b, const myZZ &modulus) const {
    return AddMod(*this, b, modulus);
  }

  /**
   * Modulus addition where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus addition operation.
   */
  const myZZ &ModAddFastEq(const myZZ &b, const myZZ &modulus) {
    *this = AddMod(*this, b, modulus);
    return *this;
  }

  /**
   * Barrett modulus addition operation.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  myZZ ModAdd(const myZZ &b, const myZZ &modulus, const myZZ &mu) const {
    return AddMod(*this, b, modulus);
  }

  /**
   * Barrett modulus addition operation. In-place variant.
   *
   * @param &b is the scalar to add.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus addition operation.
   */
  const myZZ &ModAddEq(const myZZ &b, const myZZ &modulus, const myZZ &mu) {
    *this = AddMod(*this, b, modulus);
    return *this;
  }

  /**
   * Modulus subtraction operation.
   * NOTE ModSub needs to return signed modulus (i.e. -1/2..q/2) in order
   * to be consistent with BE 2
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  myZZ ModSub(const myZZ &b, const myZZ &modulus) const {
    myZZ newthis(*this % modulus);
    myZZ newb(b % modulus);
    if (newthis >= newb) {
      myZZ tmp(SubMod(newthis, newb, modulus));  // normal mod sub
      return tmp;
    } else {
      myZZ tmp(newthis + modulus - newb);  // signed mod
      return tmp;
    }
  }

  /**
   * Modulus subtraction operation. In-place variant.
   * NOTE ModSub needs to return signed modulus (i.e. -1/2..q/2) in order
   * to be consistent with BE 2
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const myZZ &ModSubEq(const myZZ &b, const myZZ &modulus) {
    this->ModEq(modulus);
    myZZ newb(b % modulus);
    if (*this >= newb) {
      SubMod(*this, *this, newb, modulus);  // normal mod sub
      return *this;
    } else {
      this->AddEq(modulus);
      this->SubEq(newb);  // signed mod
      return *this;
    }
  }

  /**
   * Modulus subtraction where operands are < modulus.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  myZZ ModSubFast(const myZZ &b, const myZZ &modulus) const {
    if (*this >= b) {
      return SubMod(*this, b, modulus);  // normal mod sub
    } else {
      return (*this + modulus - b);  // signed mod
    }
  }

  /**
   * Modulus subtraction where operands are < modulus. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus subtraction operation.
   */
  const myZZ &ModSubFastEq(const myZZ &b, const myZZ &modulus) {
    if (*this >= b) {
      return *this = SubMod(*this, b, modulus);  // normal mod sub
    } else {
      return *this = (*this + modulus - b);  // signed mod
    }
  }

  /**
   * Barrett modulus subtraction operation.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  myZZ ModSub(const myZZ &b, const myZZ &modulus, const myZZ &mu) const {
    myZZ newthis(*this % modulus);
    myZZ newb(b % modulus);
    if (newthis >= newb) {
      myZZ tmp(SubMod(newthis, newb, modulus));  // normal mod sub
      return tmp;
    } else {
      myZZ tmp(newthis + modulus - newb);  // signed mod
      return tmp;
    }
  }

  /**
   * Barrett modulus subtraction operation. In-place variant.
   *
   * @param &b is the scalar to subtract.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus subtraction operation.
   */
  const myZZ &ModSubEq(const myZZ &b, const myZZ &modulus, const myZZ &mu) {
    this->ModEq(modulus);
    myZZ newb(b % modulus);
    if (*this >= newb) {
      SubMod(*this, *this, newb, modulus);  // normal mod sub
      return *this;
    } else {
      this->AddEq(modulus);
      this->SubEq(newb);  // signed mod
      return *this;
    }
  }

  /**
   * Modulus multiplication operation.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  myZZ ModMul(const myZZ &b, const myZZ &modulus) const {
    return MulMod(this->Mod(modulus), b.Mod(modulus), modulus);
  }

  /**
   * Modulus multiplication operation. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const myZZ &ModMulEq(const myZZ &b, const myZZ &modulus) {
    MulMod(*this, this->Mod(modulus), b.Mod(modulus), modulus);
    return *this;
  }

  /**
   * Barrett modulus multiplication.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  myZZ ModMul(const myZZ &b, const myZZ &modulus, const myZZ &mu) const {
    return MulMod(this->Mod(modulus), b.Mod(modulus), modulus);
  }

  /**
   * Barrett modulus multiplication. In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const myZZ &ModMulEq(const myZZ &b, const myZZ &modulus, const myZZ &mu) {
    MulMod(*this, this->Mod(modulus), b.Mod(modulus), modulus);
    return *this;
  }

  /**
   * Modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  inline myZZ ModMulFast(const myZZ &b, const myZZ &modulus) const {
    return MulMod(*this, b, modulus);
  }

  /**
   * Modulus multiplication that assumes the operands are < modulus. In-place
   * variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus multiplication operation.
   */
  const myZZ &ModMulFastEq(const myZZ &b, const myZZ &modulus) {
    *this = MulMod(*this, b, modulus);
    return *this;
  }

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  inline myZZ ModMulFast(const myZZ &b, const myZZ &modulus,
                         const myZZ &mu) const {
    return MulMod(*this, b, modulus);
  }

  /**
   * Barrett modulus multiplication that assumes the operands are < modulus.
   * In-place variant.
   *
   * @param &b is the scalar to multiply.
   * @param &modulus is the modulus to perform operations with.
   * @param &mu is the Barrett value.
   * @return is the result of the modulus multiplication operation.
   */
  const myZZ &ModMulFastEq(const myZZ &b, const myZZ &modulus, const myZZ &mu) {
    *this = MulMod(*this, b, modulus);
    return *this;
  }

  myZZ ModMulFastConst(const myZZ &b, const myZZ &modulus,
                       const myZZ &bInv) const {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConst is not implemented for backend 6");
  }

  const myZZ &ModMulFastConstEq(const myZZ &b, const myZZ &modulus,
                                const myZZ &bInv) {
    PALISADE_THROW(lbcrypto::not_implemented_error,
                   "ModMulFastConstEq is not implemented for backend 6");
  }

  /**
   * Modulus exponentiation operation.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  inline myZZ ModExp(const myZZ &b, const myZZ &modulus) const {
    myZZ res;
    PowerMod(res, *this, b, modulus);
    return res;
  }

  /**
   * Modulus exponentiation operation. In-place variant.
   *
   * @param &b is the scalar to exponentiate at all locations.
   * @param &modulus is the modulus to perform operations with.
   * @return is the result of the modulus exponentiation operation.
   */
  const myZZ &ModExpEq(const myZZ &b, const myZZ &modulus) {
    PowerMod(*this, *this, b, modulus);
    return *this;
  }

  /**
   * Modulus inverse operation.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  myZZ ModInverse(const myZZ &modulus) const {
    if (modulus == myZZ(0)) {
      PALISADE_THROW(lbcrypto::math_error, "zero has no inverse");
    }
    myZZ tmp(0);
    try {
      tmp = InvMod(*this % modulus, modulus);
    } catch (InvModErrorObject
                 &e) {  // note this code requires NTL Excptions coto be turned
                        // on. TODO: provide alternative when that is off.
      std::stringstream errmsg;
      errmsg << "ModInverse exception "
             << " this: " << *this << " modulus: " << modulus << "GCD("
             << e.get_a() << "," << e.get_n() << "!=1" << std::endl;
      PALISADE_THROW(lbcrypto::math_error, errmsg.str());
    }
    return tmp;
  }

  /**
   * Modulus inverse operation. In-place variant.
   *
   * @param &modulus is the modulus to perform.
   * @return is the result of the modulus inverse operation.
   */
  const myZZ &ModInverseEq(const myZZ &modulus) {
    if (modulus == myZZ(0)) {
      PALISADE_THROW(lbcrypto::math_error, "zero has no inverse");
    }
    try {
      *this = InvMod(*this % modulus, modulus);
    } catch (InvModErrorObject
                 &e) {  // note this code requires NTL Excptions coto be turned
                        // on. TODO: provide alternative when that is off.
      std::stringstream errmsg;
      errmsg << "ModInverse exception "
             << " this: " << *this << " modulus: " << modulus << "GCD("
             << e.get_a() << "," << e.get_n() << "!=1" << std::endl;
      PALISADE_THROW(lbcrypto::math_error, errmsg.str());
    }
    return *this;
  }

  /**
   * Left shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  myZZ LShift(usshort shift) const {
    return *static_cast<const ZZ *>(this) << shift;
  }

  /**
   * Left shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const myZZ &LShiftEq(usshort shift) {
    *static_cast<ZZ *>(this) <<= shift;
    return *this;
  }

  /**
   * Right shift operation.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  myZZ RShift(usshort shift) const {
    return *static_cast<const ZZ *>(this) >> shift;
  }

  /**
   * Right shift operation. In-place variant.
   *
   * @param shift # of bits.
   * @return result of the shift operation.
   */
  const myZZ &RShiftEq(usshort shift) {
    *static_cast<ZZ *>(this) >>= shift;
    return *this;
  }

  // COMPARE

  // comparison method inline for speed
  int Compare(const myZZ &a) const { return compare(*this, a); }

  // CONVERTING

  // palisade conversion methods
  uint64_t ConvertToInt() const;

  uint64_t ConvertToUint64() const;

  double ConvertToDouble() const;

  /**
   * Convert a string representation of a binary number to a myZZ.
   * Note: needs renaming to a generic form since the variable type name is
   * embedded in the function name. Suggest FromBinaryString()
   * @param bitString the binary num in string.
   * @return the  number represented as a ubint.
   */
  static myZZ FromBinaryString(const std::string &bitString);

  // OTHER FUNCTIONS

  // adapter kit that wraps ZZ with BACKEND 2 functionality

  static const myZZ &zero();

  usint GetMSB() const;

  /**
   * Get the number of digits using a specific base - support for
   * arbitrary base may be needed.
   *
   * @param base is the base with which to determine length in.
   * @return the length of the representation in a specific base.
   */
  usint GetLengthForBase(usint base) const { return GetMSB(); }

  /**
   * Get the integer value of the of a subfield of bits. Where the length of
   * the field is specifice by a power of two base
   * Warning: only power-of-2 bases are currently supported.
   * Example: for number 83, index 2 and base 4 we have:
   *
   *                         index:0,1,2,3
   * 83 --base 4 decomposition--> (3,0,1,1) --at index 2--> 1
   *
   * The return number is 1.
   *
   * @param index is the bit location (lsb)
   * @param base such that log2(base)+1 is the bitwidth of the subfield
   * @return the unsigned integer value of the subfield
   */
  usint GetDigitAtIndexForBase(usint index, usint base) const;

  // variable to store the log(base 2) of the number of bits in the
  // limb data type.
  static const usint m_log2LimbBitLength;

  /**
   * Gets a subset of bits of a given length with LSB at specified index.
   * optimized for speed in backend 6
   * @param index of the set of bit to get. LSB=1
   * @param length of the set of bits to get. LSB=1
   * @return resulting unsigned in formed by set of bits.
   */
  usint GetBitRangeAtIndex(usint index, usint length) const;

  /**
   * Gets the bit at the specified index.
   *
   * @param index of the bit to get. LSB=1
   * @return resulting bit.
   */
  uschar GetBitAtIndex(usint index) const;

  /**
   * A zero allocator that is called by the Matrix class. It is used to
   * initialize a Matrix of myZZ objects.
   */
  static myZZ Allocator() { return 0; }

  // STRINGS & STREAMS

  // palisade string conversion
  const std::string ToString() const;

  static const std::string IntegerTypeName() { return "UBNTLINT"; }

  // big integer stream output
  friend std::ostream &operator<<(std::ostream &os, const myZZ &ptr_obj);

  /**
   * Gets a copy of the  internal limb storage
   * Used primarily for debugging
   */
  std::string GetInternalRepresentation(void) const {
    std::string ret("");
    const ZZ_limb_t *zlp = ZZ_limbs_get(*this);

    for (size_t i = 0; i < (size_t)this->size(); i++) {
      ret += std::to_string(zlp[i]);
      if (i < ((size_t)this->size() - 1)) {
        ret += " ";
      }
    }
    return ret;
  }

  /// SERIALIZATION

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    void *data = this->rep.rep;
    ::cereal::size_type len = 0;
    if (data == nullptr) {
      ar(::cereal::binary_data(&len, sizeof(len)));
    } else {
      len = _ntl_ALLOC(this->rep.rep);

      ar(::cereal::binary_data(&len, sizeof(len)));
      ar(::cereal::binary_data(data, len * sizeof(_ntl_gbigint)));
      ar(::cereal::make_nvp("mb", m_MSB));
    }
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  save(Archive &ar, std::uint32_t const version) const {
    ar(::cereal::make_nvp("v", ToString()));
  }

  template <class Archive>
  typename std::enable_if<!cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    ::cereal::size_type len;
    ar(::cereal::binary_data(&len, sizeof(len)));
    if (len == 0) {
      *this = 0;
      return;
    }

    void *mem = malloc(len * sizeof(_ntl_gbigint));
    ar(::cereal::binary_data(mem, len * sizeof(_ntl_gbigint)));
    WrappedPtr<_ntl_gbigint_body, Deleter> newrep;
    newrep.rep = reinterpret_cast<_ntl_gbigint_body *>(mem);
    _ntl_gswap(&this->rep, &newrep);

    ar(::cereal::make_nvp("mb", m_MSB));
  }

  template <class Archive>
  typename std::enable_if<cereal::traits::is_text_archive<Archive>::value,
                          void>::type
  load(Archive &ar, std::uint32_t const version) {
    if (version > SerializedVersion()) {
      PALISADE_THROW(lbcrypto::deserialize_error,
                     "serialized object version " + std::to_string(version) +
                         " is from a later version of the library");
    }
    std::string s;
    ar(::cereal::make_nvp("v", s));
    *this = s;
  }

  std::string SerializedObjectName() const { return "NTLInteger"; }

  static uint32_t SerializedVersion() { return 1; }

 private:
  // adapter kits
  void SetMSB();

  /**
   * function to return the ceiling of the input number divided by
   * the number of bits in the limb data type.  DBC this is to
   * determine how many limbs are needed for an input bitsize.
   * @param Number is the number to be divided.
   * @return the ceiling of Number/(bits in the limb data type)
   */
  // todo: rename to MSB2NLimbs()
  static usint ceilIntByUInt(const ZZ_limb_t Number);

  mutable uint32_t m_MSB;
  usint GetMSBLimb_t(ZZ_limb_t x) const;
};
// class ends

NTL_DECLARE_RELOCATABLE((myZZ *))
}  // namespace NTL

\core\include\math\bigintntl\mubintvecntl.h

This file contains mgmpintvec, a <vector> of gmpint, with associated math operators
This file contains mgmpintvec, a <vector> of gmpint, with associated math operators.

  • NOTE: this has been refactored so that implied modulo (ring) aritmetic is in mbintvec
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值