HEAAN源码(二)

文章目录

  • HEAAN源码(二)
    • Scheme.h
    • Scheme.cpp
    • SchemeAlgo.h
    • SchemeAlgo.cpp

Scheme.h

#ifndef HEAAN_SCHEME_H_
#define HEAAN_SCHEME_H_#include <NTL/RR.h>
#include <NTL/ZZ.h>
#include <complex>
#include <string>#include "BootContext.h"
#include "SecretKey.h"
#include "Ciphertext.h"
#include "Plaintext.h"
#include "Key.h"
#include "EvaluatorUtils.h"
#include "Ring.h"namespace heaan {static long ENCRYPTION = 0;
static long MULTIPLICATION  = 1;
static long CONJUGATION = 2;class Scheme {private:
public:Ring& ring;bool isSerialized;std::map<long, Key*> keyMap; ///< contain Encryption, Multiplication and Conjugation keys, if generatedstd::map<long, Key*> leftRotKeyMap; ///< contain left rotation keys, if generatedstd::map<long, std::string> serKeyMap; ///< contain Encryption, Multiplication and Conjugation keys, if generatedstd::map<long, std::string> serLeftRotKeyMap; ///< contain left rotation keys, if generatedScheme(SecretKey& secretKey, Ring& ring, bool isSerialized = false);virtual ~Scheme();//----------------------------------------------------------------------------------//   KEYS GENERATION//----------------------------------------------------------------------------------void addEncKey(SecretKey& secretKey);void addMultKey(SecretKey& secretKey);void addConjKey(SecretKey& secretKey);void addLeftRotKey(SecretKey& secretKey, long r);void addRightRotKey(SecretKey& secretKey, long r);void addLeftRotKeys(SecretKey& secretKey);void addRightRotKeys(SecretKey& secretKey);void addBootKey(SecretKey& secretKey, long logl, long logp);//----------------------------------------------------------------------------------//   ENCODING & DECODING//----------------------------------------------------------------------------------void encode(Plaintext& plain, std::complex<double>* vals, long n, long logp, long logq);void encode(Plaintext& plain, double* vals, long n, long logp, long logq);std::complex<double>* decode(Plaintext& plain);void encodeSingle(Plaintext& plain, std::complex<double> val, long logp, long logq);void encodeSingle(Plaintext& plain, double val, long logp, long logq);std::complex<double> decodeSingle(Plaintext& plain);//----------------------------------------------------------------------------------//   ENCRYPTION & DECRYPTION//----------------------------------------------------------------------------------void encryptMsg(Ciphertext& cipher, Plaintext& plain);void decryptMsg(Plaintext& plain, SecretKey& secretKey, Ciphertext& cipher);void encrypt(Ciphertext& cipher, std::complex<double>* vals, long n, long logp, long logq);void encrypt(Ciphertext& cipher, double* vals, long n, long logp, long logq);void encryptBySk(Ciphertext& cipher, SecretKey& secretKey, std::complex<double>* vals, long n, long logp, long logq, double=3.2);void encryptBySk(Ciphertext& cipher, SecretKey& secretKey, double* vals, long n, long logp, long logq, double=3.2);void encryptZeros(Ciphertext& cipher, long n, long logp, long logq);std::complex<double>* decrypt(SecretKey& secretKey, Ciphertext& cipher);std::complex<double>* decryptForShare(SecretKey& secretKey, Ciphertext& cipher, long=0);void encryptSingle(Ciphertext& cipher, std::complex<double> val, long logp, long logq);void encryptSingle(Ciphertext& cipher, double val, long logp, long logq);std::complex<double> decryptSingle(SecretKey& secretKey, Ciphertext& cipher);//----------------------------------------------------------------------------------//   HOMOMORPHIC OPERATIONS//----------------------------------------------------------------------------------void negate(Ciphertext& res, Ciphertext& cipher);void negateAndEqual(Ciphertext& cipher);void add(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2);void addAndEqual(Ciphertext& cipher1, Ciphertext& cipher2);void addConst(Ciphertext& res, Ciphertext& cipher, double cnst, long logp);void addConst(Ciphertext& res, Ciphertext& cipher, NTL::RR& cnst, long logp);void addConst(Ciphertext& res, Ciphertext& cipher, std::complex<double> cnst, long logp);void addConstAndEqual(Ciphertext& cipher, double cnst, long logp);void addConstAndEqual(Ciphertext& cipher, NTL::RR& cnst, long logp);void addConstAndEqual(Ciphertext& cipher, std::complex<double> cnst, long logp);void sub(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2);void subAndEqual(Ciphertext& cipher1, Ciphertext& cipher2);void subAndEqual2(Ciphertext& cipher1, Ciphertext& cipher2);void imult(Ciphertext& res, Ciphertext& cipher);void idiv(Ciphertext& res, Ciphertext& cipher);void imultAndEqual(Ciphertext& cipher);void idivAndEqual(Ciphertext& cipher);void mult(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2);void multAndEqual(Ciphertext& cipher1, Ciphertext& cipher2);void square(Ciphertext& res, Ciphertext& cipher);void squareAndEqual(Ciphertext& cipher);void multByConst(Ciphertext& res, Ciphertext& cipher, double cnst, long logp);void multByConst(Ciphertext& res, Ciphertext& cipher, std::complex<double> cnst, long logp);void multByConstVec(Ciphertext& res, Ciphertext& cipher, std::complex<double>* cnstVec, long logp);void multByConstVecAndEqual(Ciphertext& cipher, std::complex<double>* cnstVec, long logp);void multByConstAndEqual(Ciphertext& cipher, double cnst, long logp);void multByConstAndEqual(Ciphertext& cipher, NTL::RR& cnst, long logp);void multByConstAndEqual(Ciphertext& cipher, std::complex<double> cnst, long logp);void multByPoly(Ciphertext& res, Ciphertext& cipher, NTL::ZZ* poly, long logp);void multByPolyNTT(Ciphertext& res, Ciphertext& cipher, uint64_t* rpoly, long bnd, long logp);void multByPolyAndEqual(Ciphertext& cipher, NTL::ZZ* poly, long logp);void multByPolyNTTAndEqual(Ciphertext& cipher, uint64_t* rpoly, long bnd, long logp);void multByMonomial(Ciphertext& res, Ciphertext& cipher, const long degree);void multByMonomialAndEqual(Ciphertext& cipher, const long degree);void leftShift(Ciphertext& res, Ciphertext& cipher, long bits);void leftShiftAndEqual(Ciphertext& cipher, long bits);void doubleAndEqual(Ciphertext& cipher);void divByPo2(Ciphertext& res, Ciphertext& cipher, long bits);void divByPo2AndEqual(Ciphertext& cipher, long bits);//----------------------------------------------------------------------------------//   RESCALING//----------------------------------------------------------------------------------void reScaleBy(Ciphertext& res, Ciphertext& cipher, long dlogq);void reScaleTo(Ciphertext& res, Ciphertext& cipher, long logq);void reScaleByAndEqual(Ciphertext& cipher, long dlogq);void reScaleToAndEqual(Ciphertext& cipher, long logq);void modDownBy(Ciphertext& res, Ciphertext& cipher, long dlogq);void modDownByAndEqual(Ciphertext& cipher, long dlogq);void modDownTo(Ciphertext& res, Ciphertext& cipher, long logq);void modDownToAndEqual(Ciphertext& cipher, long logq);//----------------------------------------------------------------------------------//   ROTATIONS & CONJUGATIONS//----------------------------------------------------------------------------------void leftRotateFast(Ciphertext& res, Ciphertext& cipher, long r);void rightRotateFast(Ciphertext& res, Ciphertext& cipher, long r);void leftRotateFastAndEqual(Ciphertext& cipher, long r);void rightRotateFastAndEqual(Ciphertext& cipher, long r);void conjugate(Ciphertext& res, Ciphertext& cipher);void conjugateAndEqual(Ciphertext& cipher);//----------------------------------------------------------------------------------//   BOOTSTRAPPING//----------------------------------------------------------------------------------void normalizeAndEqual(Ciphertext& cipher);void coeffToSlotAndEqual(Ciphertext& cipher);void slotToCoeffAndEqual(Ciphertext& cipher);void exp2piAndEqual(Ciphertext& cipher, long logp);void evalExpAndEqual(Ciphertext& cipher, long logT, long logI = 4);void bootstrapAndEqual(Ciphertext& cipher, long logq, long logQ, long logT, long logI = 4);
};}  // namespace heaan#endif

Scheme.cpp

/*
* Copyright (c) by CryptoLab inc.
* This program is licensed under a
* Creative Commons Attribution-NonCommercial 3.0 Unported License.
* You should have received a copy of the license along with this
* work.  If not, see <http://creativecommons.org/licenses/by-nc/3.0/>.
*/
#include "Scheme.h"#include "NTL/BasicThreadPool.h"
#include <string>#include "StringUtils.h"
#include "SerializationUtils.h"using namespace std;
using namespace NTL;namespace heaan {Scheme::Scheme(SecretKey& secretKey, Ring& ring, bool isSerialized) : ring(ring), isSerialized(isSerialized) {addEncKey(secretKey);addMultKey(secretKey);
};Scheme::~Scheme() {for (auto const& t : keyMap)delete t.second;for (auto const& t : leftRotKeyMap)delete t.second;
}void Scheme::addEncKey(SecretKey& secretKey) {ZZ* ax = new ZZ[N];ZZ* bx = new ZZ[N];long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(ax, logQQ);ring.mult(bx, secretKey.sx, ax, np, QQ);ring.subFromGaussAndEqual(bx, QQ);Key* key = new Key();ring.CRT(key->rax, ax, nprimes);ring.CRT(key->rbx, bx, nprimes);delete[] ax; delete[] bx;if(isSerialized) {string path = "serkey/ENCRYPTION.txt";SerializationUtils::writeKey(key, path);serKeyMap.insert(pair<long, string>(ENCRYPTION, path));delete key;} else {keyMap.insert(pair<long, Key*>(ENCRYPTION, key));}
}void Scheme::addMultKey(SecretKey& secretKey) {ZZ* ax = new ZZ[N];ZZ* bx = new ZZ[N];ZZ* sxsx = new ZZ[N];long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(ax, logQQ);ring.mult(bx, secretKey.sx, ax, np, QQ);ring.subFromGaussAndEqual(bx, QQ);np = ceil((2 + logN + 2)/(double)pbnd);ring.mult(sxsx, secretKey.sx, secretKey.sx, np, Q);ring.leftShiftAndEqual(sxsx, logQ, QQ);ring.addAndEqual(bx, sxsx, QQ);delete[] sxsx;Key* key = new Key();ring.CRT(key->rax, ax, nprimes);ring.CRT(key->rbx, bx, nprimes);delete[] ax; delete[] bx;if(isSerialized) {string path = "serkey/MULTIPLICATION.txt";SerializationUtils::writeKey(key, path);serKeyMap.insert(pair<long, string>(MULTIPLICATION, path));delete key;} else {keyMap.insert(pair<long, Key*>(MULTIPLICATION, key));}
}void Scheme::addConjKey(SecretKey& secretKey) {ZZ* ax = new ZZ[N];ZZ* bx = new ZZ[N];long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(ax, logQQ);ring.mult(bx, secretKey.sx, ax, np, QQ);ring.subFromGaussAndEqual(bx, QQ);ZZ* sxconj = new ZZ[N];ring.conjugate(sxconj, secretKey.sx);ring.leftShiftAndEqual(sxconj, logQ, QQ);ring.addAndEqual(bx, sxconj, QQ);delete[] sxconj;Key* key = new Key();ring.CRT(key->rax, ax, nprimes);ring.CRT(key->rbx, bx, nprimes);delete[] ax; delete[] bx;if(isSerialized) {string path = "serkey/CONJUGATION.txt";SerializationUtils::writeKey(key, path);serKeyMap.insert(pair<long, string>(CONJUGATION, path));delete key;} else {keyMap.insert(pair<long, Key*>(CONJUGATION, key));}
}void Scheme::addLeftRotKey(SecretKey& secretKey, long r) {ZZ* ax = new ZZ[N];ZZ* bx = new ZZ[N];long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(ax, logQQ);ring.mult(bx, secretKey.sx, ax, np, QQ);ring.subFromGaussAndEqual(bx, QQ);ZZ* spow = new ZZ[N];ring.leftRotate(spow, secretKey.sx, r);ring.leftShiftAndEqual(spow, logQ, QQ);ring.addAndEqual(bx, spow, QQ);delete[] spow;Key* key = new Key();ring.CRT(key->rax, ax, nprimes);ring.CRT(key->rbx, bx, nprimes);delete[] ax; delete[] bx;if(isSerialized) {string path = "serkey/ROTATION_" + to_string(r) + ".txt";SerializationUtils::writeKey(key, path);serLeftRotKeyMap.insert(pair<long, string>(r, path));delete key;} else {leftRotKeyMap.insert(pair<long, Key*>(r, key));}
}void Scheme::addRightRotKey(SecretKey& secretKey, long r) {long idx = Nh - r;if(leftRotKeyMap.find(idx) == leftRotKeyMap.end() && serLeftRotKeyMap.find(idx) == serLeftRotKeyMap.end()) {addLeftRotKey(secretKey, idx);}
}void Scheme::addLeftRotKeys(SecretKey& secretKey) {for (long i = 0; i < logN - 1; ++i) {long idx = 1 << i;if(leftRotKeyMap.find(idx) == leftRotKeyMap.end() && serLeftRotKeyMap.find(idx) == serLeftRotKeyMap.end()) {addLeftRotKey(secretKey, idx);}}
}void Scheme::addRightRotKeys(SecretKey& secretKey) {for (long i = 0; i < logN - 1; ++i) {long idx = Nh - (1 << i);if(leftRotKeyMap.find(idx) == leftRotKeyMap.end() && serLeftRotKeyMap.find(idx) == serLeftRotKeyMap.end()) {addLeftRotKey(secretKey, idx);}}
}void Scheme::addBootKey(SecretKey& secretKey, long logl, long logp) {ring.addBootContext(logl, logp);addConjKey(secretKey);addLeftRotKeys(secretKey);long loglh = logl/2;long k = 1 << loglh;long m = 1 << (logl - loglh);for (long i = 1; i < k; ++i) {if(leftRotKeyMap.find(i) == leftRotKeyMap.end() && serLeftRotKeyMap.find(i) == serLeftRotKeyMap.end()) {addLeftRotKey(secretKey, i);}}for (long i = 1; i < m; ++i) {long idx = i * k;if(leftRotKeyMap.find(idx) == leftRotKeyMap.end() && serLeftRotKeyMap.find(idx) == serLeftRotKeyMap.end()) {addLeftRotKey(secretKey, idx);}}
}void Scheme::encode(Plaintext& plain, double* vals, long n, long logp, long logq) {plain.logp = logp;plain.logq = logq;plain.n = n;ring.encode(plain.mx, vals, n, logp + logQ);
}void Scheme::encode(Plaintext& plain, complex<double>* vals, long n, long logp, long logq) {plain.logp = logp;plain.logq = logq;plain.n = n;ring.encode(plain.mx, vals, n, logp + logQ);
}complex<double>* Scheme::decode(Plaintext& plain) {complex<double>* res = new complex<double>[plain.n];ring.decode(plain.mx, res, plain.n, plain.logp, plain.logq);return res;
}void Scheme::encodeSingle(Plaintext& plain, double val, long logp, long logq) {plain.logp = logp;plain.logq = logq;plain.n = 1;plain.mx[0] = EvaluatorUtils::scaleUpToZZ(val, logp + logQ);
}void Scheme::encodeSingle(Plaintext& plain, complex<double> val, long logp, long logq) {plain.logp = logp;plain.logq = logq;plain.n = 1;plain.mx[0] = EvaluatorUtils::scaleUpToZZ(val.real(), logp + logQ);plain.mx[Nh] = EvaluatorUtils::scaleUpToZZ(val.imag(), logp + logQ);
}complex<double> Scheme::decodeSingle(Plaintext& plain) {ZZ q = ring.qpows[plain.logq];complex<double> res;ZZ tmp = plain.mx[0] % q;if(NumBits(tmp) == plain.logq) tmp -= q;res.real(EvaluatorUtils::scaleDownToReal(tmp, plain.logp));tmp = plain.mx[Nh] % q;if(NumBits(tmp) == plain.logq) tmp -= q;res.imag(EvaluatorUtils::scaleDownToReal(tmp, plain.logp));return res;
}void Scheme::encryptMsg(Ciphertext& cipher, Plaintext& plain) {cipher.logp = plain.logp;cipher.logq = plain.logq;cipher.n = plain.n;ZZ qQ = ring.qpows[plain.logq + logQ];ZZ* vx = new ZZ[N];ring.sampleZO(vx);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(ENCRYPTION)) : keyMap.at(ENCRYPTION);long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.multNTT(cipher.ax, vx, key->rax, np, qQ);ring.multNTT(cipher.bx, vx, key->rbx, np, qQ);delete[] vx;ring.addAndEqual(cipher.bx, plain.mx, qQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);ring.addGaussAndEqual(cipher.ax, qQ);ring.addGaussAndEqual(cipher.bx, qQ);
}void Scheme::decryptMsg(Plaintext& plain, SecretKey& secretKey, Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];plain.logp = cipher.logp;plain.logq = cipher.logq;plain.n = cipher.n;long np = ceil((1 + cipher.logq + logN + 2)/(double)pbnd);ring.mult(plain.mx, cipher.ax, secretKey.sx, np, q);ring.addAndEqual(plain.mx, cipher.bx, q);
}void Scheme::encrypt(Ciphertext& cipher, complex<double>* vals, long n, long logp, long logq) {Plaintext plain;encode(plain, vals, n, logp, logq);encryptMsg(cipher, plain);
}void Scheme::encrypt(Ciphertext& cipher, double* vals, long n, long logp, long logq) {Plaintext plain;encode(plain, vals, n, logp, logq);encryptMsg(cipher, plain);
}void Scheme::encryptBySk(Ciphertext& cipher, SecretKey& secretKey, complex<double>* vals, long n, long logp, long logq, double sigma1) {Plaintext plain;encode(plain, vals, n, logp, logq);cipher.logp = plain.logp;cipher.logq = plain.logq;cipher.n = plain.n;long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(cipher.ax, logQQ);ring.mult(cipher.bx, secretKey.sx, cipher.ax, np, QQ);ring.subFromGaussAndEqual(cipher.bx, QQ, sigma1);ring.addAndEqual(cipher.bx, plain.mx, QQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);
}void Scheme::encryptBySk(Ciphertext& cipher, SecretKey& secretKey, double* vals, long n, long logp, long logq, double sigma1) {Plaintext plain;encode(plain, vals, n, logp, logq);cipher.logp = plain.logp;cipher.logq = plain.logq;cipher.n = plain.n;long np = ceil((1 + logQQ + logN + 2)/(double)pbnd);ring.sampleUniform2(cipher.ax, logQQ);ring.mult(cipher.bx, secretKey.sx, cipher.ax, np, QQ);ring.subFromGaussAndEqual(cipher.bx, QQ, sigma1);ring.addAndEqual(cipher.bx, plain.mx, QQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);
}void Scheme::encryptZeros(Ciphertext& cipher, long n, long logp, long logq) {encryptSingle(cipher, 0.0, logp, logq);cipher.n = n;
}complex<double>* Scheme::decrypt(SecretKey& secretKey, Ciphertext& cipher) {Plaintext plain;decryptMsg(plain, secretKey, cipher);return decode(plain);
}complex<double>* Scheme::decryptForShare(SecretKey& secretKey, Ciphertext& cipher, long logErrBound) {Plaintext plain;decryptMsg(plain, secretKey, cipher);double sigma1 = sigma * sqrt(2);double sigma2;double PI = 4.0 * atan(1.0);if (logErrBound == -1) {// WIDTH = 8, WIDTH1 = sqrt(2*pi)*sigma// Note that sigma is already multiplied by sqrt(2) in TestScheme.cppdouble WIDTH_sq = 64.0; double WIDTH1_sq = 2.0*PI*sigma1*sigma1;sigma2 = sqrt(WIDTH1_sq * WIDTH_sq / ((WIDTH1_sq - WIDTH_sq) * 2 * PI));} else {sigma2 = ((double) ((long) 1 << logErrBound)) / sqrt(2 * PI);}ZZ q = ring.qpows[plain.logq];ring.addGaussAndEqual(plain.mx, q, sigma2);return decode(plain);
}void Scheme::encryptSingle(Ciphertext& cipher, complex<double> val, long logp, long logq) {Plaintext plain;encodeSingle(plain, val, logp, logq);encryptMsg(cipher, plain);
}void Scheme::encryptSingle(Ciphertext& cipher, double val, long logp, long logq) {Plaintext plain;encodeSingle(plain, val, logp, logq);encryptMsg(cipher, plain);
}complex<double> Scheme::decryptSingle(SecretKey& secretKey, Ciphertext& cipher) {Plaintext plain;decryptMsg(plain, secretKey, cipher);return decodeSingle(plain);
}//-----------------------------------------void Scheme::negate(Ciphertext& res, Ciphertext& cipher) {res.copyParams(cipher);ring.negate(res.ax, cipher.ax);ring.negate(res.bx, cipher.bx);
}void Scheme::negateAndEqual(Ciphertext& cipher) {ring.negateAndEqual(cipher.ax);ring.negateAndEqual(cipher.bx);
}void Scheme::add(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];res.copyParams(cipher1);ring.add(res.ax, cipher1.ax, cipher2.ax, q);ring.add(res.bx, cipher1.bx, cipher2.bx, q);
}void Scheme::addAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];ring.addAndEqual(cipher1.ax, cipher2.ax, q);ring.addAndEqual(cipher1.bx, cipher2.bx, q);
}//-----------------------------------------void Scheme::addConst(Ciphertext& res, Ciphertext& cipher, double cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);res.copy(cipher);AddMod(res.bx[0], res.bx[0], cnstZZ, q);
}void Scheme::addConst(Ciphertext& res, Ciphertext& cipher, RR& cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);res.copy(cipher);AddMod(res.bx[0], res.bx[0], cnstZZ, q);
}void Scheme::addConst(Ciphertext& res, Ciphertext& cipher, complex<double> cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.real(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);res.copy(cipher);AddMod(res.bx[0], cipher.bx[0], cnstZZ, q);
}void Scheme::addConstAndEqual(Ciphertext& cipher, double cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);AddMod(cipher.bx[0], cipher.bx[0], cnstZZ, q);
}void Scheme::addConstAndEqual(Ciphertext& cipher, RR& cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst, cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst, logp);AddMod(cipher.bx[0], cipher.bx[0], cnstZZ, q);
}void Scheme::addConstAndEqual(Ciphertext& cipher, complex<double> cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstrZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.real(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);ZZ cnstiZZ = logp < 0 ? EvaluatorUtils::scaleUpToZZ(cnst.imag(), cipher.logp) : EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);AddMod(cipher.bx[0], cipher.bx[0], cnstrZZ, q);AddMod(cipher.bx[Nh], cipher.bx[Nh], cnstiZZ, q);
}//-----------------------------------------void Scheme::sub(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];res.copyParams(cipher1);ring.sub(res.ax, cipher1.ax, cipher2.ax, q);ring.sub(res.bx, cipher1.bx, cipher2.bx, q);
}void Scheme::subAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];ring.subAndEqual(cipher1.ax, cipher2.ax, q);ring.subAndEqual(cipher1.bx, cipher2.bx, q);
}void Scheme::subAndEqual2(Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];ring.subAndEqual2(cipher1.ax, cipher2.ax, q);ring.subAndEqual2(cipher1.bx, cipher2.bx, q);
}void Scheme::imult(Ciphertext& res, Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];res.copyParams(cipher);ring.multByMonomial(res.ax, cipher.ax, Nh);ring.multByMonomial(res.bx, cipher.bx, Nh);
}void Scheme::idiv(Ciphertext& res, Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];res.copyParams(cipher);ring.multByMonomial(res.ax, cipher.ax, 3 * Nh);ring.multByMonomial(res.bx, cipher.bx, 3 * Nh);
}void Scheme::imultAndEqual(Ciphertext& cipher) {ring.multByMonomialAndEqual(cipher.ax, Nh);ring.multByMonomialAndEqual(cipher.bx, Nh);
}void Scheme::idivAndEqual(Ciphertext& cipher) {ring.multByMonomialAndEqual(cipher.ax, 3 * Nh);ring.multByMonomialAndEqual(cipher.bx, 3 * Nh);
}void Scheme::mult(Ciphertext& res, Ciphertext& cipher1, Ciphertext& cipher2) {res.copyParams(cipher1);res.logp += cipher2.logp;ZZ q = ring.qpows[cipher1.logq];ZZ qQ = ring.qpows[cipher1.logq + logQ];long np = ceil((2 + cipher1.logq + cipher2.logq + logN + 2)/(double)pbnd);uint64_t* ra1 = new uint64_t[np << logN];uint64_t* rb1 = new uint64_t[np << logN];uint64_t* ra2 = new uint64_t[np << logN];uint64_t* rb2 = new uint64_t[np << logN];ring.CRT(ra1, cipher1.ax, np);ring.CRT(rb1, cipher1.bx, np);ring.CRT(ra2, cipher2.ax, np);ring.CRT(rb2, cipher2.bx, np);ZZ* axax = new ZZ[N];ZZ* bxbx = new ZZ[N];ZZ* axbx = new ZZ[N];ring.multDNTT(axax, ra1, ra2, np, q);ring.multDNTT(bxbx, rb1, rb2, np, q);ring.addNTTAndEqual(ra1, rb1, np);ring.addNTTAndEqual(ra2, rb2, np);ring.multDNTT(axbx, ra1, ra2, np, q);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(MULTIPLICATION)) : keyMap.at(MULTIPLICATION);np = ceil((cipher1.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raa = new uint64_t[np << logN];ring.CRT(raa, axax, np);ring.multDNTT(res.ax, raa, key->rax, np, qQ);ring.multDNTT(res.bx, raa, key->rbx, np, qQ);ring.rightShiftAndEqual(res.ax, logQ);ring.rightShiftAndEqual(res.bx, logQ);ring.addAndEqual(res.ax, axbx, q);ring.subAndEqual(res.ax, bxbx, q);ring.subAndEqual(res.ax, axax, q);ring.addAndEqual(res.bx, bxbx, q);delete[] axax;delete[] bxbx;delete[] axbx;delete[] ra1;delete[] ra2;delete[] rb1;delete[] rb2;delete[] raa;
}void Scheme::multAndEqual(Ciphertext& cipher1, Ciphertext& cipher2) {ZZ q = ring.qpows[cipher1.logq];ZZ qQ = ring.qpows[cipher1.logq + logQ];long np = ceil((2 + cipher1.logq + cipher2.logq + logN + 2)/(double)pbnd);uint64_t* ra1 = new uint64_t[np << logN];uint64_t* rb1 = new uint64_t[np << logN];uint64_t* ra2 = new uint64_t[np << logN];uint64_t* rb2 = new uint64_t[np << logN];ring.CRT(ra1, cipher1.ax, np);ring.CRT(rb1, cipher1.bx, np);ring.CRT(ra2, cipher2.ax, np);ring.CRT(rb2, cipher2.bx, np);ZZ* axax = new ZZ[N];ZZ* bxbx = new ZZ[N];ZZ* axbx = new ZZ[N];ring.multDNTT(axax, ra1, ra2, np, q);ring.multDNTT(bxbx, rb1, rb2, np, q);ring.addNTTAndEqual(ra1, rb1, np);ring.addNTTAndEqual(ra2, rb2, np);ring.multDNTT(axbx, ra1, ra2, np, q);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(MULTIPLICATION)) : keyMap.at(MULTIPLICATION);np = ceil((cipher1.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raa = new uint64_t[np << logN];ring.CRT(raa, axax, np);ring.multDNTT(cipher1.ax, raa, key->rax, np, qQ);ring.multDNTT(cipher1.bx, raa, key->rbx, np, qQ);ring.rightShiftAndEqual(cipher1.ax, logQ);ring.rightShiftAndEqual(cipher1.bx, logQ);ring.addAndEqual(cipher1.ax, axbx, q);ring.subAndEqual(cipher1.ax, bxbx, q);ring.subAndEqual(cipher1.ax, axax, q);ring.addAndEqual(cipher1.bx, bxbx, q);delete[] axax;delete[] bxbx;delete[] axbx;delete[] ra1;delete[] ra2;delete[] rb1;delete[] rb2;delete[] raa;cipher1.logp += cipher2.logp;
}//-----------------------------------------void Scheme::square(Ciphertext& res, Ciphertext& cipher) {res.copyParams(cipher);res.logp += cipher.logp;ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];long np = ceil((2 * cipher.logq + logN + 2)/(double)pbnd);uint64_t* ra = new uint64_t[np << logN];uint64_t* rb = new uint64_t[np << logN];ring.CRT(ra, cipher.ax, np);ring.CRT(rb, cipher.bx, np);ZZ* axax = new ZZ[N];ZZ* axbx = new ZZ[N];ZZ* bxbx = new ZZ[N];ring.squareNTT(bxbx, rb, np, q);ring.squareNTT(axax, ra, np, q);ring.multDNTT(axbx, ra, rb, np, q);ring.addAndEqual(axbx, axbx, q);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(MULTIPLICATION)) : keyMap.at(MULTIPLICATION);np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raa = new uint64_t[np << logN];ring.CRT(raa, axax, np);ring.multDNTT(res.ax, raa, key->rax, np, qQ);ring.multDNTT(res.bx, raa, key->rbx, np, qQ);ring.rightShiftAndEqual(res.ax, logQ);ring.rightShiftAndEqual(res.bx, logQ);ring.addAndEqual(res.ax, axbx, q);ring.addAndEqual(res.bx, bxbx, q);delete[] axbx;delete[] axax;delete[] bxbx;delete[] ra;delete[] rb;delete[] raa;
}void Scheme::squareAndEqual(Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];long np = ceil((2 + 2 * cipher.logq + logN + 2)/(double)pbnd);uint64_t* ra = new uint64_t[np << logN];uint64_t* rb = new uint64_t[np << logN];ring.CRT(ra, cipher.ax, np);ring.CRT(rb, cipher.bx, np);ZZ* axax = new ZZ[N];ZZ* axbx = new ZZ[N];ZZ* bxbx = new ZZ[N];ring.squareNTT(bxbx, rb, np, q);ring.squareNTT(axax, ra, np, q);ring.multDNTT(axbx, ra, rb, np, q);ring.addAndEqual(axbx, axbx, q);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(MULTIPLICATION)) : keyMap.at(MULTIPLICATION);np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raa = new uint64_t[np << logN];ring.CRT(raa, axax, np);ring.multDNTT(cipher.ax, raa, key->rax, np, qQ);ring.multDNTT(cipher.bx, raa, key->rbx, np, qQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);ring.addAndEqual(cipher.ax, axbx, q);ring.addAndEqual(cipher.bx, bxbx, q);cipher.logp *= 2;delete[] axbx;delete[] axax;delete[] bxbx;delete[] ra;delete[] rb;delete[] raa;
}//-----------------------------------------void Scheme::multByConst(Ciphertext& res, Ciphertext& cipher, double cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);ring.multByConst(res.ax, cipher.ax, cnstZZ, q);ring.multByConst(res.bx, cipher.bx, cnstZZ, q);res.copyParams(cipher);res.logp += logp;
}void Scheme::multByConst(Ciphertext& res, Ciphertext& cipher, complex<double> cnst, long logp) {res.copy(cipher);multByConstAndEqual(res, cnst, logp);
}void Scheme::multByConstVec(Ciphertext& res, Ciphertext& cipher, complex<double>* cnstVec, long logp) {res.copy(cipher);multByConstVecAndEqual(res, cnstVec, logp);
}void Scheme::multByConstVecAndEqual(Ciphertext& cipher, complex<double>* cnstVec, long logp) {long slots = cipher.n;ZZ* cnstPoly = new ZZ[N];ring.encode(cnstPoly, cnstVec, slots, logp);multByPolyAndEqual(cipher, cnstPoly, logp);delete[] cnstPoly;
}void Scheme::multByConstAndEqual(Ciphertext& cipher, double cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);ring.multByConstAndEqual(cipher.ax, cnstZZ, q);ring.multByConstAndEqual(cipher.bx, cnstZZ, q);cipher.logp += logp;
}void Scheme::multByConstAndEqual(Ciphertext& cipher, RR& cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZ = EvaluatorUtils::scaleUpToZZ(cnst, logp);ring.multByConstAndEqual(cipher.ax, cnstZZ, q);ring.multByConstAndEqual(cipher.bx, cnstZZ, q);cipher.logp += logp;
}void Scheme::multByConstAndEqual(Ciphertext& cipher, complex<double> cnst, long logp) {ZZ q = ring.qpows[cipher.logq];ZZ cnstZZReal = EvaluatorUtils::scaleUpToZZ(cnst.real(), logp);ZZ cnstZZImag = EvaluatorUtils::scaleUpToZZ(cnst.imag(), logp);Ciphertext tmp; // compute imagnary parttmp.copyParams(cipher);ring.multByConst(tmp.ax, cipher.ax, cnstZZImag, q);ring.multByConst(tmp.bx, cipher.bx, cnstZZImag, q);ring.multByMonomialAndEqual(tmp.ax, N / 2);ring.multByMonomialAndEqual(tmp.bx, N / 2);ring.multByConstAndEqual(cipher.ax, cnstZZReal, q);ring.multByConstAndEqual(cipher.bx, cnstZZReal, q);ring.addAndEqual(cipher.ax, tmp.ax, QQ);ring.addAndEqual(cipher.bx, tmp.bx, QQ);cipher.logp += logp;
}void Scheme::multByPoly(Ciphertext& res, Ciphertext& cipher, ZZ* poly, long logp) {ZZ q = ring.qpows[cipher.logq];res.copyParams(cipher);long bnd = ring.maxBits(poly, N);long np = ceil((cipher.logq + bnd + logN + 2)/(double)pbnd);uint64_t* rpoly = new uint64_t[np << logN];ring.CRT(rpoly, poly, np);ring.multNTT(res.ax, cipher.ax, rpoly, np, q);ring.multNTT(res.bx, cipher.bx, rpoly, np, q);delete[] rpoly;res.logp += logp;
}void Scheme::multByPolyAndEqual(Ciphertext& cipher, ZZ* poly, long logp) {ZZ q = ring.qpows[cipher.logq];long bnd = ring.maxBits(poly, N);long np = ceil((cipher.logq + bnd + logN + 2)/(double)pbnd);uint64_t* rpoly = new uint64_t[np << logN];ring.CRT(rpoly, poly, np);ring.multNTTAndEqual(cipher.ax, rpoly, np, q);ring.multNTTAndEqual(cipher.bx, rpoly, np, q);delete[] rpoly;cipher.logp += logp;
}void Scheme::multByPolyNTT(Ciphertext& res, Ciphertext& cipher, uint64_t* rpoly, long bnd, long logp) {ZZ q = ring.qpows[cipher.logq];res.copyParams(cipher);long np = ceil((cipher.logq + bnd + logN + 2)/(double)pbnd);ring.multNTT(res.ax, cipher.ax, rpoly, np, q);ring.multNTT(res.bx, cipher.bx, rpoly, np, q);res.logp += logp;
}void Scheme::multByPolyNTTAndEqual(Ciphertext& cipher, uint64_t* rpoly, long bnd, long logp) {ZZ q = ring.qpows[cipher.logq];long np = ceil((cipher.logq + bnd + logN + 2)/(double)pbnd);ring.multNTTAndEqual(cipher.ax, rpoly, np, q);ring.multNTTAndEqual(cipher.bx, rpoly, np, q);cipher.logp += logp;
}//-----------------------------------------void Scheme::multByMonomial(Ciphertext& res, Ciphertext& cipher, const long degree) {res.copyParams(cipher);ring.multByMonomial(res.ax, cipher.ax, degree);ring.multByMonomial(res.bx, cipher.bx, degree);
}void Scheme::multByMonomialAndEqual(Ciphertext& cipher, const long degree) {ring.multByMonomialAndEqual(cipher.ax, degree);ring.multByMonomialAndEqual(cipher.bx, degree);
}//-----------------------------------------void Scheme::leftShift(Ciphertext& res, Ciphertext& cipher, long bits) {ZZ q = ring.qpows[cipher.logq];res.copyParams(cipher);ring.leftShift(res.ax, cipher.ax, bits, q);ring.leftShift(res.bx, cipher.bx, bits, q);
}void Scheme::leftShiftAndEqual(Ciphertext& cipher, long bits) {ZZ q = ring.qpows[cipher.logq];ring.leftShiftAndEqual(cipher.ax, bits, q);ring.leftShiftAndEqual(cipher.bx, bits, q);
}void Scheme::doubleAndEqual(Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];ring.doubleAndEqual(cipher.ax, q);ring.doubleAndEqual(cipher.bx, q);
}void Scheme::divByPo2(Ciphertext& res, Ciphertext& cipher, long bits) {res.copyParams(cipher);ring.rightShift(res.ax, cipher.ax, bits);ring.rightShift(res.bx, cipher.bx, bits);res.logq -= bits;
}void Scheme::divByPo2AndEqual(Ciphertext& cipher, long bits) {ring.rightShiftAndEqual(cipher.ax, bits);ring.rightShiftAndEqual(cipher.bx, bits);cipher.logq -= bits;
}//-----------------------------------------void Scheme::reScaleBy(Ciphertext& res, Ciphertext& cipher, long dlogq) {res.copyParams(cipher);ring.rightShift(res.ax, cipher.ax, dlogq);ring.rightShift(res.bx, cipher.bx, dlogq);res.logp -= dlogq;res.logq -= dlogq;
}void Scheme::reScaleTo(Ciphertext& res, Ciphertext& cipher, long logq) {long dlogq = cipher.logq - logq;res.copyParams(cipher);ring.rightShift(res.ax, cipher.ax, dlogq);ring.rightShift(res.bx, cipher.bx, dlogq);res.logp -= dlogq;
}void Scheme::reScaleByAndEqual(Ciphertext& cipher, long dlogq) {ring.rightShiftAndEqual(cipher.ax, dlogq);ring.rightShiftAndEqual(cipher.bx, dlogq);cipher.logq -= dlogq;cipher.logp -= dlogq;
}void Scheme::reScaleToAndEqual(Ciphertext& cipher, long logq) {long dlogq = cipher.logq - logq;ring.rightShiftAndEqual(cipher.ax, dlogq);ring.rightShiftAndEqual(cipher.bx, dlogq);cipher.logq = logq;cipher.logp -= dlogq;
}void Scheme::modDownBy(Ciphertext& res, Ciphertext& cipher, long dlogq) {ZZ q = ring.qpows[cipher.logq - dlogq];res.copyParams(cipher);ring.mod(res.ax, cipher.ax, q);ring.mod(res.bx, cipher.bx, q);res.logq -= dlogq;
}void Scheme::modDownByAndEqual(Ciphertext& cipher, long dlogq) {ZZ q = ring.qpows[cipher.logq - dlogq];ring.modAndEqual(cipher.ax, q);ring.modAndEqual(cipher.bx, q);cipher.logq -= dlogq;
}void Scheme::modDownTo(Ciphertext& res, Ciphertext& cipher, long logq) {ZZ q = ring.qpows[logq];res.copyParams(cipher);ring.mod(res.ax, cipher.ax, q);ring.mod(res.bx, cipher.bx, q);res.logq = logq;
}void Scheme::modDownToAndEqual(Ciphertext& cipher, long logq) {ZZ q = ring.qpows[logq];cipher.logq = logq;ring.modAndEqual(cipher.ax, q);ring.modAndEqual(cipher.bx, q);
}//----------------------------------------------------------------------------------
//   ROTATIONS & CONJUGATIONS
//----------------------------------------------------------------------------------void Scheme::leftRotateFast(Ciphertext& res, Ciphertext& cipher, long r) {ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];ZZ* bxrot = new ZZ[N];ZZ* axrot = new ZZ[N];ring.leftRotate(bxrot, cipher.bx, r);ring.leftRotate(axrot, cipher.ax, r);Key* key = isSerialized ? SerializationUtils::readKey(serLeftRotKeyMap.at(r)) : leftRotKeyMap.at(r);res.copyParams(cipher);long np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* rarot = new uint64_t[np << logN];ring.CRT(rarot, axrot, np);ring.multDNTT(res.ax, rarot, key->rax, np, qQ);ring.multDNTT(res.bx, rarot, key->rbx, np, qQ);ring.rightShiftAndEqual(res.ax, logQ);ring.rightShiftAndEqual(res.bx, logQ);ring.addAndEqual(res.bx, bxrot, q);delete[] bxrot;delete[] axrot;delete[] rarot;
}void Scheme::leftRotateFastAndEqual(Ciphertext& cipher, long r) {ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];ZZ* bxrot = new ZZ[N];ZZ* axrot = new ZZ[N];ring.leftRotate(bxrot, cipher.bx, r);ring.leftRotate(axrot, cipher.ax, r);Key* key = isSerialized ? SerializationUtils::readKey(serLeftRotKeyMap.at(r)) : leftRotKeyMap.at(r);long np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* rarot = new uint64_t[np << logN];ring.CRT(rarot, axrot, np);ring.multDNTT(cipher.ax, rarot, key->rax, np, qQ);ring.multDNTT(cipher.bx, rarot, key->rbx, np, qQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);ring.addAndEqual(cipher.bx, bxrot, q);delete[] bxrot;delete[] axrot;delete[] rarot;
}void Scheme::rightRotateFast(Ciphertext& res, Ciphertext& cipher, long r) {long rr = Nh - r;leftRotateFast(res, cipher, rr);
}void Scheme::rightRotateFastAndEqual(Ciphertext& cipher, long r) {long rr = Nh - r;leftRotateFastAndEqual(cipher, rr);
}void Scheme::conjugate(Ciphertext& res, Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];ZZ* bxconj = new ZZ[N];ZZ* axconj = new ZZ[N];ring.conjugate(bxconj, cipher.bx);ring.conjugate(axconj, cipher.ax);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(CONJUGATION)) : keyMap.at(CONJUGATION);res.copyParams(cipher);long np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raconj = new uint64_t[np << logN];ring.CRT(raconj, axconj, np);ring.multDNTT(res.ax, raconj, key->rax, np, qQ);ring.multDNTT(res.bx, raconj, key->rbx, np, qQ);ring.rightShiftAndEqual(res.ax, logQ);ring.rightShiftAndEqual(res.bx, logQ);ring.addAndEqual(res.bx, bxconj, q);delete[] bxconj;delete[] axconj;delete[] raconj;
}void Scheme::conjugateAndEqual(Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];ZZ qQ = ring.qpows[cipher.logq + logQ];ZZ* bxconj = new ZZ[N];ZZ* axconj = new ZZ[N];ring.conjugate(bxconj, cipher.bx);ring.conjugate(axconj, cipher.ax);Key* key = isSerialized ? SerializationUtils::readKey(serKeyMap.at(CONJUGATION)) : keyMap.at(CONJUGATION);long np = ceil((cipher.logq + logQQ + logN + 2)/(double)pbnd);uint64_t* raconj = new uint64_t[np << logN];ring.CRT(raconj, axconj, np);ring.multDNTT(cipher.ax, raconj, key->rax, np, qQ);ring.multDNTT(cipher.bx, raconj, key->rbx, np, qQ);ring.rightShiftAndEqual(cipher.ax, logQ);ring.rightShiftAndEqual(cipher.bx, logQ);ring.addAndEqual(cipher.bx, bxconj, q);delete[] bxconj;delete[] axconj;delete[] raconj;
}//----------------------------------------------------------------------------------
//   BOOTSTRAPPING
//----------------------------------------------------------------------------------void Scheme::normalizeAndEqual(Ciphertext& cipher) {ZZ q = ring.qpows[cipher.logq];for (long i = 0; i < N; ++i) {if(NumBits(cipher.ax[i]) == cipher.logq) cipher.ax[i] -= q;if(NumBits(cipher.bx[i]) == cipher.logq) cipher.bx[i] -= q;}
}void Scheme::coeffToSlotAndEqual(Ciphertext& cipher) {long slots = cipher.n;long logSlots = log2(slots);long logk = logSlots / 2;long k = 1 << logk;Ciphertext* rotvec = new Ciphertext[k];rotvec[0].copy(cipher);NTL_EXEC_RANGE(k - 1, first, last);for (long j = first; j < last; ++j) {leftRotateFast(rotvec[j+1], rotvec[0], j + 1);}NTL_EXEC_RANGE_END;BootContext* bootContext = ring.bootContextMap.at(logSlots);Ciphertext* tmpvec = new Ciphertext[k];NTL_EXEC_RANGE(k, first, last);for (long j = first; j < last; ++j) {multByPolyNTT(tmpvec[j], rotvec[j], bootContext->rpvec[j], bootContext->bndvec[j], bootContext->logp);}NTL_EXEC_RANGE_END;for (long j = 1; j < k; ++j) {addAndEqual(tmpvec[0], tmpvec[j]);}cipher.copy(tmpvec[0]);for (long ki = k; ki < slots; ki += k) {NTL_EXEC_RANGE(k, first, last);for (long j = first; j < last; ++j) {multByPolyNTT(tmpvec[j], rotvec[j], bootContext->rpvec[j + ki], bootContext->bndvec[j + ki], bootContext->logp);}NTL_EXEC_RANGE_END;for (long j = 1; j < k; ++j) {addAndEqual(tmpvec[0], tmpvec[j]);}leftRotateFastAndEqual(tmpvec[0], ki);addAndEqual(cipher, tmpvec[0]);}reScaleByAndEqual(cipher, bootContext->logp);delete[] rotvec;delete[] tmpvec;
}void Scheme::slotToCoeffAndEqual(Ciphertext& cipher) {long slots = cipher.n;long logSlots = log2(slots);long logk = logSlots / 2;long k = 1 << logk;Ciphertext* rotvec = new Ciphertext[k];rotvec[0].copy(cipher);NTL_EXEC_RANGE(k-1, first, last);for (long j = first; j < last; ++j) {leftRotateFast(rotvec[j + 1], rotvec[0], j + 1);}NTL_EXEC_RANGE_END;BootContext* bootContext = ring.bootContextMap.at(logSlots);Ciphertext* tmpvec = new Ciphertext[k];NTL_EXEC_RANGE(k, first, last);for (long j = first; j < last; ++j) {multByPolyNTT(tmpvec[j], rotvec[j], bootContext->rpvecInv[j], bootContext->bndvecInv[j], bootContext->logp);}NTL_EXEC_RANGE_END;for (long j = 1; j < k; ++j) {addAndEqual(tmpvec[0], tmpvec[j]);}cipher.copy(tmpvec[0]);for (long ki = k; ki < slots; ki+=k) {NTL_EXEC_RANGE(k, first, last);for (long j = first; j < last; ++j) {multByPolyNTT(tmpvec[j], rotvec[j], bootContext->rpvecInv[j + ki], bootContext->bndvecInv[j + ki], bootContext->logp);}NTL_EXEC_RANGE_END;for (long j = 1; j < k; ++j) {addAndEqual(tmpvec[0], tmpvec[j]);}leftRotateFastAndEqual(tmpvec[0], ki);addAndEqual(cipher, tmpvec[0]);}reScaleByAndEqual(cipher, bootContext->logp);delete[] rotvec;delete[] tmpvec;
}void Scheme::exp2piAndEqual(Ciphertext& cipher, long logp) {Ciphertext cipher2;square(cipher2, cipher);reScaleByAndEqual(cipher2, logp); // cipher2.logq : logq - logpCiphertext cipher4;square(cipher4, cipher2);reScaleByAndEqual(cipher4, logp); // cipher4.logq : logq -2logpRR c = 1/(2*Pi);Ciphertext cipher01;addConst(cipher01, cipher, c, logp); // cipher01.logq : logqc = 2*Pi;multByConstAndEqual(cipher01, c, logp);reScaleByAndEqual(cipher01, logp); // cipher01.logq : logq - logpc = 3/(2*Pi);Ciphertext cipher23;addConst(cipher23, cipher, c, logp); // cipher23.logq : logqc = 4*Pi*Pi*Pi/3;multByConstAndEqual(cipher23, c, logp);reScaleByAndEqual(cipher23, logp); // cipher23.logq : logq - logpmultAndEqual(cipher23, cipher2);reScaleByAndEqual(cipher23, logp); // cipher23.logq : logq - 2logpaddAndEqual(cipher23, cipher01); // cipher23.logq : logq - 2logpc = 5/(2*Pi);Ciphertext cipher45;addConst(cipher45, cipher, c, logp); // cipher45.logq : logqc = 4*Pi*Pi*Pi*Pi*Pi/15;multByConstAndEqual(cipher45, c, logp);reScaleByAndEqual(cipher45, logp); // cipher45.logq : logq - logpc = 7/(2*Pi);addConstAndEqual(cipher, c, logp); // cipher.logq : logqc = 8*Pi*Pi*Pi*Pi*Pi*Pi*Pi/315;multByConstAndEqual(cipher, c, logp);reScaleByAndEqual(cipher, logp); // cipher.logq : logq - logpmultAndEqual(cipher, cipher2);reScaleByAndEqual(cipher, logp); // cipher.logq : logq - 2logpmodDownByAndEqual(cipher45, logp); // cipher45.logq : logq - 2logpaddAndEqual(cipher, cipher45); // cipher.logq : logq - 2logpmultAndEqual(cipher, cipher4);reScaleByAndEqual(cipher, logp); // cipher.logq : logq - 3logpmodDownByAndEqual(cipher23, logp);addAndEqual(cipher, cipher23); // cipher.logq : logq - 3logp
}void Scheme::evalExpAndEqual(Ciphertext& cipher, long logT, long logI) {long slots = cipher.n;long logSlots = log2(slots);BootContext* bootContext = ring.bootContextMap.at(logSlots);if(logSlots < logNh) {Ciphertext tmp;conjugate(tmp, cipher);subAndEqual(cipher, tmp);divByPo2AndEqual(cipher, logT + 1); // bitDown: logT + 1exp2piAndEqual(cipher, bootContext->logp); // bitDown: logT + 1 + 3(logq + logI)for (long i = 0; i < logI + logT; ++i) {squareAndEqual(cipher);reScaleByAndEqual(cipher, bootContext->logp);}conjugate(tmp, cipher);subAndEqual(cipher, tmp);multByPolyNTT(tmp, cipher, bootContext->rp1, bootContext->bnd1, bootContext->logp);Ciphertext tmprot;leftRotateFast(tmprot, tmp, slots);addAndEqual(tmp, tmprot);multByPolyNTTAndEqual(cipher, bootContext->rp2, bootContext->bnd2, bootContext->logp);leftRotateFast(tmprot, cipher, slots);addAndEqual(cipher, tmprot);addAndEqual(cipher, tmp);} else {Ciphertext tmp;conjugate(tmp, cipher);Ciphertext c2;sub(c2, cipher, tmp);addAndEqual(cipher, tmp);imultAndEqual(cipher);divByPo2AndEqual(cipher, logT + 1); // cipher bitDown: logT + 1reScaleByAndEqual(c2, logT + 1); // c2 bitDown: logT + 1exp2piAndEqual(cipher, bootContext->logp); // cipher bitDown: logT + 1 + 3(logq + logI)exp2piAndEqual(c2, bootContext->logp); // c2 bitDown: logT + 1 + 3(logq + logI)for (long i = 0; i < logI + logT; ++i) {squareAndEqual(c2);squareAndEqual(cipher);reScaleByAndEqual(c2, bootContext->logp);reScaleByAndEqual(cipher, bootContext->logp);}conjugate(tmp, c2);subAndEqual(c2, tmp);conjugate(tmp, cipher);subAndEqual(cipher, tmp);imultAndEqual(cipher);subAndEqual2(c2, cipher);RR c = 0.25/Pi;multByConstAndEqual(cipher, c, bootContext->logp);}reScaleByAndEqual(cipher, bootContext->logp + logI);
}void Scheme::bootstrapAndEqual(Ciphertext& cipher, long logq, long logQ, long logT, long logI) {long logSlots = log2(cipher.n);long logp = cipher.logp;modDownToAndEqual(cipher, logq);normalizeAndEqual(cipher);cipher.logq = logQ;cipher.logp = logq + 4;Ciphertext rot;for (long i = logSlots; i < logNh; ++i) {leftRotateFast(rot, cipher, (1 << i));addAndEqual(cipher, rot);}divByPo2AndEqual(cipher, logNh); // bitDown: context.logNh - logSlotscoeffToSlotAndEqual(cipher);evalExpAndEqual(cipher, logT, logI); // bitDown: context.logNh + (logI + logT + 5) * logq + (logI + logT + 6) * logI + logT + 1slotToCoeffAndEqual(cipher);cipher.logp = logp;
}}  // namespace heaan

SchemeAlgo.h

#ifndef HEAAN_SCHEMEALGO_H_
#define HEAAN_SCHEMEALGO_H_#include <NTL/BasicThreadPool.h>
#include <NTL/ZZ.h>
#include <string>#include "EvaluatorUtils.h"
#include "Plaintext.h"
#include "SecretKey.h"
#include "Ciphertext.h"
#include "Scheme.h"namespace heaan {static std::string LOGARITHM = "Logarithm"; ///< log(x)
static std::string EXPONENT  = "Exponent"; ///< exp(x)
static std::string SIGMOID   = "Sigmoid"; ///< sigmoid(x) = exp(x) / (1 + exp(x))class SchemeAlgo {public:Scheme& scheme;std::map<std::string, double*> taylorCoeffsMap;SchemeAlgo(Scheme& scheme) : scheme(scheme) {taylorCoeffsMap.insert(std::pair<std::string, double*>(LOGARITHM,new double[11] {0,1,-0.5,1./3,-1./4,1./5,-1./6,1./7,-1./8,1./9,-1./10}));taylorCoeffsMap.insert(std::pair<std::string, double*>(EXPONENT,new double[11] {1,1,0.5,1./6,1./24,1./120,1./720,1./5040,1./40320,1./362880,1./3628800 }));taylorCoeffsMap.insert(std::pair<std::string, double*>(SIGMOID,new double[11] {1./2,1./4,0,-1./48,0,1./480,0,-17./80640,0,31./1451520,0}));};void powerOf2(Ciphertext& res, Ciphertext& cipher, long precisionBits, long logDegree);void powerOf2Extended(Ciphertext* res, Ciphertext& cipher, long logp, long logDegree);void power(Ciphertext& res, Ciphertext& cipher, long logp, long degree);void powerExtended(Ciphertext* res, Ciphertext& cipher, long logp, long degree);void inverse(Ciphertext& res, Ciphertext& cipher, long logp, long steps);void function(Ciphertext& res, Ciphertext& cipher, std::string& funcName, long logp, long degree);void functionLazy(Ciphertext& res, Ciphertext& cipher, std::string& funcName, long logp, long degree);};}  // namespace heaan#endif

SchemeAlgo.cpp

#include "SchemeAlgo.h"using namespace std;
using namespace NTL;namespace heaan {void SchemeAlgo::powerOf2(Ciphertext& res, Ciphertext& cipher, long logp, long logDegree) {res.copy(cipher);for (long i = 0; i < logDegree; ++i) {scheme.squareAndEqual(res);scheme.reScaleByAndEqual(res, logp);}
}void SchemeAlgo::powerOf2Extended(Ciphertext* res, Ciphertext& cipher, long logp, long logDegree) {res[0].copy(cipher);for (long i = 1; i < logDegree + 1; ++i) {scheme.square(res[i], res[i-1]);scheme.reScaleByAndEqual(res[i], logp);}
}//-----------------------------------------void SchemeAlgo::power(Ciphertext& res, Ciphertext& cipher, long logp, long degree) {long logDegree = log2((double)degree);long po2Degree = 1 << logDegree;powerOf2(res, cipher, logp, logDegree);long remDegree = degree - po2Degree;Ciphertext tmp;if(remDegree > 0) {power(tmp, cipher, logp, remDegree);long bitsDown = tmp.logq - res.logq;scheme.modDownByAndEqual(tmp, bitsDown);scheme.multAndEqual(res, tmp);scheme.reScaleByAndEqual(res, logp);}
}void SchemeAlgo::powerExtended(Ciphertext* res, Ciphertext& cipher, long logp, long degree) {long logDegree = log2((double)degree);Ciphertext* cpows = new Ciphertext[logDegree + 1];powerOf2Extended(cpows, cipher, logp, logDegree);long idx = 0;for (long i = 0; i < logDegree; ++i) {long powi = (1 << i);res[idx++].copy(cpows[i]);for (int j = 0; j < powi-1; ++j) {long bitsDown = res[j].logq - cpows[i].logq;scheme.modDownBy(res[idx], res[j], bitsDown);scheme.multAndEqual(res[idx], cpows[i]);scheme.reScaleByAndEqual(res[idx++], logp);}}res[idx++].copy(cpows[logDegree]);long degree2 = (1 << logDegree);for (int i = 0; i < (degree - degree2); ++i) {long bitsDown = res[i].logq - cpows[logDegree].logq;scheme.modDownBy(res[idx], res[i], bitsDown);scheme.multAndEqual(res[idx], cpows[logDegree]);scheme.reScaleByAndEqual(res[idx++], logp);}delete[] cpows;
}void SchemeAlgo::inverse(Ciphertext& res, Ciphertext& cipher, long logp, long steps) {Ciphertext cbar;Ciphertext cpow;Ciphertext tmp;scheme.negate(cbar, cipher);scheme.addConstAndEqual(cbar, 1.0, logp);cpow.copy(cbar);scheme.addConst(tmp, cbar, 1.0, logp);scheme.modDownByAndEqual(tmp, logp);res.copy(tmp);for (long i = 1; i < steps; ++i) {scheme.squareAndEqual(cpow);scheme.reScaleByAndEqual(cpow, logp);tmp.copy(cpow);scheme.addConstAndEqual(tmp, 1.0, logp);scheme.multAndEqual(tmp, res);scheme.reScaleByAndEqual(tmp, logp);res.copy(tmp);}
}//-----------------------------------------void SchemeAlgo::function(Ciphertext& res, Ciphertext& cipher, string& funcName, long logp, long degree) {Ciphertext* cpows = new Ciphertext[degree];powerExtended(cpows, cipher, logp, degree);long dlogp = 2 * logp;double* coeffs = taylorCoeffsMap.at(funcName);scheme.multByConst(res, cpows[0], coeffs[1], logp);scheme.addConstAndEqual(res, coeffs[0], dlogp);Ciphertext aixi;for (int i = 1; i < degree; ++i) {if(abs(coeffs[i + 1]) > 1e-27) {scheme.multByConst(aixi, cpows[i], coeffs[i + 1], logp);scheme.modDownToAndEqual(res, aixi.logq);scheme.addAndEqual(res, aixi);}}scheme.reScaleByAndEqual(res, logp);delete[] cpows;
}void SchemeAlgo::functionLazy(Ciphertext& res, Ciphertext& cipher, string& funcName, long logp, long degree) {Ciphertext* cpows = new Ciphertext[degree];powerExtended(cpows, cipher, logp, degree);long dlogp = 2 * logp;double* coeffs = taylorCoeffsMap.at(funcName);scheme.multByConst(res, cpows[0], coeffs[1], logp);scheme.addConstAndEqual(res, coeffs[0], dlogp);Ciphertext aixi;for (int i = 1; i < degree; ++i) {if(abs(coeffs[i + 1]) > 1e-27) {scheme.multByConst(aixi, cpows[i], coeffs[i + 1], logp);long bitsDown = res.logq - aixi.logq;scheme.modDownByAndEqual(res, bitsDown);scheme.addAndEqual(res, aixi);}}delete[] cpows;
}}  // namespace heaan

HEAAN源码(二)相关推荐

  1. 阅读react-redux源码(二) - createConnect、match函数的实现

    阅读react-redux源码 - 零 阅读react-redux源码 - 一 阅读react-redux源码(二) - createConnect.match函数的实现 上一节看了Provider组 ...

  2. 抖音seo源码 短视频seo源码二次开发,怎么使用抖音seo源码,视频seo源码私有化部署?

    抖音seo源码 短视频seo源码二次开发,怎么使用抖音seo源码,短视频seo源码私有化部署? 抖音seo源码 短视频seo源码二次开发,怎么使用抖音seo源码,短视频seo源码私有化部署到本地.首先 ...

  3. 拉拉米抢单发单系统源码+二开ui带视频介绍+ 放量功能

    拉拉米抢单发单系统源码+二开ui带视频介绍+ 放量功能 安装搭建说明 服务器系统:Linux+宝塔 亲测环境:Nginx1.16.1+PHP5.6+Mysql5.5 修改数据库配置文件:/config ...

  4. 抖音seo源码二次开发,短视频seo源码二次开发

    抖音seo源码二次开发,短视频seo源码二次开发 开发逻辑及部分代码展示 抖音seo系统前端采用vue 与React技术语言,后端采用jave后台技术语言. 抖音seo是什么技术逻辑呢?seo是搜索引 ...

  5. Unity UGUI图文混排源码(二)

    Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...

  6. 【共享农场】智慧农业小程序,定制开发与开元源码二次开发那个更合适呢?

    如果要谈定制开发和拥有源码二次开发哪个更合适的话,首先得搞清智慧农业小程序这两个有什么区别呢?如果你要完全定制开发一套小程序费用基本上是在5-8W.而且时间比较长.很多人就算愿意承担资金成本,也不愿意 ...

  7. 站长导航系统源码 二开优化 美观自动审核 自动获取网站信息

    介绍: 站长导航系统源码 二开优化 美观自动审核 自动获取网站信息 网盘下载地址: http://www.bytepan.net/7KOqz7bmN33 图片:

  8. spring cloud alibaba中台架构源码二次开发+系统集成、集中式应用权限管理

    基于Spring Cloud Alibaba 分布式微服务高并发数据平台化(中台)思想+多租户saas设计的企业开发架构,支持源码二次开发.支持其他业务系统集成.集中式应用权限管理.支持拓展其他任意子 ...

  9. 丁威: 优秀程序员必备技能之如何高效阅读源码(二更)

    @[toc](丁威: 优秀程序员必备技能之如何高效阅读源码(二更)) 消息中间件 我能熟练使用这个框架/软件/技术就行了, 为什么要看源码?" "平时不用看源码, 看源码太费时间, ...

最新文章

  1. AI、区块链和机器人:技术会让未来的工作发生什变化?
  2. 转贴:[转]所有 OLE api 和接口的目的
  3. h3c GR5200路由器上如何设置公网ip可以访问
  4. centos7.2安装mysql5.7_Centos7.2下使用YUM快速安装MySQL5.7的方法
  5. 如何在SAP UI5应用里添加使用摄像头拍照的功能
  6. Windows phone7 开发-Zune software is not launched 【转】
  7. VM虚拟机不能上网的问题解决
  8. 第一章 计算机系统概述 1.2.1 计算机硬件的基本组成 [计算机组成原理笔记]
  9. java中运算符的优先级
  10. pdf编辑 开源_新闻编辑室看到了开源的光芒
  11. Pandas set_indexreset_index
  12. href=“javascript:void(0);”和href=void(change_code(this));
  13. 火山PC_数据库知识_MySQL操作
  14. de4dot构建过程
  15. Linux 的shell脚本的分享,运用了多个不同的方法,实现使用脚本批量巡检服务器,非常有借鉴作用...
  16. python爬取苏宁易购--jsonpath方法
  17. DINO 自监督算法简介
  18. 基于Java的qq截图工具(毕业设计含源码)
  19. 2022款联想拯救者R7000P和联想小新Pro16 选哪个好
  20. 为什么你得不到 90 度的温暖

热门文章

  1. git 国外镜像下载慢的解决方案
  2. 是德科技34461a万用表
  3. Matplotlib使用Latex中文
  4. 8421码5421码2421码余3码
  5. python彩色蟒蛇绘制方向_python绘制蟒蛇,绘制五彩蟒蛇
  6. 淘宝API_item_cat_get - 获得淘宝商品类目
  7. 除了迅雷还有什么靠谱的下载软件
  8. python读取短信验证码_我用Python给你发了个短信验证码,你也来试试
  9. fn映射 mac 键盘_如何在Mac OS X下修改Fn键的属性?
  10. React给antd中TreeSelect组件左侧加自定义图标icon