├── Database.cpp ├── Database.h ├── HELR.cpp ├── HELR.h ├── LICENSE ├── LRtest.cpp ├── LRtest.h ├── Makefile ├── README.md ├── Test.cpp ├── Test_HELR.cpp ├── Test_LR.cpp ├── data ├── edin.txt ├── lbw.txt ├── nhanes3.txt ├── pcs.txt └── uis.txt ├── foo ├── libHELR.a └── src ├── CZZ.cpp ├── CZZ.h ├── CZZ.o ├── CZZX.cpp ├── CZZX.h ├── CZZX.o ├── Cipher.cpp ├── Cipher.h ├── Cipher.o ├── EvaluatorUtils.cpp ├── EvaluatorUtils.h ├── EvaluatorUtils.o ├── HEAAN.cpp ├── HEAAN.o ├── Makefile ├── Message.cpp ├── Message.h ├── Message.o ├── NumUtils.cpp ├── NumUtils.h ├── NumUtils.o ├── Params.cpp ├── Params.h ├── Params.o ├── PubKey.cpp ├── PubKey.h ├── PubKey.o ├── README.md ├── Ring2Utils.cpp ├── Ring2Utils.h ├── Ring2Utils.o ├── Scheme.cpp ├── Scheme.h ├── Scheme.o ├── SchemeAlgo.cpp ├── SchemeAlgo.h ├── SchemeAlgo.o ├── SchemeAux.cpp ├── SchemeAux.h ├── SchemeAux.o ├── SecKey.cpp ├── SecKey.h ├── SecKey.o ├── StringUtils.cpp ├── StringUtils.h ├── StringUtils.o ├── TestScheme.cpp ├── TestScheme.h ├── TestScheme.o ├── TimeUtils.cpp ├── TimeUtils.h └── TimeUtils.o /Database.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "math.h" 10 | 11 | #include "time.h" 12 | #include "Database.h" 13 | 14 | using namespace std; 15 | 16 | 17 | //--------------------------------------------------------------------- 18 | int readData(dMat& Z, char* filename){ 19 | string str(filename); 20 | // ifstream infile("data/edin.txt"); 21 | ifstream infile(str); 22 | string line; 23 | char split_char = '\t'; 24 | int dim1; 25 | 26 | if(getline(infile, line)){ 27 | istringstream split(line); 28 | vector tokens; 29 | for (string each; getline(split, each, split_char); tokens.push_back(each)); 30 | dim1 = tokens.size(); 31 | 32 | vector Z0; 33 | Z0.push_back(stod(tokens[dim1 - 1]) * 2 - 1); 34 | if(Z0[0] != 1 && Z0[0] != -1){ cout << "Error: Y[0] is non-binary" << endl; } 35 | for(int i = 0; i < dim1 - 1; ++i) Z0.push_back(stod(tokens[i]) * Z0[0]); 36 | Z.push_back(Z0); 37 | } 38 | else{ cout << "Error: file reading error" << endl; } 39 | 40 | while(getline(infile, line)){ 41 | istringstream split(line); 42 | vector tokens; 43 | for (string each; getline(split, each, split_char); tokens.push_back(each)); 44 | if(tokens.size() != dim1){ cout << "Error: database dimension" << endl; } 45 | vector Zi; 46 | Zi.push_back(stod(tokens[dim1 - 1]) * 2 - 1); 47 | if(Zi[0] != 1 && Zi[0] != -1){ cout << "Error: Y[i] is non-binary" << endl; } 48 | for(int i = 0; i < dim1 - 1; ++i) Zi.push_back(stod(tokens[i]) * Zi[0]); 49 | Z.push_back(Zi); 50 | } 51 | 52 | int nLine = Z.size(); 53 | 54 | double XjMax, XjMean; 55 | 56 | for(int j = 1; j < dim1; j++){ 57 | XjMax = 0.0; 58 | for(int i = 0; i < nLine; ++i){ 59 | if(XjMax < fabs(Z[i][j])) XjMax = fabs(Z[i][j]); 60 | } 61 | if(XjMax > 1){ 62 | XjMean = 0.0; 63 | for(int i = 0; i < nLine; ++i) XjMean += fabs(Z[i][j]); 64 | XjMean /= nLine; 65 | for(int i = 0; i < nLine; ++i) Z[i][j] /= XjMean; 66 | } 67 | } 68 | return nLine; 69 | } 70 | 71 | //--------------------------------------------------------------------- 72 | 73 | void SamplingData(dMat& Ztrain, dMat& Ztest, dMat& Z){ 74 | int n_train = 1 << ((int) log2(Z.size() * 0.91)); 75 | for(int k = 0; k < n_train; ++k) Ztrain.push_back(Z[k]); 76 | for(int k = 0; k < Z.size() - n_train; ++k) Ztest.push_back(Z[k]); 77 | } 78 | 79 | 80 | void RandomSamplingData(dMat& Ztrain, dMat& Ztest, dMat& Z){ 81 | int n_train = 1 << ((int) log2(Z.size() * 0.91)); 82 | vector randBit(Z.size(), false); 83 | srand(time(NULL)); 84 | 85 | int k = 0; 86 | while(k < n_train){ 87 | int i = rand() % Z.size(); 88 | if(randBit[i] == false){ 89 | randBit[i] = true; 90 | Ztrain.push_back(Z[i]); 91 | k++; 92 | } 93 | } 94 | 95 | for(int i = 0; i < Z.size(); ++i){ 96 | if(randBit[i] == false){ Ztest.push_back(Z[i]); } 97 | } 98 | } 99 | 100 | 101 | //--------------------------------------------------------------------- 102 | 103 | void cvRandomSamplingData(dMat*& Ztrain, dMat*& Ztest, dMat& Z, char* filename){ 104 | 105 | int n_train; 106 | int n_test[5]; 107 | 108 | string str(filename); 109 | 110 | if(str == "data/edin.txt"){ 111 | n_train = 1024; 112 | n_test[0]= 250; 113 | n_test[1]= 250; 114 | n_test[2]= 251; 115 | n_test[3]= 251; 116 | n_test[4]= 251; 117 | } 118 | else if(str == "data/lbw.txt"){ 119 | n_train = 256; 120 | n_test[0]= 37; 121 | n_test[1]= 38; 122 | n_test[2]= 38; 123 | n_test[3]= 38; 124 | n_test[4]= 38; 125 | } 126 | else if(str == "data/nhanes3.txt"){ 127 | n_train = 16384; 128 | n_test[0]= 3129; 129 | n_test[1]= 3130; 130 | n_test[2]= 3130; 131 | n_test[3]= 3130; 132 | n_test[4]= 3130; 133 | } 134 | else if(str == "data/pcs.txt"){ 135 | n_train = 512; 136 | n_test[0]= 75; 137 | n_test[1]= 76; 138 | n_test[2]= 76; 139 | n_test[3]= 76; 140 | n_test[4]= 76; 141 | } 142 | else if(str == "data/uis.txt"){ 143 | n_train = 512; 144 | n_test[0]= 115; 145 | n_test[1]= 115; 146 | n_test[2]= 115; 147 | n_test[3]= 115; 148 | n_test[4]= 115; 149 | } 150 | 151 | 152 | 153 | 154 | // Z0: zero vector of dimension "d" 155 | vector Z0; 156 | for(int l = 0; l < Z[0].size(); ++l){ 157 | Z0.push_back(0); 158 | } 159 | 160 | vector randBit(Z.size(), false); 161 | srand(time(NULL)); 162 | 163 | //-------------------------------------------------- 164 | //! Generate the testing dataset 165 | int k; 166 | ofstream fout; 167 | fout.open("test_data.txt"); 168 | 169 | 170 | for(int l = 0; l < 4; ++l){ 171 | k = 0; 172 | 173 | while(k < n_test[l]){ 174 | int i = rand() % Z.size(); 175 | if(randBit[i] == false){ 176 | randBit[i] = true; 177 | Ztest[l].push_back(Z[i]); 178 | for(int l = 0; l < Z[i].size(); ++l){ 179 | fout << Z[i][l]<< ","; 180 | } 181 | fout << endl; 182 | 183 | k++; 184 | } 185 | } 186 | //fout << "----------------------------------------------" << endl; 187 | } 188 | 189 | 190 | 191 | for(int i = 0; i < Z.size(); ++i){ 192 | if(randBit[i] == false){ 193 | Ztest[4].push_back(Z[i]); 194 | for(int l = 0; l < Z[i].size(); ++l){ 195 | fout << Z[i][l]<< ","; 196 | } 197 | fout << endl; 198 | 199 | } 200 | } 201 | fout.close(); 202 | 203 | 204 | //-------------------------------------------------- 205 | //! Generate the learning dataset : Ztrain[0] ... Ztrain[4] 206 | //! Ztrain[0] = (Ztest[1], Ztest[2], Ztest[3], Ztest[4]) 207 | //! Ztrain[1] = (Ztest[2], Ztest[3], Ztest[4], Ztest[0]) 208 | 209 | for(int m = 0; m < 5; ++m){ 210 | for(int l = m+1; l < 5; ++l){ 211 | for(int i = 0; i < n_test[l]; ++i){ 212 | Ztrain[m].push_back(Ztest[l][i]); 213 | //cout << Ztest[l][i][0] << "\t" ; 214 | } 215 | //cout << endl; 216 | } 217 | 218 | for(int l = 0; l < m; ++l){ 219 | for(int i = 0; i < n_test[l]; ++i){ 220 | Ztrain[m].push_back(Ztest[l][i]); 221 | //cout << Ztest[l][i][0] << "\t" ; 222 | } 223 | //cout << endl; 224 | } 225 | 226 | int l1 = n_train + n_test[m] - Z.size(); 227 | 228 | for(int l = 0; l< l1; ++l){ 229 | Ztrain[m].push_back(Z0); 230 | } 231 | 232 | cout << "#(learning samples[" << m << "]): " << Z.size() - n_test[m] << ", " ; 233 | cout << "Ztrain.size: " << Ztrain[m].size() << endl; 234 | } 235 | } 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /Database.h: -------------------------------------------------------------------------------- 1 | #ifndef DATABASE_H 2 | #define DATABASE_H 3 | 4 | #include 5 | #include 6 | 7 | using namespace NTL; 8 | using namespace std; 9 | 10 | typedef vector dVec; 11 | typedef vector< vector > dMat; 12 | 13 | 14 | 15 | 16 | //!@ return: number of samples 17 | int readData(dMat& Z, char* filename); 18 | 19 | //--------------------------------------------------------------------- 20 | //!@ Choose the learning data and test data 21 | 22 | void RandomSamplingData(dMat& Ztrain, dMat& Ztest, dMat& Z); 23 | 24 | void SamplingData(dMat& zTrain, dMat& Ztest, dMat& Z); 25 | 26 | //--------------------------------------------------------------------- 27 | // cross-validation 28 | void cvRandomSamplingData(dMat*& Ztrain, dMat*& Ztest, dMat& Z, char* filename); 29 | 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /HELR.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include // pow 5 | #include 6 | #include // check the memory usage 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | #include "../src/TestScheme.h" 18 | #include "../src/Cipher.h" 19 | #include "../src/CZZ.h" 20 | #include "../src/EvaluatorUtils.h" 21 | #include "../src/Message.h" 22 | #include "../src/Params.h" 23 | #include "../src/PubKey.h" 24 | #include "../src/Scheme.h" 25 | #include "../src/SchemeAlgo.h" 26 | #include "../src/SchemeAux.h" 27 | #include "../src/SecKey.h" 28 | #include "../src/StringUtils.h" 29 | 30 | 31 | #include "LRtest.h" 32 | #include "HELR.h" 33 | 34 | #define debug 0 35 | 36 | 37 | long LogReg::getctlvl(Cipher& ctxt){ 38 | long nBits = NumBits(ctxt.mod)-1; 39 | return nBits; 40 | } 41 | 42 | 43 | 44 | //--------------------------------------------------------------------------------------------------- 45 | 46 | //! @ output ztrain = (2*y[k]-1) * (1, x[k]) -> encryption: zTrainCipher 47 | void LogReg::EncryptData(Cipher*& zTrainCipher, dMat zTrain){ 48 | 49 | //long slots = LRparams.n_training; 50 | 51 | CZZ** mvec= new CZZ*[LRparams.dim1]; 52 | 53 | // zTrainCipher = (2*y[k]-1) * (1, x[k]) 54 | for (long i = 0; i < LRparams.dim1; ++i){ 55 | mvec[i]= new CZZ[LRparams.nslots]; 56 | for(int k=0; k< LRparams.nslots; ++k){ 57 | if(zTrain[k][i]!=0){ 58 | mvec[i][k].r = scaleup(zTrain[k][i], LRparams.logp-3); // logp/8 59 | } 60 | else{ 61 | mvec[i][k].r = to_ZZ("0"); 62 | } 63 | mvec[i][k].i = to_ZZ("0"); 64 | } 65 | } 66 | 67 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 68 | for (long i = first; i < last; ++i){ 69 | zTrainCipher[i] = scheme.encrypt(mvec[i], LRparams.nslots); 70 | } 71 | NTL_EXEC_RANGE_END; 72 | 73 | 74 | delete[] mvec; 75 | 76 | } 77 | 78 | 79 | void LogReg::show_and_compare(dVec& theta, dMat zTrain, CZZ*& dtheta){ 80 | 81 | LR_poly(theta, zTrain, LRparams); 82 | 83 | double maxErrorBit = 0.0; 84 | double minRelativeBit= 20.0; 85 | 86 | for(int i=0; i< LRparams.dim1; i++){ 87 | ZZ msg_scaleup= scaleup(theta[i], LRparams.logp); 88 | 89 | cout << "m " << i << " : [" << msg_scaleup << "], theta: " << theta[i] << endl; // unencrypted 90 | 91 | double theta; 92 | conv(theta, dtheta[i].r); 93 | theta = scaledown(theta, LRparams.logp); 94 | 95 | cout << "d " << i << " : [" << dtheta[i].r << "], (HE)theta: " << theta << endl; // encrypted 96 | cout << "e " << i << " : [" << (msg_scaleup - dtheta[i].r) << "], "; // error 97 | 98 | 99 | // Msg-bit 100 | ZZ msgbnd= dtheta[i].r; 101 | double MsgBit = 0.0; 102 | if(msgbnd!=0) 103 | MsgBit= (log(abs(msgbnd))/log(2)) ; 104 | cout << "Msg: " << MsgBit << ", "; 105 | 106 | // Error-bit 107 | ZZ error = (msg_scaleup - dtheta[i].r); 108 | double ErrorBit = 0.0; 109 | if(error!=0) 110 | ErrorBit= (log(abs(error))/log(2)) ; 111 | cout << "Error: " << ErrorBit << endl; 112 | 113 | double RelativeBit= MsgBit- ErrorBit; 114 | 115 | if(maxErrorBit < ErrorBit) maxErrorBit= ErrorBit; 116 | if(minRelativeBit > RelativeBit) minRelativeBit= RelativeBit; 117 | cout << "-------------------------------------------------------------" << endl; 118 | 119 | } 120 | 121 | cout << "MAX error bit : " << maxErrorBit << ", Min relative-error bit: " << minRelativeBit<< endl; 122 | cout << "-------------------------------------------------------------" << endl; 123 | 124 | 125 | } 126 | 127 | 128 | 129 | void LogReg::HElogreg(Cipher*& thetaCipher, Cipher*& zTrainCipher, dMat zTrain){ 130 | struct rusage usage; 131 | auto start= chrono::steady_clock::now(); 132 | 133 | // zSumCipher = 1/(n/polyscale) * sum (2y[k]-1) x[k] = 1/n * sum z[k] 134 | // At the first round, we just take zTrainCipher as theta (lvl= 2) 135 | Cipher* zSumCipher= new Cipher[LRparams.dim1]; 136 | 137 | //! rot and sum 138 | Cipher* ctemp= new Cipher[LRparams.dim1]; 139 | 140 | 141 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 142 | for (long i = first; i < last; ++i){ 143 | zSumCipher[i]= zTrainCipher[i]; 144 | 145 | for(long j= 0; j< LRparams.logn; ++j){ 146 | int l = (1< (diff).count()/1000.0; 161 | double totaltime = timeElapsed; 162 | 163 | int ret = getrusage(RUSAGE_SELF,&usage); 164 | 165 | cout << "-------------------------------------------------------------" << endl; 166 | cout << "1-iter : mod(theta)= " << getctlvl(thetaCipher[0]) << ", running time= " << timeElapsed << "s, " ; 167 | cout<< "Mem= " << usage.ru_maxrss/(1024*1024) << "GB" << endl; 168 | cout << "-------------------------------------------------------------" << endl; 169 | 170 | 171 | 172 | dVec mtheta(LRparams.dim1, 0.0); 173 | CZZ* dtheta = new CZZ[LRparams.dim1]; 174 | for(int i = 0; i< LRparams.dim1; ++i){ 175 | dtheta[i] = (scheme.decrypt(secretKey, thetaCipher[i]))[0]; 176 | } 177 | 178 | show_and_compare(mtheta, zTrain, dtheta); 179 | 180 | 181 | //-------------------------------------------------------------- 182 | double zlvl = getctlvl(zSumCipher[0]); 183 | 184 | for(int j= 1; j< LRparams.max_iter; ++j){ 185 | auto start= chrono::steady_clock::now(); 186 | 187 | Cipher* gradCipher= new Cipher[LRparams.dim1]; 188 | 189 | switch(LRparams.polydeg){ 190 | case 3: 191 | gradCipher= getgrad_deg3(thetaCipher, zTrainCipher); 192 | break; 193 | case 7: 194 | gradCipher= getgrad_deg7(thetaCipher, zTrainCipher); 195 | break; 196 | 197 | } 198 | 199 | double tlvl = getctlvl(thetaCipher[0]); 200 | double glvl = getctlvl(gradCipher[0]); 201 | 202 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 203 | for (long i = first; i < last; ++i){ 204 | Cipher ztemp = scheme.modEmbed(zSumCipher[i], zlvl- tlvl); 205 | scheme.addAndEqual(thetaCipher[i], ztemp); 206 | 207 | scheme.modEmbedAndEqual(thetaCipher[i], tlvl- glvl); 208 | scheme.subAndEqual(thetaCipher[i], gradCipher[i]); 209 | } 210 | NTL_EXEC_RANGE_END; 211 | 212 | 213 | auto end = std::chrono::steady_clock::now(); 214 | auto diff = end - start; 215 | double timeElapsed= chrono::duration (diff).count()/1000.0; 216 | totaltime += timeElapsed; 217 | 218 | ret = getrusage(RUSAGE_SELF,&usage); 219 | 220 | delete[] gradCipher; 221 | 222 | cout << "-------------------------------------------------------------" << endl; 223 | cout << j+1 << "-iter : mod(theta)= " << getctlvl(thetaCipher[0]) << ", running time= " << timeElapsed << "s, " ; 224 | cout<< "Mem= " << usage.ru_maxrss/(1024*1024) << "GB" << endl; 225 | cout << "-------------------------------------------------------------" << endl; 226 | 227 | 228 | for(int i=0; i< LRparams.dim1; ++i){ 229 | dtheta[i] = (scheme.decrypt(secretKey, thetaCipher[i]))[0]; 230 | } 231 | 232 | show_and_compare(mtheta, zTrain, dtheta); 233 | } 234 | 235 | 236 | cout << "Total Evaluation Time = " << totaltime << " s" << endl; 237 | 238 | delete[] zSumCipher; 239 | delete[] ctemp; 240 | delete[] dtheta; 241 | 242 | 243 | } 244 | 245 | 246 | 247 | 248 | Cipher* LogReg::getgrad_deg7(Cipher*& thetaCipher, Cipher*& zTrainCipher){ 249 | 250 | //! compute ztheta = (p* z[k]/8) (p* theta)/p : mod(theta)+ logp 251 | double tlvl = getctlvl(thetaCipher[0]); 252 | double zlvl = getctlvl(zTrainCipher[0]); 253 | 254 | Cipher* ctemp= new Cipher[LRparams.dim1]; 255 | 256 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 257 | for (long i = first; i < last; i++){ 258 | ctemp[i] = scheme.modEmbed(zTrainCipher[i], zlvl - tlvl); 259 | scheme.multAndEqual(ctemp[i], thetaCipher[i]); 260 | } 261 | NTL_EXEC_RANGE_END; 262 | 263 | Cipher ztheta = ctemp[0]; 264 | for (long i = 1; i < LRparams.dim1; i++){ 265 | scheme.addAndEqual(ztheta, ctemp[i]); 266 | } 267 | 268 | scheme.modSwitchAndEqual(ztheta, LRparams.logp); // ztheta.lvl : tlvl - logp 269 | 270 | 271 | 272 | //----------------------------------------------------------------------------------------- 273 | // ctemp = alpha * (ztheta) * (a7*ztheta^6 + a5*ztheta^4 +a3*ztheta^2 + a1) * z[i] for 0<=i<=dim 274 | // = ((alpha*a7*z[i]) * (ztheta)) * (ztheta^6 + a5/a7*ztheta^4 +a3/a7*ztheta^2 + a1/a7) 275 | //----------------------------------------------------------------------------------------- 276 | 277 | 278 | // zSquare = p * (theat*z[k]/8)^2 with tlvl - 2*logp 279 | Cipher zSquare= scheme.square(ztheta); 280 | scheme.modSwitchAndEqual(zSquare, LRparams.logp); 281 | 282 | // zQuartic = p * (theat*z[k]/8)^4 with tlvl - 3*logp 283 | Cipher zQuartic = scheme.square(zSquare); 284 | scheme.modSwitchAndEqual(zQuartic, LRparams.logp); 285 | 286 | // zQuartic = p * (a7*ztheta^4 + a5*ztheta^2 + a3) with tlvl - 3*logp 287 | Cipher ctemp1= scheme.multByConst(zSquare, LRparams.evalcoeff[5]); 288 | scheme.modSwitchAndEqual(ctemp1, LRparams.logp); // lvl(theta)+3 289 | scheme.addConstAndEqual(ctemp1, LRparams.evalcoeff[3]); 290 | 291 | scheme.multByConst(zQuartic, LRparams.evalcoeff[7]); 292 | scheme.addAndEqual(zQuartic, ctemp1); 293 | 294 | 295 | Cipher* res= new Cipher[LRparams.dim1]; 296 | 297 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 298 | for (long i = first; i < last; ++i){ 299 | res[i] = scheme.modEmbed(zTrainCipher[i], zlvl - tlvl + LRparams.logp); 300 | scheme.multAndEqual(res[i], ztheta); 301 | scheme.modSwitchAndEqual(res[i], LRparams.logp); // res: tlvl - logp 302 | 303 | ctemp[i]= scheme.multByConst(res[i], LRparams.evalcoeff[1]); 304 | scheme.modSwitchAndEqual(ctemp[i], LRparams.logp); // res: tlvl - 2*logp 305 | 306 | scheme.multAndEqual(res[i], zSquare); 307 | scheme.modSwitchAndEqual(res[i], LRparams.logp); // res: tlvl - 3 *logp 308 | 309 | 310 | scheme.multAndEqual(res[i], zQuartic); 311 | scheme.modSwitchAndEqual(res[i], LRparams.logp); 312 | scheme.multByConst(res[i], LRparams.evalcoeff[7]); // res: tlvl - 4 *logp 313 | 314 | scheme.addAndEqual(res[i], ctemp[i]); 315 | } 316 | NTL_EXEC_RANGE_END; 317 | 318 | 319 | //! rot and sum 320 | 321 | NTL_EXEC_RANGE(LRparams.dim1, first, last); 322 | for (long i = first; i < last; ++i){ 323 | for(long j= 0; j< LRparams.logn; ++j){ 324 | long l = (1< 6 | #include 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | #include "../src/TestScheme.h" 14 | #include "../src/Cipher.h" 15 | #include "../src/CZZ.h" 16 | #include "../src/EvaluatorUtils.h" 17 | #include "../src/Message.h" 18 | #include "../src/Params.h" 19 | #include "../src/PubKey.h" 20 | #include "../src/Scheme.h" 21 | #include "../src/SchemeAlgo.h" 22 | #include "../src/SchemeAux.h" 23 | #include "../src/SecKey.h" 24 | #include "../src/StringUtils.h" 25 | 26 | 27 | 28 | #include "Database.h" 29 | #include "LRtest.h" 30 | 31 | using namespace std; 32 | using namespace NTL; 33 | 34 | 35 | class LogReg { 36 | public: 37 | 38 | Scheme& scheme; 39 | LRpar& LRparams; 40 | SecKey& secretKey; 41 | 42 | 43 | //! @ constructor 44 | LogReg(Scheme& scheme, SecKey& secretKey, LRpar& LRparams) : scheme(scheme), secretKey(secretKey), LRparams(LRparams) {} 45 | 46 | 47 | //--------------------------------------------------------------------------------------------------- 48 | 49 | void EncryptData(Cipher*& zTrainCipher, dMat zTrain); 50 | //void EncryptData_small(Cipher*& zTrainCipher, dMat zTrain, LRpar& LRparams, Scheme& scheme); 51 | 52 | void HElogreg(Cipher*& thetaCipher, Cipher*& zTrainCipher, dMat zTrain); 53 | 54 | Cipher* getgrad_deg3(Cipher*& thetaCipher, Cipher*& zTrainCipher); 55 | Cipher* getgrad_deg7(Cipher*& thetaCipher, Cipher*& zTrainCipher); 56 | 57 | static long getctlvl(Cipher& ctxt); 58 | void show_and_compare(dVec& theta, dMat zTrain, CZZ*& dtheta); 59 | 60 | 61 | }; 62 | 63 | 64 | 65 | #endif /* LOGISTIC_H_ */ 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Miran Kim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LRtest.cpp: -------------------------------------------------------------------------------- 1 | #include "LRtest.h" 2 | 3 | 4 | 5 | 6 | void ReadLRparams(LRpar& LRparams, int max_iter, dMat zTrain, int polydeg, long logp){ 7 | LRparams.max_iter= max_iter; 8 | 9 | LRparams.dim1 = zTrain[0].size(); 10 | //LRparams.n_training = zTrain.size(); 11 | LRparams.n_training = zTrain.size(); // Power of two 12 | LRparams.logn = log2(LRparams.n_training); 13 | 14 | 15 | //---------------------------------------------- 16 | // polynomial coefficients 17 | for(int i=0; i<10; i++){ 18 | LRparams.coeff[i] = 0.0; 19 | } 20 | 21 | // "Scaled" polynomial coefficients 22 | LRparams.polyscale= 4; 23 | 24 | for(int i=0; i<10; i++){ 25 | LRparams.evalcoeff[i]= to_ZZ("0"); 26 | } 27 | 28 | 29 | switch(polydeg){ 30 | case 3: 31 | LRparams.max_iter = 25; 32 | LRparams.coeff[1] = 2.401926612; 33 | LRparams.coeff[3] = (-1.631249824); 34 | 35 | LRparams.evalcoeff[1]= scaleup(LRparams.coeff[1]/LRparams.coeff[3], logp); 36 | LRparams.evalcoeff[3]= scaleup(LRparams.coeff[3], logp); 37 | break; 38 | 39 | case 7: 40 | LRparams.max_iter = 20; 41 | LRparams.coeff[1] = 3.46992; 42 | LRparams.coeff[3] = - 8.38814; 43 | LRparams.coeff[5] = 10.86804; 44 | LRparams.coeff[7] = - 5.0; 45 | 46 | LRparams.evalcoeff[1]= scaleup(LRparams.coeff[1], logp); 47 | LRparams.evalcoeff[3]= scaleup(LRparams.coeff[3], logp); 48 | LRparams.evalcoeff[5]= scaleup(LRparams.coeff[5], logp); 49 | LRparams.evalcoeff[7]= to_ZZ(LRparams.coeff[7]); 50 | break; 51 | } 52 | 53 | 54 | 55 | LRparams.log2polyscale= log2(LRparams.polyscale); 56 | LRparams.polydeg= polydeg; 57 | 58 | LRparams.logp = logp; 59 | 60 | LRparams.nslots= zTrain.size(); // POT close to "N*0.8" 61 | 62 | } 63 | 64 | 65 | //--------------------------------------------------------------------- 66 | 67 | 68 | ZZ scaleup(double value, const long& l){ 69 | ZZ precision = power2_ZZ(l); 70 | double dtemp; 71 | conv(dtemp, precision); 72 | dtemp *= value; 73 | ZZ res = to_ZZ(dtemp); 74 | 75 | return res; 76 | } 77 | 78 | 79 | 80 | double scaledown(double value, const long& l){ 81 | double res = value; 82 | for(int j=0; j< l; j++){ 83 | res /= 2; 84 | } 85 | return res; 86 | 87 | } 88 | 89 | 90 | 91 | double inner_prod(dVec u, dVec v, int start = 0){ 92 | double res = 0.0; 93 | for(int i = start; i < u.size(); ++i) res += u[i] * v[i]; 94 | return res; 95 | } 96 | 97 | //--------------------------------------------------------------------- 98 | 99 | //! One iteration with the original method 100 | void LR_sigmoid(dVec& theta, dMat zTrain, LRpar& LRparams){ 101 | double* grad = new double[theta.size()]; 102 | for(int i = 0; i < theta.size(); ++i) grad[i] = 0.0; 103 | for(int k = 0; k < zTrain.size(); ++k){ 104 | double coeff = 1.0 / (1.0 + exp(inner_prod(zTrain[k], theta))); 105 | for(int i = 0; i < theta.size(); ++i) grad[i] += coeff * zTrain[k][i]; 106 | } 107 | for(int i = 0; i < theta.size(); ++i) theta[i] += grad[i]/zTrain.size();; 108 | delete[] grad; 109 | } 110 | 111 | 112 | 113 | // update for one iteration 114 | // deg3: 0.5 - 115 | // deg7: 0.5 - (3.4 (x/8)+ ... ) 116 | // 4/n sum_i (1- \sum coeff[j] * (ztrain*beta/8)^j ) z[i]/8 117 | // 1/n sum_i (0.5 - 0.5 \sum coeff[j] * (ztrain*beta/8)^j ) z[i] 118 | void LR_poly(dVec& theta, dMat zTrain, LRpar& LRparams){ 119 | double* grad = new double[theta.size()]; 120 | for(int i = 0; i < theta.size(); ++i) grad[i] = 0.0; 121 | 122 | 123 | // deg=3: (0.5- 1/2 (c1*ip+ c3*(ip)^3))z[k] 124 | for(int k = 0; k < zTrain.size(); ++k){ 125 | double innerprod = inner_prod(zTrain[k], theta)/8.0; 126 | double dtemp= innerprod; 127 | 128 | double coeff = 0.0; 129 | 130 | for(int i= 1; i< 10; ++i){ 131 | double power= pow(innerprod, i); 132 | coeff += LRparams.coeff[i] * power; 133 | } 134 | 135 | coeff= 1.0 - coeff; 136 | 137 | for(int i = 0; i < theta.size(); ++i) grad[i] += coeff * (zTrain[k][i]/8.0); 138 | } 139 | 140 | for(int i = 0; i < theta.size(); ++i) theta[i] += grad[i]/(zTrain.size()/4.0); 141 | delete[] grad; 142 | } 143 | 144 | 145 | 146 | 147 | double getAUC(dVec theta, dMat zTest){ 148 | int n_fail_y1 = 0; 149 | int n_fail_y0 = 0; 150 | 151 | dVec xtheta_y1; 152 | dVec xtheta_y0; 153 | 154 | for(int i = 0; i < zTest.size(); ++i){ 155 | if(zTest[i][0] == 1.0){ 156 | if(inner_prod(zTest[i], theta) < 0) n_fail_y1++; 157 | xtheta_y1.push_back(zTest[i][0] * inner_prod(zTest[i], theta, 1)); 158 | } 159 | else{ 160 | if(inner_prod(zTest[i], theta) < 0) n_fail_y0++; 161 | xtheta_y0.push_back(zTest[i][0] * inner_prod(zTest[i], theta, 1)); 162 | } 163 | } 164 | 165 | double correctness= 100.0 - (100.0 * (n_fail_y0 + n_fail_y1) / zTest.size()); 166 | cout << "Failure rate: (y = 1) " << n_fail_y1 << "/" << xtheta_y1.size() << " + (y = 0) " << n_fail_y0 << "/" ; 167 | cout << xtheta_y0.size() << " = " << (100.0 * (n_fail_y0 + n_fail_y1) / zTest.size()) << " %." << endl; 168 | cout << "Correctness: " << correctness << " %." << endl; 169 | 170 | 171 | if(xtheta_y0.size() == 0 || xtheta_y1.size() ==0){ 172 | cout << "n_test_yi = 0 : cannot compute AUC" << endl; 173 | return 0.0; 174 | } 175 | else{ 176 | double auc = 0.0; 177 | for(int i = 0; i < xtheta_y1.size(); ++i){ 178 | for(int j = 0; j < xtheta_y0.size(); ++j){ 179 | if(xtheta_y0[j] <= xtheta_y1[i]) auc++; 180 | } 181 | } 182 | auc /= xtheta_y1.size() * xtheta_y0.size(); 183 | return auc; 184 | cout << "AUC: " << auc << endl; 185 | } 186 | } 187 | 188 | double getMSE(dVec theta1, dVec theta2){ 189 | double res= 0.0; 190 | 191 | for(int i=0; i< theta1.size(); ++i){ 192 | double dtemp = pow(theta1[i]-theta2[i], 2.0); 193 | res += dtemp; 194 | } 195 | res/= (theta1.size()); 196 | return res; 197 | 198 | } 199 | 200 | 201 | double getNMSE(dVec theta1, dVec theta2){ 202 | double res= 0.0; 203 | 204 | for(int i=0; i< theta1.size(); ++i){ 205 | double dtemp = pow(theta1[i], 2.0); 206 | res += dtemp; 207 | } 208 | res/= (theta1.size()); 209 | 210 | double mse= getMSE(theta1, theta2); 211 | res= (mse/res); 212 | 213 | return res; 214 | 215 | } 216 | 217 | 218 | 219 | // Update mtheta (in an unencrypted status) and compare the encrypted output "theta" 220 | // with using the same sigmoid-approximation method 221 | 222 | //void show_and_compare(dVec& theta, dMat zTrain, CZZ*& dtheta, LRpar& LRparams, long logp){ 223 | 224 | -------------------------------------------------------------------------------- /LRtest.h: -------------------------------------------------------------------------------- 1 | #ifndef LR_UNENC 2 | #define LR_UNENC 3 | 4 | #include 5 | #include "Database.h" 6 | #include "../src/CZZ.h" // -> for comparison 7 | 8 | using namespace std; 9 | using namespace NTL; 10 | 11 | ZZ scaleup(double value, const long& l); 12 | double scaledown(double value, const long& l); 13 | 14 | // structure for LRparam 15 | typedef struct LRpar{ 16 | 17 | int max_iter; 18 | 19 | int dim1; 20 | int n_training; 21 | int logn; // log2(n_training) 22 | 23 | double coeff[10]; // double coefficients 24 | ZZ evalcoeff[10]; // transformed coefficients for HE 25 | 26 | int polyscale; 27 | int log2polyscale; 28 | 29 | int polydeg; 30 | 31 | long logp; 32 | long nslots; 33 | 34 | }LRpar; 35 | 36 | 37 | void ReadLRparams(LRpar& LRparams, int max_iter, dMat zTrain, int polydeg, long logp); 38 | 39 | 40 | //--------------------------------------------------------------------- 41 | //! @ Plaintext logistic regression 42 | void LR_sigmoid(dVec& theta, dMat zTrain, LRpar& LRparams); 43 | 44 | void LR_poly(dVec& theta, dMat zTrain, LRpar& LRparams); 45 | 46 | 47 | //--------------------------------------------------------------------- 48 | double getAUC(dVec theta, dMat zTest); 49 | 50 | double getMSE(dVec theta1, dVec theta2); 51 | 52 | double getNMSE(dVec theta1, dVec theta2); 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | PREFIX = $(HOME) 3 | CC = g++ 4 | AR = ar 5 | CFLAGS= -g -O2 -std=c++11 -pthread 6 | 7 | # path to the library files 8 | LDLIBS = -L/usr/local/lib -lntl -lgmp -lm 9 | 10 | # link in a library 11 | LDFLAGS = -I/usr/local/include 12 | LIBS = -lntl -lm 13 | 14 | 15 | HEADER = Database.h LRtest.h HELR.h 16 | SRC = Database.cpp LRtest.cpp HELR.cpp 17 | OBJ= $(SRC:.cpp=.o) 18 | 19 | 20 | lib: ar rc libheaan.a ../src/*.o 21 | 22 | all: libHELR.a 23 | 24 | clean: 25 | rm *.o libHELR.a || echo nothing to clean 26 | 27 | new: 28 | make clean 29 | make all 30 | 31 | 32 | test: 33 | g++ -std=c++11 -O2 -I/usr/local/include -pthread Test.cpp libheaan.a libHELR.a -o foo -L/usr/local/lib -lntl -lgmp -lm 34 | #./foo 35 | #data/edin.txt 36 | 37 | 38 | obj: $(OBJ) 39 | 40 | %.o: %.cpp $(HEADER) 41 | $(CC) $(CFLAGS) -c $(LDFLAGS) $< 42 | 43 | libHELR.a: $(OBJ) 44 | $(AR) -q libHELR.a $(OBJ) 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HELR 2 | 3 | HELR is a software project for performing a logistic regression training on encrypted data (Secure Logistic Regression based on Homomorphic Encryption: Design and Evaluation (https://medinform.jmir.org/2018/2/e19/)) 4 | 5 | ## Setting up HELR library 6 | 7 | ### Dependencies 8 | 9 | Our library requires a c++ compiler and the following libraries: 10 | 11 | * `GMP`(GNU Multi-Precision library), which is available at https://gmplib.org, 12 | 13 | * `NTL`(ver. 10.5.0), which is available at http://www.shoup.net/ntl/, (with pThread) 14 | 15 | * `HEAAN`, which is an implementation of the paper "Homomorphic Encryption for Arithmetic of Approximate Numbers" (https://eprint.iacr.org/2016/421.pdf). We refered to the underlying HE library in the "src" folder. You can build the libarary “libheaan.a" by typing "$make all" in the "/src" directory. 16 | 17 | ### Installing HELR library 18 | 19 | HELR is easy to configure and build in Linux and macOS. You can then install our library by the following work with command line tools: 20 | 21 | ```sh 22 | make new 23 | ``` 24 | 25 | ## Running a test source code 26 | 27 | You run a test program Test_HELR.cpp with a filename and a degree of approximating polynomial of the sigmoid function. 28 | For example, you can write: 29 | 30 | ```sh 31 | g++ -std=c++11 -O2 -I/usr/local/include -pthread Test_HELR.cpp src/libheaan.a libHELR.a -o foo -L/usr/local/lib -lntl -lgmp -lm 32 | ./foo data/edint.txt 3 33 | ``` 34 | 35 | In particular, our program supports the evaluation of the gradient descent algorithm based on polynomial of degree 3 or degree 7 with several optimizations. 36 | -------------------------------------------------------------------------------- /Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // check the memory usage 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | #include "../src/CZZ.h" 21 | #include "../src/Params.h" 22 | #include "../src/PubKey.h" 23 | #include "../src/Scheme.h" 24 | #include "../src/SchemeAlgo.h" 25 | #include "../src/SecKey.h" 26 | #include "../src/TestScheme.h" 27 | #include "../src/TimeUtils.h" 28 | #include "../src/Ring2Utils.h" 29 | #include "../src/StringUtils.h" 30 | #include "../src/EvaluatorUtils.h" 31 | 32 | #include "Database.h" 33 | #include "LRtest.h" 34 | #include "HELR.h" 35 | 36 | 37 | using namespace NTL; 38 | using namespace std; 39 | 40 | #define edin 0 41 | #define lbw 0 42 | #define nhanes 0 43 | #define pcs 0 44 | #define uis 1 45 | 46 | #define deg3 0 47 | #define deg7 1 48 | 49 | 50 | int main(int Argc, char** Argv) { 51 | 52 | 53 | 54 | 55 | //------------------------------------------------- 56 | // edin 3 57 | 58 | #if edin 59 | 60 | long dim = 10; 61 | 62 | dVec HEtheta; 63 | for(long i = 0; i < dim; ++i){ 64 | HEtheta.push_back(0); 65 | } 66 | dVec theta = HEtheta; 67 | 68 | 69 | #if deg3 70 | // enc 71 | double d1[5][10] = { 72 | {-2.3096, 0.0272073, 0.237126, 0.413105, 1.56539, 0.420032, 1.22366, 0.24056, 0.348441, -0.115547}, 73 | {-2.30421, 0.100643, 0.258077, 0.425902, 1.57127, 0.487219, 1.2142, 0.299149, 0.344583, -0.232117}, 74 | {-2.26649, 0.129234, 0.220046, 0.419709, 1.55028, 0.470247, 1.2181, 0.332275, 0.232887, -0.16465}, 75 | {-2.27702,0.121896,0.210386,0.476516,1.55823,0.47324,1.29062,0.301172,0.322334,-0.222855}, 76 | {-2.32468,0.13117,0.296224,0.455724,1.58208,0.488631,1.12723,0.293705,0.26573,-0.175652} 77 | }; 78 | 79 | // unenc 80 | double d2[5][10]= { 81 | {-1.84561,0.0410266,0.21145,0.375287,1.42349,0.393118,1.10869,0.260133,0.340038, -0.0301592}, 82 | {-1.84228,0.107926,0.227087,0.387291,1.42572,0.464584,1.09585,0.309594,0.340326,-0.131425}, 83 | {-1.80964,0.130404,0.196373,0.380948,1.41048,0.446163,1.10605,0.33555,0.240369,-0.07113}, 84 | {-1.82295,0.1303,0.185208,0.432315,1.41445,0.445306,1.16731,0.309165,0.318403,-0.120376}, 85 | {-1.85623,0.131818,0.270671,0.414115,1.43815,0.463057,1.02489,0.312728,0.27056,-0.0772305} 86 | }; 87 | #endif 88 | 89 | #if deg7 90 | // enc 91 | double d1[5][10] = { 92 | {-1.70862,0.0767734,0.111934,0.320924,1.20332,0.368435,0.975623,0.202047,0.225981,-0.164111}, 93 | {-1.72696,0.0828964,0.233901,0.325366,1.23315,0.352987,0.978842,0.285361,0.254023,-0.118856}, 94 | {-1.77931,0.146215,0.19663,0.334124,1.22997,0.34505,0.88086,0.301459,0.227977,-0.096778}, 95 | {-1.71429,0.0859897,0.223657,0.383277,1.26796,0.39982,0.966313,0.193434,0.266558,-0.106615}, 96 | {-1.73692,0.039327,0.198135,0.353211,1.20737,0.384475,0.974432,0.22363,0.271022,-0.113051} 97 | }; 98 | 99 | // unenc 100 | double d2[5][10]= { 101 | {-1.63077,0.0775747,0.109707,0.315522,1.18099,0.365107,0.959937,0.208349,0.229848,-0.14904}, 102 | {-1.64957,0.0842011,0.228315,0.318633,1.20718,0.348627,0.959917,0.289039,0.254139,-0.103792}, 103 | {-1.70052,0.145764,0.1935,0.327747,1.20809,0.342304,0.867952,0.305434,0.232147,-0.0827491}, 104 | {-1.63677,0.0875185,0.218174,0.375201,1.2413,0.395056,0.950016,0.197295,0.266842,-0.0921361}, 105 | {-1.66,0.0414038,0.19404,0.346126,1.18316,0.380969,0.956811,0.228401,0.271773,-0.0986661} 106 | }; 107 | #endif 108 | #endif 109 | 110 | //----------------------------------------------------------------------------------------------- 111 | #if lbw 112 | 113 | long dim = 10; 114 | 115 | dVec HEtheta; 116 | for(long i = 0; i < dim; ++i){ 117 | HEtheta.push_back(0); 118 | } 119 | dVec theta = HEtheta; 120 | 121 | 122 | #if deg3 123 | // enc 124 | double d1[5][10] = { 125 | {0.422997,0.563842,0.574296,0.356639,-0.0901424,-0.3138,-0.249092,-0.262686,-0.273382,0.00652375}, 126 | {0.326865,0.436024,0.504505,0.607584,-0.0901471,-0.226328,-0.263989,-0.234317,-0.231822,0.226328}, 127 | {0.290507,0.422196,0.468165,0.671223,-0.26527,-0.374119,-0.269304,-0.247008,-0.00263957,0.103969}, 128 | {0.356252,0.495548,0.534322,0.459868,-0.0386566,-0.162655,-0.22191,-0.110973,-0.361777,0.0766106}, 129 | {0.366316,0.409031,0.513619,0.481204,-0.2051,-0.359439,-0.134855,-0.247572,-0.217659,0.155762} 130 | }; 131 | 132 | // unenc 133 | double d2[5][10]= { 134 | {0.268483,0.409213,0.416833,0.272224,-0.104962,-0.325568,-0.156486,-0.270302,-0.274935,-0.021582}, 135 | {0.18401,0.294149,0.357697,0.505306,-0.0952575,-0.254155,-0.166291,-0.236949,-0.23085,0.141055}, 136 | {0.161241,0.289536,0.339311,0.563476,-0.253307,-0.38964,-0.171436,-0.248853,-0.00868123,0.0529501}, 137 | {0.203191,0.343795,0.378623,0.369493,-0.0520884,-0.194201,-0.137257,-0.119521,-0.355257,0.0356871}, 138 | {0.229272,0.271008,0.375981,0.394043,-0.202615,-0.364669,-0.0824151,-0.250081,-0.21947,0.0889461} 139 | }; 140 | #endif 141 | 142 | #if deg7 143 | double d1[5][10] = { 144 | {0.23337,0.340781,0.360396,0.50912,-0.132583,-0.305335,-0.15835,-0.235382,-0.206483,0.108969}, 145 | {0.240676,0.361545,0.328231,0.410251,-0.105575,-0.182004,-0.129082,-0.239813,-0.115716,0.018708}, 146 | {0.216525,0.349923,0.461581,0.400642,-0.11834,-0.274333,-0.168312,-0.147344,-0.148751,0.0513287}, 147 | {0.24523,0.268792,0.353208,0.343201,-0.14802,-0.203049,-0.213857,-0.139986,-0.267208,0.18439}, 148 | {0.299159,0.370108,0.403848,0.295206,-0.057741,-0.213337,-0.162167,-0.130216,-0.142562,-0.0122919} 149 | }; 150 | 151 | 152 | double d2[5][10]= { 153 | {0.203375,0.312023,0.33169,0.494735,-0.134543,-0.309076,-0.142767,-0.235718,-0.207982,0.101724}, 154 | {0.210552,0.333059,0.299944,0.39334,-0.10751,-0.188218,-0.115059,-0.240765,-0.118536,0.0139313}, 155 | {0.187129,0.32149,0.432182,0.385391,-0.120502,-0.27858,-0.151088,-0.148807,-0.149541,0.0423764}, 156 | {0.216928,0.242138,0.325805,0.326608,-0.149881,-0.206897,-0.19202,-0.141794,-0.266267,0.176538}, 157 | {0.26772,0.340275,0.373016,0.280735,-0.0612741,-0.219704,-0.145385,-0.131988,-0.144298,-0.0164114} 158 | }; 159 | #endif 160 | 161 | #endif 162 | 163 | 164 | //----------------------------------------------------------------------------------------------- 165 | #if nhanes 166 | 167 | long dim = 16; 168 | 169 | dVec HEtheta; 170 | for(long i = 0; i < dim; ++i){ 171 | HEtheta.push_back(0); 172 | } 173 | dVec theta = HEtheta; 174 | 175 | #if deg3 176 | 177 | double d1[5][16] = { 178 | {-0.509702,-0.436656,0.812806,-0.104327,-0.178984,-0.273675,-0.0569273,-0.405834,-0.523567,-0.111917,-0.127165,-0.24938,-0.383506,0.123729,-0.249789,-0.188048}, 179 | {-0.511547,-0.428814,0.79463,-0.11388,-0.172645,-0.277063,-0.0600614,-0.40531,-0.523367,-0.123478,-0.132929,-0.220274,-0.3786,0.0885165,-0.220708,-0.181821}, 180 | {-0.507992,-0.427226,0.791156,-0.106124,-0.159646,-0.29013,-0.0567484,-0.415313,-0.522236,-0.130412,-0.134872,-0.232424,-0.372524,0.0979456,-0.23232,-0.18985}, 181 | {-0.509376,-0.432348,0.797631,-0.126974,-0.175651,-0.279435,-0.0532585,-0.411935,-0.525635,-0.114459,-0.14472,-0.228384,-0.365355,0.0840068,-0.227922,-0.170983}, 182 | {-0.510039,-0.413817,0.791328,-0.122951,-0.172852,-0.269375,-0.0671568,-0.393519,-0.526029,-0.108344,-0.130484,-0.240543,-0.379729,0.110248,-0.240923,-0.18537} 183 | }; 184 | 185 | // unenc 186 | double d2[5][16]= { 187 | {-0.417536,-0.408259,0.826907,-0.0839599,-0.147082,-0.220024,-0.0505396,-0.316469,-0.431089,-0.0250014,-0.102938,-0.206636,-0.314598,0.104004,-0.206636,-0.112228}, 188 | {-0.418896,-0.401888,0.812628,-0.0926409,-0.140102,-0.223175,-0.0539007,-0.315327,-0.430735,-0.0361079,-0.106885,-0.180727,-0.312011,0.0741434,-0.180727,-0.104924}, 189 | {-0.41368,-0.404316,0.81022,-0.0847799,-0.127832,-0.23485,-0.0513436,-0.323945,-0.428598,-0.042761,-0.10841,-0.191883,-0.305269,0.0834724,-0.191883,-0.113023}, 190 | {-0.416963,-0.406645,0.814641,-0.104314,-0.142158,-0.226073,-0.0481087,-0.32242,-0.432904,-0.0273535,-0.116536,-0.187911,-0.300427,0.0716744,-0.187911,-0.0944277}, 191 | {-0.417996,-0.385368,0.807054,-0.100575,-0.140205,-0.216252,-0.0608955,-0.304873,-0.433389,-0.0219947,-0.105711,-0.198094,-0.312285,0.0926891,-0.198094,-0.109833} 192 | }; 193 | #endif 194 | 195 | #if deg7 196 | 197 | double d1[5][16] = { 198 | {-0.386908,-0.342747,0.633259,-0.0820743,-0.130115,-0.209118,-0.0453112,-0.303979,-0.398057,-0.0706921,-0.0931633,-0.18554,-0.292709,0.0931659,-0.185468,-0.125443}, 199 | {-0.387296,-0.343143,0.658761,-0.0874399,-0.132796,-0.204762,-0.0478443,-0.305208,-0.39983,-0.080535,-0.0987078,-0.175728,-0.287854,0.0773493,-0.175564,-0.126196}, 200 | {-0.380768,-0.35364,0.651971,-0.092917,-0.12588,-0.207294,-0.0457791,-0.301225,-0.391926,-0.0672453,-0.105946,-0.189288,-0.274506,0.0846216,-0.189846,-0.127777}, 201 | {-0.384959,-0.354486,0.65843,-0.085151,-0.133295,-0.209428,-0.0416175,-0.300128,-0.396936,-0.0686171,-0.100872,-0.177275,-0.283519,0.076367,-0.177419,-0.127996}, 202 | {-0.382264,-0.348052,0.654011,-0.0928662,-0.118096,-0.217502,-0.0461899,-0.312024,-0.396309,-0.0739655,-0.100359,-0.175623,-0.281793,0.0760841,-0.175397,-0.124201} 203 | }; 204 | 205 | // unenc 206 | double d2[5][16]= { 207 | {-0.36747,-0.389659,0.647536,-0.0826648,-0.122534,-0.199535,-0.0443042,-0.287882,-0.379549,-0.0528479,-0.0875986,-0.183383,-0.279872,0.0960378,-0.183383,-0.108428}, 208 | {-0.367703,-0.389275,0.67293,-0.0879813,-0.125456,-0.194841,-0.0469033,-0.288982,-0.381326,-0.0634198,-0.0931606,-0.173335,-0.274543,0.0804283,-0.173335,-0.109262}, 209 | {-0.361403,-0.398413,0.66566,-0.0930521,-0.118982,-0.197413,-0.0448409,-0.285499,-0.373695,-0.0498745,-0.100276,-0.187494,-0.261127,0.0872186,-0.187494,-0.111123}, 210 | {-0.365904,-0.400712,0.672282,-0.0857551,-0.125807,-0.199267,-0.0403109,-0.284188,-0.378694,-0.0512406,-0.0957335,-0.17482,-0.270171,0.0793422,-0.17482,-0.110903}, 211 | {-0.363435,-0.390017,0.667482,-0.0932839,-0.110943,-0.207487,-0.0452524,-0.296227,-0.378173,-0.0565097,-0.0948731,-0.173227,-0.268562,0.0786063,-0.173227,-0.107617} 212 | }; 213 | #endif 214 | 215 | #endif 216 | 217 | 218 | #if pcs 219 | 220 | long dim = 10; 221 | 222 | dVec HEtheta; 223 | for(long i = 0; i < dim; ++i){ 224 | HEtheta.push_back(0); 225 | } 226 | dVec theta = HEtheta; 227 | 228 | 229 | #if deg3 230 | // enc 231 | double d1[5][10] = { 232 | {-0.396804,-0.409782,-0.131726,-0.62876,-0.178234,0.278771,0.334936,0.907458,-0.498244,0.0468849}, 233 | {-0.323273,-0.3064,-0.222945,-0.688208,-0.288657,0.293826,0.319125,0.799614,-0.386816,0.105713}, 234 | {-0.40622,-0.410778,-0.206003,-0.634669,-0.173537,0.23467,0.191136,0.948636,-0.363979,0.0353504}, 235 | {-0.345967,-0.336286,-0.265665,-0.710789,-0.358499,0.40369,0.302459,0.727827,-0.302868,0.123272}, 236 | {-0.294109,-0.314517,-0.287464,-0.718921,-0.154705,0.260062,0.416831,0.772349,-0.482361,0.099255} 237 | }; 238 | 239 | // unenc 240 | double d2[5][10]= { 241 | {-0.325608,-0.335742,-0.0610194,-0.548909,-0.137763,0.253188,0.291079,0.716666,-0.348864,0.0905624}, 242 | {-0.260603,-0.241469,-0.140363,-0.607566,-0.244686,0.253319,0.279206,0.605749,-0.258191,0.141257}, 243 | {-0.329762,-0.331809,-0.114874,-0.552862,-0.135744,0.211456,0.160556,0.740585,-0.246913,0.0820288}, 244 | {-0.277286,-0.265268,-0.181245,-0.624341,-0.29568,0.345954,0.26791,0.536757,-0.186921,0.164677}, 245 | {-0.230608,-0.2483,-0.205389,-0.632893,-0.128098,0.241532,0.373072,0.590657,-0.330987,0.137249} 246 | }; 247 | #endif 248 | 249 | #if deg7 250 | // enc 251 | double d1[5][10] = { 252 | {-0.291031,-0.292615,-0.146587,-0.534505,-0.233712,0.253309,0.266031,0.601826,-0.273377,0.0657083}, 253 | {-0.296123,-0.306986,-0.151729,-0.463651,-0.200342,0.266079,0.200702,0.663068,-0.243162,0.0556476}, 254 | {-0.25627,-0.257151,-0.213695,-0.560226,-0.133541,0.263721,0.239975,0.666216,-0.296886,0.0849749}, 255 | {-0.218091,-0.202982,-0.160825,-0.487106,-0.131102,0.101116,0.242501,0.591813,-0.400647,0.108983}, 256 | {-0.271263,-0.277104,-0.124402,-0.579099,-0.178999,0.266336,0.266124,0.616188,-0.270593,0.0655934} 257 | }; 258 | 259 | // unenc 260 | double d2[5][10]= { 261 | {-0.277091,-0.278476,-0.129332,-0.519732,-0.22412,0.246515,0.25788,0.579047,-0.252402,0.0741219}, 262 | {-0.28185,-0.292581,-0.135985,-0.451484,-0.190421,0.25892,0.194446,0.639444,-0.223924,0.064986}, 263 | {-0.24341,-0.24393,-0.197337,-0.544683,-0.127067,0.25653,0.234502,0.650726,-0.278517,0.092739}, 264 | {-0.206807,-0.191062,-0.146287,-0.474637,-0.127135,0.0993992,0.236159,0.566037,-0.374476,0.11547}, 265 | {-0.25875,-0.264167,-0.10926,-0.56499,-0.171994,0.259195,0.258927,0.598907,-0.252123,0.0732831} 266 | }; 267 | #endif 268 | #endif 269 | 270 | 271 | 272 | #if uis 273 | 274 | long dim = 9; 275 | 276 | dVec HEtheta; 277 | for(long i = 0; i < dim; ++i){ 278 | HEtheta.push_back(0); 279 | } 280 | dVec theta = HEtheta; 281 | 282 | 283 | #if deg3 284 | // enc 285 | double d1[5][9] = { 286 | {0.384215,0.191973,0.434771,-0.317343,0.254925,0.301087,0.33959,0.488754,0.142825}, 287 | {0.324928,0.155588,0.10235,-0.371976,0.176389,0.316115,0.374546,0.414583,0.394635}, 288 | {0.344823,0.153075,0.180152,-0.0301378,-0.0275188,0.363993,0.447671,0.356882,0.263324}, 289 | {0.352371,0.181306,0.177223,-0.119848,0.074264,0.292695,0.40553,0.373648,0.319083}, 290 | {0.24951,0.114417,0.28154,-0.271076,0.0178798,0.427462,0.402376,0.386603,0.231958} 291 | }; 292 | 293 | // unenc 294 | double d2[5][9]= { 295 | {0.253091,0.0602054,0.319134,-0.315853,0.203712,0.268911,0.236565,0.399009,0.0646211}, 296 | {0.221026,0.0483443,0.0257128,-0.344558,0.131891,0.249146,0.274804,0.335384,0.299215}, 297 | {0.220208,0.0313082,0.0928322,-0.0612107,-0.0546365,0.311081,0.338718,0.277298,0.179891}, 298 | {0.229009,0.0583257,0.0885778,-0.137879,0.0366888,0.244216,0.301204,0.295203,0.23007}, 299 | {0.138754,0.00141469,0.184895,-0.261925,-0.0187373,0.374976,0.303354,0.308262,0.155218} 300 | }; 301 | #endif 302 | 303 | #if deg7 304 | // enc 305 | double d1[5][9] = { 306 | {0.183495,0.104425,0.177821,-0.225676,0.0609212,0.278777,0.250036,0.385556,0.223898}, 307 | {0.206025,0.0451485,0.183937,-0.179252,0.0517283,0.273098,0.241186,0.315526,0.217613}, 308 | {0.236503,0.0786809,0.151718,-0.128854,0.173713,0.357246,0.294785,0.310382,0.166837}, 309 | {0.235495,0.107051,0.147793,-0.252712,0.0268938,0.271813,0.326528,0.312734,0.18549}, 310 | {0.293067,0.131642,0.153259,-0.141633,0.0278621,0.212043,0.343242,0.19066,0.18186} 311 | }; 312 | 313 | // unenc 314 | double d2[5][9]= { 315 | {0.155178,0.0775829,0.15848,-0.232455,0.0514927,0.291044,0.231494,0.372177,0.207281}, 316 | {0.178169,0.0185114,0.16655,-0.184599,0.0422327,0.281805,0.2232,0.301977,0.199971}, 317 | {0.204922,0.0480639,0.131435,-0.139319,0.164798,0.387524,0.275573,0.298676,0.147496}, 318 | {0.206303,0.0797317,0.129896,-0.259443,0.016184,0.287227,0.306874,0.299711,0.168025}, 319 | {0.261984,0.102016,0.135746,-0.150942,0.0185771,0.223012,0.323259,0.178307,0.165088} 320 | }; 321 | #endif 322 | #endif 323 | 324 | 325 | 326 | double avg_MSE = 0.0; 327 | double avg_NMSE= 0.0; 328 | 329 | for(long k = 0; k < 5; ++k){ 330 | for(long i = 0; i < dim; ++i){ 331 | HEtheta[i] = d1[k][i]; 332 | theta[i] = d2[k][i]; 333 | } 334 | 335 | avg_MSE += getMSE(HEtheta, theta); 336 | avg_NMSE += getNMSE(HEtheta, theta); 337 | } 338 | 339 | avg_MSE/= 5.0; 340 | avg_NMSE/= 5.0; 341 | 342 | //cout << avg_MSE << endl; 343 | //cout << avg_NMSE << endl; 344 | 345 | for(long i = 0; i < dim; ++i){ 346 | for(long k = 0; k < 4; ++k){ 347 | cout << d2[k][i] <<","; 348 | } 349 | cout << d2[4][i] << ";" << endl; 350 | } 351 | 352 | 353 | return 0; 354 | } 355 | 356 | 357 | 358 | 359 | 360 | 361 | -------------------------------------------------------------------------------- /Test_HELR.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // check the memory usage 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | #include "../src/CZZ.h" 21 | #include "../src/Params.h" 22 | #include "../src/PubKey.h" 23 | #include "../src/Scheme.h" 24 | #include "../src/SchemeAlgo.h" 25 | #include "../src/SecKey.h" 26 | #include "../src/TestScheme.h" 27 | #include "../src/TimeUtils.h" 28 | #include "../src/Ring2Utils.h" 29 | #include "../src/StringUtils.h" 30 | #include "../src/EvaluatorUtils.h" 31 | 32 | #include "Database.h" 33 | #include "LRtest.h" 34 | #include "HELR.h" 35 | 36 | 37 | using namespace NTL; 38 | using namespace std; 39 | 40 | 41 | 42 | int main(int Argc, char** Argv) { 43 | 44 | 45 | if(Argc != 3){ 46 | cout << "-------------------------------------------------------------" << endl; 47 | cerr << "Enter the File and degree of approximation \t" << "(e.g. $test edin.txt 3) \n "; 48 | } 49 | 50 | char* filename = Argv[1]; 51 | int polydeg = atoi(Argv[2]); // degree of approximation polynomial 52 | 53 | 54 | dMat zData; 55 | dMat* zTest = new dMat[5]; 56 | dMat* zTrain = new dMat[5]; 57 | 58 | 59 | int nLine= readData(zData, filename); 60 | 61 | cout << "Sample the learning and test data ..." << endl; 62 | cvRandomSamplingData(zTrain, zTest, zData, filename); 63 | 64 | 65 | //---------------------------------------------------------------- 66 | // Parameters for Logistic regression 67 | //---------------------------------------------------------------- 68 | 69 | long logN= 17; 70 | long logp= 28; 71 | long logl= 10; 72 | long logq, cBit1, cBit2; 73 | int max_iter; 74 | 75 | struct LRpar LRparams; 76 | ReadLRparams(LRparams, max_iter, zTrain[0], polydeg, logp); 77 | 78 | SetNumThreads(LRparams.dim1); 79 | //SetNumThreads(4); 80 | 81 | switch(polydeg){ 82 | case 3: 83 | cBit1= (LRparams.logn - LRparams.log2polyscale); // 1st iteration 84 | cBit2 = (3*logp+ LRparams. logn - LRparams.log2polyscale); // 2nd~ iteration 85 | logq = cBit1 + (LRparams.max_iter-1)*(cBit2)+ logp + logl; // max-bitlength we need 86 | break; 87 | 88 | case 7: 89 | cBit1= (LRparams.logn - LRparams.log2polyscale); // 1st iteration 90 | cBit2= (4*logp+ LRparams.logn - LRparams.log2polyscale); 91 | logq= cBit1 + (LRparams.max_iter-1)*(cBit2)+ logp + logl; 92 | break; 93 | } 94 | 95 | 96 | 97 | 98 | cout << "Data dimension with dummy vectors: " << LRparams.dim1 << ", Number of lines: " << nLine << endl; 99 | 100 | cout << "-------------------------------------------------------------" << endl; 101 | cout << "Key Generation ... (logN,logp,logq, nslots)= (" ; 102 | cout << logN << "," << logp << "," << logq << "," << LRparams.nslots << ")" < 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include // check the memory usage 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | 20 | #include "../src/CZZ.h" 21 | #include "../src/Params.h" 22 | #include "../src/PubKey.h" 23 | #include "../src/Scheme.h" 24 | #include "../src/SchemeAlgo.h" 25 | #include "../src/SecKey.h" 26 | #include "../src/TestScheme.h" 27 | #include "../src/TimeUtils.h" 28 | #include "../src/Ring2Utils.h" 29 | #include "../src/StringUtils.h" 30 | #include "../src/EvaluatorUtils.h" 31 | 32 | #include "Database.h" 33 | #include "LRtest.h" 34 | #include "HELR.h" 35 | 36 | 37 | using namespace NTL; 38 | using namespace std; 39 | 40 | 41 | 42 | int main(int Argc, char** Argv) { 43 | 44 | 45 | if(Argc != 2){ 46 | cout << "-------------------------------------------------------------" << endl; 47 | cerr << "Enter the File and degree of approximation \t" << "(e.g. $test edin.txt 3) \n "; 48 | } 49 | 50 | char* filename = Argv[1]; 51 | 52 | 53 | 54 | dMat zData; 55 | dMat* zTest = new dMat[5]; 56 | dMat* zTrain = new dMat[5]; 57 | 58 | 59 | int nLine= readData(zData, filename); 60 | 61 | cout << "Sample the learning and test data ..." << endl; 62 | cvRandomSamplingData(zTrain, zTest, zData, filename); 63 | 64 | 65 | //---------------------------------------------------------------- 66 | // Parameters for Logistic regression 67 | //---------------------------------------------------------------- 68 | 69 | long logN= 11; 70 | long logp= 28; 71 | long logl= 10; 72 | long logq, cBit1, cBit2; 73 | int max_iter; 74 | long dim ; 75 | 76 | 77 | dMat mtheta3_list; 78 | dMat mtheta7_list; 79 | dMat mtheta_sig_list; 80 | 81 | ofstream fout; 82 | fout.open("beta.txt"); 83 | 84 | 85 | for(int k = 0; k < 5; ++k){ 86 | 87 | 88 | cout << "-------------------------------------------------------------" << endl; 89 | cout << "HELR_3 " << endl; 90 | 91 | int polydeg = 3; // degree of approximation polynomial 92 | 93 | struct LRpar LRparams; 94 | ReadLRparams(LRparams, max_iter, zTrain[0], polydeg, logp); 95 | 96 | dVec mtheta3(LRparams.dim1, 0.0); 97 | for(int i= 0; i< LRparams.max_iter; i++){ 98 | LR_poly(mtheta3, zTrain[k], LRparams); 99 | } 100 | 101 | for(int i= 0; i< LRparams.dim1; i++) 102 | cout << "[" << mtheta3[i] << "] " ; 103 | cout << endl; 104 | 105 | getAUC(mtheta3, zTest[k]); 106 | mtheta3_list.push_back(mtheta3); 107 | 108 | 109 | cout << "-------------------------------------------------------------" << endl; 110 | cout << "HELR_7 " << endl; 111 | 112 | polydeg = 7; // degree of approximation polynomial 113 | 114 | struct LRpar LRparams7; 115 | ReadLRparams(LRparams7, max_iter, zTrain[0], polydeg, logp); 116 | 117 | dVec mtheta7(LRparams7.dim1, 0.0); 118 | for(int i= 0; i< LRparams7.max_iter; i++){ 119 | LR_poly(mtheta7, zTrain[k], LRparams7); 120 | } 121 | 122 | for(int i= 0; i< LRparams7.dim1; i++) 123 | cout << "[" << mtheta7[i] << "] " ; 124 | cout << endl; 125 | 126 | getAUC(mtheta7, zTest[k]); 127 | mtheta7_list.push_back(mtheta7); 128 | 129 | dim = LRparams7.dim1; 130 | 131 | 132 | cout << "-------------------------------------------------------------" << endl; 133 | cout << "sigmoid LR " << endl; 134 | dVec mtheta_sig(LRparams.dim1, 0.0); 135 | 136 | for(int i= 0; i< LRparams.max_iter; i++){ 137 | LR_sigmoid(mtheta_sig, zTrain[k], LRparams); 138 | } 139 | 140 | for(int i= 0; i< LRparams.dim1; i++) 141 | cout << "[" << mtheta_sig[i] << "] " ; 142 | cout << endl; 143 | 144 | getAUC(mtheta_sig, zTest[k]); 145 | mtheta_sig_list.push_back(mtheta_sig); 146 | 147 | 148 | cout << "-------------------------------------------------------------" << endl; 149 | cout << "MSE (HELR/non-HELR): " << getMSE(mtheta3, mtheta_sig) << endl; 150 | cout << "MSE (HELR/non-HELR): " << getMSE(mtheta7, mtheta_sig) << endl; 151 | 152 | } 153 | 154 | 155 | //! write the beta results in the text file 156 | //fout << "-------------------------------------------------------------" << endl; 157 | //fout << "HELR_3" << endl; 158 | for(int i = 0; i < dim; ++i){ 159 | for(int k = 0; k < 4; ++k){ 160 | fout << mtheta3_list[k][i] << "," ; 161 | } 162 | fout << mtheta3_list[4][i] << ";" << endl; 163 | } 164 | 165 | 166 | //fout << "-------------------------------------------------------------" << endl; 167 | //fout << "HELR_7" << endl; 168 | for(int i = 0; i < dim; ++i){ 169 | for(int k = 0; k < 4; ++k){ 170 | fout << mtheta7_list[k][i] << "," ; 171 | } 172 | fout << mtheta7_list[4][i] << ";" << endl; 173 | } 174 | 175 | 176 | //fout << "-------------------------------------------------------------" << endl; 177 | //fout << "LR" << endl; 178 | for(int i = 0; i < dim; ++i){ 179 | for(int k = 0; k < 4; ++k){ 180 | fout << mtheta_sig_list[k][i] << "," ; 181 | } 182 | fout << mtheta_sig_list[4][i] << ";" << endl; 183 | } 184 | 185 | fout.close(); 186 | 187 | 188 | 189 | delete[] zTest; 190 | delete[] zTrain; 191 | 192 | return 0; 193 | } 194 | 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /data/lbw.txt: -------------------------------------------------------------------------------- 1 | 28 120 0 0 1 1 0 1 0 0 2 | 29 130 1 0 0 0 0 1 2 0 3 | 34 187 0 1 1 0 1 0 0 0 4 | 25 105 0 0 0 1 1 0 0 0 5 | 25 85 0 0 0 0 0 1 0 0 6 | 27 150 0 0 0 0 0 0 0 0 7 | 23 97 0 0 0 0 0 1 1 0 8 | 24 128 0 1 0 1 0 0 1 0 9 | 24 132 0 0 0 0 1 0 0 0 10 | 21 165 1 0 1 0 1 0 1 0 11 | 32 105 1 0 1 0 0 0 0 0 12 | 19 91 1 0 1 2 0 1 0 0 13 | 25 115 0 0 0 0 0 0 0 0 14 | 16 130 0 0 0 0 0 0 1 0 15 | 25 92 1 0 1 0 0 0 0 0 16 | 20 150 1 0 1 0 0 0 2 0 17 | 21 200 0 1 0 0 0 1 2 0 18 | 24 155 1 0 1 1 0 0 0 0 19 | 21 103 0 0 0 0 0 0 0 0 20 | 20 125 0 0 0 0 0 1 0 0 21 | 25 89 0 0 0 2 0 0 1 0 22 | 19 102 1 0 0 0 0 0 2 0 23 | 19 112 1 0 1 0 0 1 0 0 24 | 26 117 1 0 1 1 0 0 0 0 25 | 24 138 1 0 0 0 0 0 0 0 26 | 17 130 0 0 1 1 0 1 0 0 27 | 20 120 0 1 1 0 0 0 3 0 28 | 22 130 1 0 1 1 0 1 1 0 29 | 27 130 0 1 0 0 0 1 0 0 30 | 20 80 0 0 1 0 0 1 0 0 31 | 17 110 1 0 1 0 0 0 0 0 32 | 25 105 0 0 0 1 0 0 1 0 33 | 20 109 0 0 0 0 0 0 0 0 34 | 18 148 0 0 0 0 0 0 0 0 35 | 18 110 0 1 1 1 0 0 0 0 36 | 20 121 1 0 1 1 0 1 0 0 37 | 21 100 0 0 0 1 0 0 4 0 38 | 26 96 0 0 0 0 0 0 0 0 39 | 31 102 1 0 1 1 0 0 1 0 40 | 15 110 1 0 0 0 0 0 0 0 41 | 23 187 0 1 1 0 0 0 1 0 42 | 20 122 0 1 1 0 0 0 0 0 43 | 24 105 0 1 1 0 0 0 0 0 44 | 15 115 0 0 0 0 0 1 0 0 45 | 23 120 0 0 0 0 0 0 0 0 46 | 30 142 1 0 1 1 0 0 0 0 47 | 22 130 1 0 1 0 0 0 1 0 48 | 17 120 1 0 1 0 0 0 3 0 49 | 23 110 1 0 1 1 0 0 0 0 50 | 17 120 0 1 0 0 0 0 2 0 51 | 26 154 0 0 0 1 1 0 1 0 52 | 20 105 0 0 0 0 0 0 3 0 53 | 26 190 1 0 1 0 0 0 0 0 54 | 14 101 0 0 1 1 0 0 0 0 55 | 28 95 1 0 1 0 0 0 2 0 56 | 14 100 0 0 0 0 0 0 2 0 57 | 23 94 0 0 1 0 0 0 0 0 58 | 17 142 0 1 0 0 1 0 0 0 59 | 21 130 1 0 1 0 1 0 3 0 60 | 19 182 0 1 0 0 0 1 0 1 61 | 33 155 0 0 0 0 0 0 3 1 62 | 20 105 1 0 1 0 0 0 1 1 63 | 21 108 1 0 1 0 0 1 2 1 64 | 18 107 1 0 1 0 0 1 0 1 65 | 21 124 0 0 0 0 0 0 0 1 66 | 22 118 1 0 0 0 0 0 1 1 67 | 17 103 0 0 0 0 0 0 1 1 68 | 29 123 1 0 1 0 0 0 1 1 69 | 26 113 1 0 1 0 0 0 0 1 70 | 19 95 0 0 0 0 0 0 0 1 71 | 19 150 0 0 0 0 0 0 1 1 72 | 22 95 0 0 0 0 1 0 0 1 73 | 30 107 0 0 0 1 0 1 2 1 74 | 18 100 1 0 1 0 0 0 0 1 75 | 18 100 1 0 1 0 0 0 0 1 76 | 15 98 0 1 0 0 0 0 0 1 77 | 25 118 1 0 1 0 0 0 3 1 78 | 20 120 0 0 0 0 0 1 0 1 79 | 28 120 1 0 1 0 0 0 1 1 80 | 32 121 0 0 0 0 0 0 2 1 81 | 31 100 1 0 0 0 0 1 3 1 82 | 36 202 1 0 0 0 0 0 1 1 83 | 28 120 0 0 0 0 0 0 0 1 84 | 25 120 0 0 0 0 0 1 2 1 85 | 28 167 1 0 0 0 0 0 0 1 86 | 17 122 1 0 1 0 0 0 0 1 87 | 29 150 1 0 0 0 0 0 2 1 88 | 26 168 0 1 1 0 0 0 0 1 89 | 17 113 0 1 0 0 0 0 1 1 90 | 17 113 0 1 0 0 0 0 1 1 91 | 24 90 1 0 1 1 0 0 1 1 92 | 35 121 0 1 1 1 0 0 1 1 93 | 25 155 1 0 0 0 0 0 1 1 94 | 25 125 0 1 0 0 0 0 0 1 95 | 29 140 1 0 1 0 0 0 2 1 96 | 19 138 1 0 1 0 0 0 2 1 97 | 27 124 1 0 1 0 0 0 0 1 98 | 31 215 1 0 1 0 0 0 2 1 99 | 33 109 1 0 1 0 0 0 1 1 100 | 21 185 0 1 1 0 0 0 2 1 101 | 19 189 1 0 0 0 0 0 2 1 102 | 23 130 0 1 0 0 0 0 1 1 103 | 21 160 1 0 0 0 0 0 0 1 104 | 18 90 1 0 1 0 0 1 0 1 105 | 18 90 1 0 1 0 0 1 0 1 106 | 32 132 1 0 0 0 0 0 4 1 107 | 19 132 0 0 0 0 0 0 0 1 108 | 24 115 1 0 0 0 0 0 2 1 109 | 22 85 0 0 1 0 0 0 0 1 110 | 22 120 1 0 0 0 1 0 1 1 111 | 23 128 0 0 0 0 0 0 0 1 112 | 22 130 1 0 1 0 0 0 0 1 113 | 30 95 1 0 1 0 0 0 2 1 114 | 19 115 0 0 0 0 0 0 0 1 115 | 16 110 0 0 0 0 0 0 0 1 116 | 21 110 0 0 1 0 0 1 0 1 117 | 30 153 0 0 0 0 0 0 0 1 118 | 20 103 0 0 0 0 0 0 0 1 119 | 17 119 0 0 0 0 0 0 0 1 120 | 17 119 0 0 0 0 0 0 0 1 121 | 23 119 0 0 0 0 0 0 2 1 122 | 24 110 0 0 0 0 0 0 0 1 123 | 28 140 1 0 0 0 0 0 0 1 124 | 26 133 0 0 1 2 0 0 0 1 125 | 20 169 0 0 0 1 0 1 1 1 126 | 24 115 0 0 0 0 0 0 2 1 127 | 28 250 0 0 1 0 0 0 6 1 128 | 20 141 1 0 0 2 0 1 1 1 129 | 22 158 0 1 0 1 0 0 2 1 130 | 22 112 1 0 1 2 0 0 0 1 131 | 31 150 0 0 1 0 0 0 2 1 132 | 23 115 0 0 1 0 0 0 1 1 133 | 16 112 0 1 0 0 0 0 0 1 134 | 16 135 1 0 1 0 0 0 0 1 135 | 18 229 0 1 0 0 0 0 0 1 136 | 25 140 1 0 0 0 0 0 1 1 137 | 32 134 1 0 1 1 0 0 4 1 138 | 20 121 0 1 1 0 0 0 0 1 139 | 23 190 1 0 0 0 0 0 0 1 140 | 22 131 1 0 0 0 0 0 1 1 141 | 32 170 1 0 0 0 0 0 0 1 142 | 30 110 0 0 0 0 0 0 0 1 143 | 20 127 0 0 0 0 0 0 0 1 144 | 23 123 0 0 0 0 0 0 0 1 145 | 17 120 0 0 1 0 0 0 0 1 146 | 19 105 0 0 0 0 0 0 0 1 147 | 23 130 1 0 0 0 0 0 0 1 148 | 36 175 1 0 0 0 0 0 0 1 149 | 22 125 1 0 0 0 0 0 1 1 150 | 24 133 1 0 0 0 0 0 0 1 151 | 21 134 0 0 0 0 0 0 2 1 152 | 19 235 1 0 1 0 1 0 0 1 153 | 25 95 1 0 1 3 0 1 0 1 154 | 16 135 1 0 1 0 0 0 0 1 155 | 29 135 1 0 0 0 0 0 1 1 156 | 29 154 1 0 0 0 0 0 1 1 157 | 19 147 1 0 1 0 0 0 0 1 158 | 19 147 1 0 1 0 0 0 0 1 159 | 30 137 1 0 0 0 0 0 1 1 160 | 24 110 1 0 0 0 0 0 1 1 161 | 19 184 1 0 1 0 1 0 0 1 162 | 24 110 0 0 0 1 0 0 0 1 163 | 23 110 1 0 0 0 0 0 1 1 164 | 20 120 0 0 0 0 0 0 0 1 165 | 25 241 0 1 0 0 1 0 0 1 166 | 30 112 1 0 0 0 0 0 1 1 167 | 22 169 1 0 0 0 0 0 0 1 168 | 18 120 1 0 1 0 0 0 2 1 169 | 16 170 0 1 0 0 0 0 4 1 170 | 32 186 1 0 0 0 0 0 2 1 171 | 18 120 0 0 0 0 0 0 1 1 172 | 29 130 1 0 1 0 0 0 2 1 173 | 33 117 1 0 0 0 0 1 1 1 174 | 20 170 1 0 1 0 0 0 0 1 175 | 28 134 0 0 0 0 0 0 1 1 176 | 14 135 1 0 0 0 0 0 0 1 177 | 28 130 0 0 0 0 0 0 0 1 178 | 25 120 1 0 0 0 0 0 2 1 179 | 16 95 0 0 0 0 0 0 1 1 180 | 20 158 1 0 0 0 0 0 1 1 181 | 26 160 0 0 0 0 0 0 0 1 182 | 21 115 1 0 0 0 0 0 1 1 183 | 22 129 1 0 0 0 0 0 0 1 184 | 25 130 1 0 0 0 0 0 2 1 185 | 31 120 1 0 0 0 0 0 2 1 186 | 35 170 1 0 0 1 0 0 1 1 187 | 19 120 1 0 1 0 0 0 0 1 188 | 24 116 1 0 0 0 0 0 1 1 189 | 45 123 1 0 0 0 0 0 1 1 190 | -------------------------------------------------------------------------------- /data/pcs.txt: -------------------------------------------------------------------------------- 1 | 65 1 0 1 0 0 1.4 0 6 0 2 | 72 1 0 0 1 1 6.7 0 7 0 3 | 70 1 1 0 0 1 4.9 0 6 0 4 | 76 0 0 1 0 0 51.2 20 7 0 5 | 69 1 1 0 0 0 12.3 55.9 6 0 6 | 71 1 0 0 1 1 3.3 0 8 1 7 | 68 0 0 0 0 1 31.9 0 7 0 8 | 61 0 0 0 0 1 66.7 27.2 7 0 9 | 69 1 1 0 0 0 3.9 24 7 0 10 | 68 0 1 0 0 1 13 0 6 0 11 | 68 0 0 0 0 1 4 0 7 1 12 | 72 1 0 1 0 1 21.2 0 7 1 13 | 72 1 0 0 0 1 22.7 0 9 1 14 | 65 1 0 0 0 1 39 0 7 1 15 | 75 1 1 0 0 0 7.5 0 5 0 16 | 73 1 0 1 0 0 2.6 0 5 0 17 | 75 0 1 0 0 0 2.5 0 5 0 18 | 70 1 0 1 0 0 2.6 11.8 5 0 19 | 54 1 1 0 0 1 2.8 0 6 0 20 | 67 0 0 0 1 1 8.6 25.5 7 1 21 | 58 1 0 1 0 0 3.1 0 7 1 22 | 70 0 0 0 0 0 67.1 0 7 1 23 | 74 1 0 0 1 0 12.7 27.5 7 1 24 | 73 1 1 0 0 0 12.3 47.3 7 0 25 | 77 1 1 0 0 0 61.1 58 7 1 26 | 77 1 1 0 0 0 8.8 0 5 0 27 | 67 1 0 1 0 0 2.8 25.6 7 0 28 | 73 1 0 0 1 0 2.9 14.1 5 0 29 | 64 1 0 0 1 0 5.6 34.1 5 0 30 | 58 1 0 0 0 0 5.6 22.8 6 0 31 | 54 1 0 0 1 0 8.4 18.3 6 1 32 | 72 1 0 1 0 0 6.5 22.5 7 0 33 | 77 1 0 0 0 0 11 0 8 0 34 | 60 1 0 0 1 1 9.5 0 7 1 35 | 65 1 0 1 0 0 11.1 17.7 6 0 36 | 71 1 0 1 0 0 7.3 20 7 0 37 | 54 1 0 1 0 0 1 0 6 0 38 | 78 1 1 0 0 1 27.2 0 8 1 39 | 63 1 0 1 0 0 35.1 18.7 7 1 40 | 73 1 0 0 1 0 4.5 26.4 7 1 41 | 66 1 0 0 1 0 7.9 20.8 7 1 42 | 71 1 1 0 0 0 2 0 6 0 43 | 71 1 0 1 0 0 7.5 0 6 1 44 | 72 1 0 1 0 0 5.3 0 7 0 45 | 65 0 0 0 1 0 83.7 32 9 1 46 | 75 0 0 0 1 1 33 15.2 8 1 47 | 69 0 0 1 0 0 6.7 59.8 6 0 48 | 68 1 0 1 0 0 12.3 16.3 8 0 49 | 70 1 0 1 0 0 0.4 17.1 5 0 50 | 67 1 0 1 0 0 5.8 14.5 6 0 51 | 76 1 1 0 0 0 7.6 3.7 6 0 52 | 72 1 0 0 0 1 124 38.6 8 1 53 | 66 1 0 0 1 0 8.8 39.9 6 0 54 | 61 1 0 0 1 0 67.6 0 7 1 55 | 70 1 0 0 1 0 13.9 13 7 0 56 | 57 1 0 0 1 0 7.4 18.3 7 1 57 | 74 1 0 1 0 0 23.1 5.9 7 0 58 | 70 1 0 0 1 0 19.3 0 7 1 59 | 60 1 0 0 1 0 3 16.5 6 0 60 | 58 1 0 0 1 0 3.7 29.9 6 0 61 | 59 1 0 1 0 0 0.7 96 5 0 62 | 71 1 0 1 0 0 6 31 6 1 63 | 76 1 0 1 0 0 9.5 14.4 7 0 64 | 66 1 0 0 1 0 2.6 0 7 0 65 | 59 1 0 0 0 0 30.7 0 7 1 66 | 65 1 0 1 0 0 10.8 0 7 1 67 | 54 1 0 1 0 0 10.5 0 6 0 68 | 78 1 1 0 0 0 6.5 0 7 0 69 | 65 1 0 1 0 0 1.3 6.8 5 0 70 | 68 0 0 0 1 0 9.6 32 6 1 71 | 68 1 0 1 0 0 0.3 0 6 0 72 | 71 1 0 0 1 0 8.3 17.5 5 0 73 | 60 1 0 0 1 0 3.2 0 7 0 74 | 65 1 0 0 1 0 6.9 23.3 5 0 75 | 68 1 1 0 0 0 11 0 7 0 76 | 54 0 1 0 0 0 64.3 0 7 0 77 | 73 1 0 0 1 0 1.6 17.1 6 0 78 | 62 1 0 1 0 0 1.9 0 6 1 79 | 60 1 0 1 0 0 7.9 0 5 0 80 | 66 1 1 0 0 0 25.7 39.1 9 1 81 | 76 1 0 0 1 0 4.9 0 6 0 82 | 62 1 1 0 0 0 22.1 0 7 0 83 | 74 1 0 1 0 0 31.5 0 7 0 84 | 75 1 0 1 0 0 11 35 7 0 85 | 75 1 1 0 0 0 9.9 15.4 7 0 86 | 75 1 0 0 1 0 3.7 0 6 1 87 | 68 1 0 0 0 1 51.3 47 9 1 88 | 71 1 0 1 0 1 89 24 8 1 89 | 68 1 0 0 0 0 17.1 35 9 0 90 | 70 1 0 0 1 0 12.3 10.3 7 0 91 | 68 1 1 0 0 0 4.4 39 6 0 92 | 66 1 1 0 0 0 8 0 5 0 93 | 70 1 0 0 1 0 15 0 7 1 94 | 65 1 0 0 1 1 35.8 29 9 1 95 | 71 1 1 0 0 0 13.4 44.2 7 0 96 | 75 1 1 0 0 0 16 18.7 7 1 97 | 70 1 0 0 1 0 11.2 0 7 0 98 | 58 1 1 0 0 0 7 0 6 0 99 | 64 1 1 0 0 0 29.1 0 6 0 100 | 66 1 0 0 1 0 9.5 28.1 7 1 101 | 64 1 0 1 0 0 6.1 0 6 0 102 | 72 1 0 0 1 0 6.3 34 7 1 103 | 62 1 1 0 0 0 2.8 44 6 0 104 | 75 1 0 0 1 0 25.7 87.6 5 0 105 | 68 1 0 1 0 0 5.7 0 7 1 106 | 56 1 0 0 1 1 2.7 37 6 0 107 | 69 1 1 0 0 0 6 0 7 1 108 | 67 1 0 0 1 0 40.4 0 7 0 109 | 66 1 0 0 1 0 13.2 23.6 6 0 110 | 69 1 0 0 1 0 15.2 0 7 1 111 | 74 1 1 0 0 0 8.8 0 7 0 112 | 79 1 0 0 1 0 7.8 0 6 1 113 | 65 1 0 0 1 0 6.9 4.6 7 1 114 | 71 1 0 1 0 0 17.2 65.6 8 0 115 | 57 1 0 0 1 1 64 0 8 1 116 | 47 1 1 0 0 0 28 0 9 1 117 | 66 0 0 0 0 0 45.3 0 6 1 118 | 64 1 0 1 0 0 32.8 22.6 6 0 119 | 74 1 0 1 0 0 3.2 44.8 6 0 120 | 56 1 0 1 0 0 5.6 20.2 8 0 121 | 77 1 1 0 0 0 16.4 0 7 1 122 | 66 1 1 0 0 0 6.8 54.5 5 0 123 | 67 0 0 0 0 0 25.2 21.7 7 0 124 | 70 1 0 1 0 0 12.5 0 9 1 125 | 70 1 0 0 0 0 3.6 21.7 7 1 126 | 65 1 0 1 0 0 11 16 6 0 127 | 63 1 0 1 0 0 8.1 20.3 6 0 128 | 59 1 0 1 0 0 2.3 0 5 0 129 | 75 1 0 1 0 0 1.4 0 6 0 130 | 70 1 1 0 0 0 6.7 29.4 6 0 131 | 73 1 1 0 0 0 1 0 5 0 132 | 72 1 0 1 0 0 4.5 29.9 8 0 133 | 67 1 0 1 0 0 6.2 0 5 0 134 | 60 1 0 0 0 0 4.6 26.3 7 1 135 | 66 1 1 0 0 0 8.9 43.5 7 0 136 | 63 1 0 1 0 0 8.2 17.8 6 0 137 | 68 1 0 1 0 0 5 0 6 0 138 | 66 1 0 0 0 0 91.9 0 8 1 139 | 69 1 0 0 0 1 94 0 7 1 140 | 67 1 1 0 0 0 13.4 0 7 0 141 | 72 1 1 0 0 0 9.1 0 6 0 142 | 56 0 0 1 0 0 41.9 0 8 1 143 | 74 1 0 1 0 0 21.6 52 7 0 144 | 66 1 0 0 0 1 37.7 0 8 1 145 | 61 1 1 0 0 0 9.4 34.6 6 0 146 | 62 0 1 0 0 0 9.1 33.1 6 0 147 | 68 1 0 0 0 1 55.6 0 8 1 148 | 63 1 0 0 1 0 3.6 38 6 0 149 | 55 1 0 0 0 0 6.2 29.2 6 0 150 | 70 1 0 1 0 0 6.3 0 7 0 151 | 65 0 0 1 0 0 4.6 0 5 0 152 | 66 1 1 0 0 0 4.9 16.1 6 1 153 | 68 1 1 0 0 0 2.6 12.8 6 0 154 | 55 1 0 1 0 0 16.3 21.2 7 1 155 | 55 1 0 1 0 0 4.39 0 6 1 156 | 76 1 0 1 0 0 8.9 87.3 5 0 157 | 58 1 0 1 0 0 21.2 26.8 7 1 158 | 75 1 0 1 0 0 7.9 0 7 1 159 | 70 1 1 0 0 0 44.4 0 6 1 160 | 59 1 0 1 0 0 16.1 23 7 1 161 | 63 0 0 1 0 0 26 21.3 7 1 162 | 62 1 0 0 1 0 8.8 0 6 1 163 | 58 1 0 1 0 0 20.6 0 7 1 164 | 62 1 0 0 1 0 26.7 0 6 1 165 | 69 1 0 0 1 0 3.5 0 5 0 166 | 62 1 0 1 0 1 14.8 22.2 7 1 167 | 70 1 0 1 0 0 11.9 35.5 6 1 168 | 76 1 0 0 0 0 5.7 40 6 0 169 | 64 1 0 0 0 0 2.4 0 6 1 170 | 73 1 0 1 0 0 42.8 0 8 1 171 | 74 1 0 0 1 0 7 0 6 1 172 | 71 1 0 0 1 0 3.3 0 6 1 173 | 60 1 0 0 0 0 7.3 0 7 1 174 | 62 1 0 1 0 0 17.2 0 7 1 175 | 71 1 0 1 0 0 3.8 19 6 0 176 | 67 1 0 0 1 0 5.7 15.4 6 0 177 | 68 1 0 0 0 0 31.6 18 7 1 178 | 69 1 1 0 0 0 5.4 37.3 6 0 179 | 67 1 1 0 0 0 15 35.1 7 0 180 | 70 1 0 1 0 0 22 0 8 1 181 | 68 1 0 0 1 1 23.4 0 7 1 182 | 70 1 1 0 0 0 51.9 20.1 8 1 183 | 70 1 1 0 0 0 20.4 35 7 1 184 | 60 1 0 1 0 0 18.7 23.4 7 1 185 | 61 1 0 0 1 0 12.7 33.4 7 1 186 | 57 1 0 0 1 0 20.1 30.3 8 1 187 | 68 1 1 0 0 0 85.4 10 7 1 188 | 75 0 0 1 0 0 9.3 23.2 6 0 189 | 69 1 0 0 1 1 8 31.2 6 1 190 | 64 1 0 0 0 0 7.5 11.4 6 0 191 | 62 1 0 0 1 0 5 0 6 0 192 | 61 1 0 0 0 0 61.6 21.2 6 0 193 | 59 1 1 0 0 0 8.5 38.3 5 0 194 | 71 1 1 0 0 0 10 15.09 6 0 195 | 72 1 0 1 0 0 12.7 0 6 1 196 | 73 1 0 0 1 0 12.3 30.1 8 1 197 | 66 0 0 0 0 0 11 0 5 0 198 | 69 1 0 0 1 0 17.7 21 5 1 199 | 69 1 0 1 0 0 3.9 0 6 0 200 | 70 1 0 0 1 0 5 21.6 7 0 201 | 57 1 1 0 0 0 10.2 0 6 0 202 | 68 1 0 0 1 0 19.2 0 8 1 203 | 61 1 0 1 0 0 2.9 0 6 1 204 | 71 1 0 1 0 0 1.7 0 6 0 205 | 62 1 0 1 0 0 9 0 6 0 206 | 76 1 0 0 0 1 11.7 28.5 7 1 207 | 65 1 1 0 0 0 8 54 6 0 208 | 53 1 0 1 0 0 9.9 27 5 0 209 | 65 1 0 1 0 0 14.7 15 7 0 210 | 57 1 0 0 1 0 1.5 0 5 0 211 | 62 1 0 1 0 0 13.7 33.4 5 0 212 | 68 1 0 1 0 0 8.6 0 8 1 213 | 66 1 0 0 0 0 45.8 0 8 1 214 | 50 1 0 0 1 0 1.8 8.7 5 0 215 | 67 1 0 1 0 0 8 20.7 7 0 216 | 56 1 1 0 0 0 5 29.6 6 0 217 | 69 1 0 0 0 0 53.9 0 6 1 218 | 68 1 0 0 0 1 18.8 27.3 9 1 219 | 68 1 0 0 1 0 2.4 20.8 6 0 220 | 74 1 0 1 0 0 1.2 21.6 6 0 221 | 51 1 0 1 0 0 7.4 0 6 1 222 | 69 1 0 0 1 0 38 32.8 7 1 223 | 65 1 1 0 0 0 9.4 38.4 5 0 224 | 58 1 0 0 1 0 3.1 0 7 1 225 | 71 1 1 0 0 0 1.29 0 7 0 226 | 68 1 0 1 0 0 12.7 0 7 0 227 | 56 1 1 0 0 0 7.3 15.7 6 0 228 | 59 1 0 0 0 0 3.8 13.8 6 0 229 | 67 1 1 0 0 0 10.2 0 7 0 230 | 54 1 0 0 1 0 7 29 6 1 231 | 69 0 0 0 1 0 24.1 24.5 7 1 232 | 54 1 0 0 1 0 9.4 36.8 6 1 233 | 68 1 0 0 1 1 25 20 7 1 234 | 59 0 0 0 0 0 126 20.3 8 1 235 | 53 0 0 1 0 0 16.8 16.9 7 1 236 | 68 1 0 1 0 0 8.2 38.2 6 1 237 | 73 1 0 1 0 0 3.1 21.9 6 0 238 | 66 1 0 1 0 0 11 36.6 6 0 239 | 71 1 0 0 0 0 4.9 15.2 6 0 240 | 69 0 1 0 0 0 15.6 17.9 6 0 241 | 68 1 1 0 0 0 6.7 16.7 6 1 242 | 74 1 0 0 1 0 8.7 20.4 6 1 243 | 58 0 0 0 0 1 20.7 0 8 1 244 | 67 1 1 0 0 0 2.1 0 6 0 245 | 70 1 1 0 0 0 8 0 7 0 246 | 70 0 0 0 0 0 13.2 25.6 7 1 247 | 66 1 1 0 0 0 2.3 0 5 0 248 | 57 0 1 0 0 0 63.3 73.4 7 1 249 | 62 1 1 0 0 0 13.7 0 5 0 250 | 50 1 0 0 1 0 13.2 0 7 0 251 | 61 1 0 1 0 1 8.4 0 6 0 252 | 43 0 0 1 0 0 3.8 21 6 0 253 | 74 1 0 1 0 0 17.7 0 7 1 254 | 78 1 0 1 0 0 5.9 32.5 6 0 255 | 65 1 0 1 0 0 22 60 7 0 256 | 57 1 0 1 0 1 15.1 0 9 1 257 | 71 1 0 0 0 1 25.1 14.9 7 0 258 | 70 1 1 0 0 0 24.8 16.1 6 0 259 | 55 1 0 1 0 0 6.7 0 6 1 260 | 71 1 1 0 0 0 11.3 32 6 0 261 | 63 1 0 1 0 0 17.5 31.2 5 0 262 | 62 1 0 1 0 0 8.3 0 6 1 263 | 71 1 0 1 0 0 4.8 0 7 1 264 | 59 1 0 1 0 0 1.7 17.2 6 0 265 | 64 1 0 0 1 0 7.5 13.7 7 1 266 | 67 1 0 0 1 0 20 17.5 5 0 267 | 65 1 0 0 1 0 3.4 14.3 7 1 268 | 62 1 0 1 0 0 10.6 42.4 5 0 269 | 65 1 0 0 1 0 18 19.3 7 1 270 | 71 1 0 0 0 0 18.7 21 5 1 271 | 61 1 1 0 0 0 5.4 27.5 6 0 272 | 59 1 1 0 0 0 4.6 29.6 5 0 273 | 60 1 0 1 0 0 28.5 0 9 1 274 | 59 1 1 0 0 0 11.2 0 6 1 275 | 70 1 1 0 0 0 8.9 24 6 1 276 | 70 1 0 1 0 0 1.7 33.8 6 1 277 | 59 1 0 1 0 0 1.4 0 6 0 278 | 70 1 0 1 0 0 8.4 21.8 5 1 279 | 54 1 0 0 1 0 8.6 0 5 0 280 | 64 1 0 1 0 0 10.9 24.8 6 0 281 | 62 1 0 0 1 0 20.1 0 7 0 282 | 65 1 1 0 0 0 7.3 0 0 0 283 | 66 0 0 1 0 0 8 0 5 0 284 | 71 1 1 0 0 0 2 0 5 0 285 | 61 1 0 1 0 0 13.1 0 7 0 286 | 58 1 0 0 1 0 5.4 55 6 1 287 | 76 1 0 1 0 0 4.1 0 8 1 288 | 53 1 0 0 1 0 6.5 0 7 1 289 | 65 1 1 0 0 0 6.1 28.9 7 0 290 | 69 1 1 0 0 0 6.2 26.3 5 0 291 | 64 1 0 0 1 0 3.8 19.1 5 0 292 | 61 1 1 0 0 0 6.8 24.6 5 1 293 | 62 1 0 1 0 0 9.5 26.6 6 0 294 | 63 1 0 0 0 0 20.4 0 7 1 295 | 61 1 0 0 1 0 4.8 0 6 0 296 | 63 1 0 0 0 0 9.8 17.5 8 1 297 | 73 1 0 0 0 1 7.9 0 8 1 298 | 72 1 1 0 0 0 22.1 0 5 0 299 | 52 1 0 1 0 0 5.5 0 5 0 300 | 73 1 1 0 0 0 17.4 14.2 5 0 301 | 70 1 0 0 0 0 10 73.8 5 0 302 | 70 1 0 1 0 0 5.8 20 6 0 303 | 67 1 0 0 0 1 135 0 7 1 304 | 64 1 0 1 0 0 8.5 0 7 0 305 | 51 1 0 1 0 0 13 0 6 0 306 | 64 1 1 0 0 0 7.2 10.9 6 0 307 | 68 1 0 0 1 0 11.8 0 5 0 308 | 66 1 0 0 1 0 4.8 8.8 7 1 309 | 69 1 1 0 0 0 14.3 67.1 4 0 310 | 67 1 0 0 1 0 18.1 0 8 0 311 | 78 1 1 0 0 0 5.2 29.1 5 0 312 | 75 1 0 0 0 0 9.9 16.3 5 1 313 | 59 1 0 0 1 1 12.9 0 6 1 314 | 64 1 1 0 0 0 22 0 5 0 315 | 74 1 0 0 1 0 9 41.8 7 1 316 | 73 1 0 0 0 0 14 0 7 1 317 | 57 0 0 0 1 0 7.8 38.9 7 1 318 | 71 1 1 0 0 0 4.8 14 7 0 319 | 66 1 0 1 0 0 58.6 0 7 1 320 | 64 1 0 1 0 0 2 0 6 0 321 | 64 1 0 0 1 0 8.7 17.2 7 0 322 | 62 1 0 0 0 0 4.6 0 6 1 323 | 63 1 0 0 1 0 0.7 18.6 5 0 324 | 64 1 0 0 0 0 24.1 0 6 1 325 | 70 1 1 0 0 0 5.3 73.7 5 0 326 | 75 1 1 0 0 0 4.8 26.3 7 1 327 | 52 1 0 1 0 0 2.2 11.5 6 0 328 | 62 1 0 1 0 0 7.4 0 6 0 329 | 71 1 0 1 0 0 4.6 48.7 5 0 330 | 60 1 0 1 0 1 11.4 0 7 1 331 | 68 1 0 0 1 0 13.7 1.92 7 1 332 | 73 0 0 1 0 0 7.9 18 6 0 333 | 51 1 0 0 1 0 8.9 0 6 0 334 | 57 0 0 0 1 0 3.4 30.8 6 0 335 | 65 1 0 0 0 0 6.3 0 6 0 336 | 61 1 0 0 1 0 1.5 0 5 0 337 | 56 1 0 1 0 1 58 0 6 1 338 | 72 1 0 1 0 0 1.4 24.2 6 1 339 | 54 1 0 1 0 0 18 43 9 1 340 | 62 1 0 1 0 0 7.3 0 7 1 341 | 63 0 0 0 1 0 14.3 16 7 0 342 | 68 1 1 0 0 0 5.4 34 5 0 343 | 65 1 0 0 1 0 8.4 26.2 6 0 344 | 66 1 0 1 0 0 75 0 7 1 345 | 70 1 0 1 0 0 4.5 37 5 0 346 | 64 1 1 0 0 0 3.7 0 6 0 347 | 71 1 1 0 0 0 11.7 41.2 5 0 348 | 61 1 1 0 0 0 21 0 7 1 349 | 65 1 1 0 0 0 18.5 0 6 0 350 | 62 1 0 0 1 0 6.4 0 6 0 351 | 75 1 0 0 0 0 1 13.3 6 0 352 | 54 1 0 0 1 0 21.6 25 7 0 353 | 59 1 0 1 0 1 7.9 0 7 1 354 | 71 0 0 1 0 0 12.3 97.6 5 0 355 | 66 1 0 1 0 0 4.4 0 6 0 356 | 63 1 1 0 0 0 0.5 0 0 0 357 | 66 1 1 0 0 0 5.4 21.3 6 0 358 | 56 1 1 0 0 0 5.3 0 6 0 359 | 73 1 1 0 0 0 10.4 0 7 0 360 | 57 1 1 0 0 0 4.4 13.9 6 0 361 | 65 1 1 0 0 0 10.8 0 6 0 362 | 78 1 0 1 0 1 50.3 29.8 7 0 363 | 67 1 0 0 0 0 15.2 32 7 1 364 | 69 1 0 1 0 0 4.2 0 5 0 365 | 55 1 1 0 0 0 0.8 21 6 0 366 | 69 0 0 1 0 0 11.5 0 6 0 367 | 74 1 0 1 0 0 48 47 7 0 368 | 53 1 1 0 0 0 10.3 16.4 5 0 369 | 79 1 1 0 0 0 4.4 23.7 6 0 370 | 74 1 0 0 1 0 6 0 5 1 371 | 73 1 0 0 0 0 10 27.4 6 0 372 | 72 1 0 1 0 0 11 31 6 0 373 | 65 1 0 0 0 0 139.7 29.9 9 1 374 | 64 1 1 0 0 0 32.2 26.6 5 0 375 | 58 0 0 0 1 0 18.2 28.6 7 0 376 | 69 0 1 0 0 0 7.9 14.6 5 0 377 | 76 1 0 1 0 0 5.5 53.9 8 1 378 | 69 0 0 1 0 0 1.5 8.6 5 0 379 | 69 1 0 1 0 0 1.9 20.7 6 0 380 | -------------------------------------------------------------------------------- /data/uis.txt: -------------------------------------------------------------------------------- 1 | 39 9 0 0 1 1 0 1 1 2 | 33 34 0 1 8 1 0 1 1 3 | 33 10 0 0 3 1 0 1 1 4 | 32 20 0 0 1 1 1 1 1 5 | 24 5 1 0 5 0 0 1 0 6 | 30 32.55 0 0 1 1 0 1 1 7 | 39 19 0 0 34 1 0 1 0 8 | 27 10 0 0 2 1 0 1 1 9 | 40 29 0 0 3 1 0 1 1 10 | 36 25 0 0 7 1 0 1 1 11 | 38 18.9 0 0 8 1 0 1 1 12 | 29 16 1 0 1 1 0 1 1 13 | 32 36 0 0 2 0 0 1 0 14 | 41 19 0 0 8 1 0 1 1 15 | 31 18 0 0 1 1 0 1 1 16 | 27 12 0 0 3 1 0 1 1 17 | 28 34 0 0 6 1 0 1 1 18 | 28 23 0 1 1 1 0 1 1 19 | 36 26 1 0 15 0 0 1 0 20 | 32 18.9 0 0 5 1 0 1 0 21 | 33 15 1 0 1 1 1 1 0 22 | 28 25.2 0 0 8 1 1 1 1 23 | 29 6.632 0 1 0 1 1 1 1 24 | 35 2.1 0 0 9 1 1 1 1 25 | 45 26 0 0 6 1 1 1 1 26 | 35 39.789 0 0 5 1 1 1 1 27 | 24 20 1 0 3 1 1 1 1 28 | 36 16 0 0 7 1 1 1 1 29 | 39 22 0 0 9 1 1 1 0 30 | 36 9.947 0 1 10 1 1 1 1 31 | 37 9.45 0 0 1 1 1 1 1 32 | 30 39 0 0 1 1 1 1 1 33 | 44 41 0 0 5 1 1 1 1 34 | 28 31 1 0 6 0 1 1 0 35 | 25 20 1 0 3 0 1 1 1 36 | 30 8 0 0 7 1 0 1 1 37 | 24 9 1 0 1 1 1 1 1 38 | 27 20 1 0 1 1 1 1 1 39 | 30 8 1 0 2 0 1 1 0 40 | 34 8 0 0 0 1 0 1 1 41 | 33 23 0 1 2 1 0 1 1 42 | 34 18 0 0 6 1 0 1 1 43 | 36 13 0 0 1 1 0 1 1 44 | 27 23 0 0 0 1 0 1 1 45 | 35 9 0 0 1 0 0 1 1 46 | 24 14 0 0 0 1 0 1 1 47 | 28 23 1 0 2 0 0 1 1 48 | 46 10 0 0 8 1 0 1 0 49 | 26 11 0 0 1 1 0 1 0 50 | 42 16 0 0 25 1 0 1 1 51 | 30 0 1 0 0 1 0 1 1 52 | 30 12 1 0 3 0 0 1 1 53 | 27 21 0 0 2 1 1 1 1 54 | 38 0 0 0 6 1 1 1 1 55 | 48 8 0 0 10 1 1 1 1 56 | 36 25 0 0 10 1 1 1 1 57 | 28 6.3 1 0 7 1 1 1 1 58 | 31 20 0 1 5 1 1 1 1 59 | 28 4 0 0 5 1 1 1 1 60 | 28 20 1 0 1 1 1 1 1 61 | 26 17 1 0 2 0 1 1 1 62 | 34 3 0 0 6 1 1 1 1 63 | 26 29 0 0 5 1 1 1 1 64 | 31 26 0 0 5 1 1 1 1 65 | 41 12 0 0 0 0 1 1 0 66 | 30 24 0 0 0 1 1 1 1 67 | 39 15.75 0 0 5 1 1 1 1 68 | 33 9 0 0 12 1 1 1 1 69 | 33 18 0 1 6 1 1 1 1 70 | 29 20 1 0 0 0 1 1 1 71 | 36 17 0 0 5 1 1 1 1 72 | 26 3 0 0 3 1 1 1 1 73 | 37 27 0 0 13 1 1 1 1 74 | 29 31.5 0 0 8 1 1 1 1 75 | 30 19 1 0 0 0 1 1 0 76 | 35 15 0 1 2 1 1 1 1 77 | 33 22 1 0 1 1 1 1 1 78 | 36 16 0 0 1 1 1 1 0 79 | 28 17 0 0 2 1 1 1 1 80 | 31 32.55 0 0 12 0 1 1 1 81 | 23 24 0 0 2 1 1 1 0 82 | 33 22 0 1 1 1 1 1 0 83 | 37 18 0 0 4 1 1 1 1 84 | 25 17.85 1 0 1 1 0 1 1 85 | 56 5 0 1 9 0 0 1 0 86 | 23 39 0 0 1 1 0 1 1 87 | 26 21 1 0 1 1 0 1 1 88 | 26 11 0 0 1 1 0 1 1 89 | 23 14 1 0 1 1 0 1 1 90 | 28 31 0 1 2 0 0 1 1 91 | 30 14 0 0 15 1 0 1 1 92 | 25 6 0 0 5 1 0 1 0 93 | 33 16 0 0 5 1 0 1 1 94 | 22 6 1 0 3 0 0 1 0 95 | 25 20 0 1 8 0 0 1 1 96 | 38 9 1 0 1 0 1 1 1 97 | 35 11 1 0 3 1 0 1 0 98 | 35 15 1 0 1 1 1 1 0 99 | 25 13 0 0 1 1 1 1 1 100 | 33 31 1 0 3 0 1 1 1 101 | 30 5 1 0 2 0 1 1 1 102 | 45 10 0 0 1 1 1 1 1 103 | 42 23 0 0 20 1 1 1 1 104 | 29 16 1 0 1 0 1 1 0 105 | 24 37.8 1 0 0 1 1 1 1 106 | 33 10 0 0 4 1 1 1 1 107 | 32 9 1 0 0 1 1 1 1 108 | 26 15 1 0 0 1 1 1 0 109 | 28 2 0 0 3 1 1 1 1 110 | 37 34 0 0 1 1 1 1 1 111 | 23 11 1 0 6 1 1 1 1 112 | 40 31 0 0 3 0 1 1 1 113 | 36 36.75 0 0 0 1 1 1 1 114 | 23 26 0 1 2 1 1 1 1 115 | 35 5 1 0 1 0 1 1 1 116 | 25 19 0 0 1 1 0 1 0 117 | 35 21 0 0 6 1 0 1 1 118 | 46 1 0 1 0 1 0 1 1 119 | 32 6 1 0 3 1 0 1 1 120 | 35 23 1 0 16 0 0 1 0 121 | 34 38 0 0 1 1 0 1 1 122 | 43 24 1 0 3 1 0 1 0 123 | 39 3 0 0 15 1 0 1 1 124 | 27 16.8 0 0 2 0 0 1 1 125 | 38 35 0 0 1 1 0 1 1 126 | 37 11 0 0 7 1 0 1 1 127 | 44 2 0 0 4 0 0 1 0 128 | 25 16 1 0 1 0 0 1 1 129 | 34 15 1 0 1 1 0 1 1 130 | 34 11 0 0 2 0 0 1 0 131 | 38 11 0 0 1 0 0 1 0 132 | 24 22 0 0 2 0 0 1 1 133 | 42 18 0 0 3 1 0 1 0 134 | 34 29 0 0 1 0 1 1 0 135 | 45 27 0 0 8 1 1 1 0 136 | 40 16 0 0 4 1 1 1 1 137 | 27 9 1 0 3 0 1 1 0 138 | 24 0 1 0 3 1 1 1 1 139 | 27 15 0 0 3 1 1 1 1 140 | 34 24 1 0 4 1 1 1 1 141 | 36 3 0 0 6 1 1 1 1 142 | 31 9 1 0 1 1 1 1 1 143 | 40 5 0 0 2 1 1 1 1 144 | 40 13 0 0 4 0 1 1 0 145 | 37 29 0 0 5 1 1 1 1 146 | 25 11 0 0 6 1 1 1 1 147 | 41 22 0 0 3 0 0 1 1 148 | 22 9 1 0 1 1 0 1 0 149 | 31 18 0 0 8 0 0 1 1 150 | 29 40 1 0 1 0 0 1 0 151 | 27 25 1 0 2 1 0 1 0 152 | 22 26 0 1 3 1 0 1 1 153 | 37 11 0 1 5 0 0 1 0 154 | 36 6 1 0 2 0 0 1 0 155 | 24 20 1 0 1 1 0 1 0 156 | 28 9 1 0 0 0 0 1 1 157 | 24 6 1 0 1 1 0 1 1 158 | 28 0 1 0 2 1 0 1 1 159 | 24 5 1 0 20 0 0 1 1 160 | 24 15 1 0 0 1 0 1 0 161 | 29 14.7 1 0 1 1 0 1 1 162 | 37 3 0 0 5 0 0 1 1 163 | 26 31 1 0 2 1 0 1 1 164 | 29 14 0 1 1 1 0 1 1 165 | 29 28 0 0 4 1 0 1 1 166 | 33 18 1 0 1 1 0 1 0 167 | 29 12 0 1 2 1 0 1 0 168 | 32 5 1 0 2 0 0 1 0 169 | 33 11 1 0 8 0 0 1 0 170 | 26 21 0 1 2 1 0 1 0 171 | 24 23 0 0 4 0 0 1 1 172 | 46 32 0 0 2 1 0 1 0 173 | 23 26 1 0 2 1 0 1 1 174 | 40 19.95 0 0 8 1 0 1 1 175 | 48 17 1 0 4 1 0 1 0 176 | 33 16 1 0 0 1 0 1 1 177 | 21 26.25 1 0 7 1 0 1 1 178 | 38 29 1 0 2 1 0 1 0 179 | 28 23 0 1 4 1 0 1 1 180 | 39 9 0 0 6 1 0 1 1 181 | 37 26 0 1 1 0 1 1 1 182 | 32 22 1 0 4 0 1 1 1 183 | 39 23 0 1 2 0 1 1 1 184 | 28 0 0 0 10 1 1 1 1 185 | 26 30 1 0 0 0 1 1 0 186 | 31 21 0 0 0 1 1 1 1 187 | 34 19 0 0 8 1 1 1 1 188 | 26 28 0 1 2 0 1 1 1 189 | 29 8 1 0 3 1 1 1 1 190 | 25 11 1 0 8 1 1 1 1 191 | 34 15 0 1 3 0 1 1 1 192 | 32 8 1 0 2 1 1 1 1 193 | 38 14 0 1 0 1 1 1 1 194 | 32 7 0 0 8 1 1 1 1 195 | 31 13 0 0 7 1 1 1 1 196 | 40 10 1 0 3 1 1 1 0 197 | 28 17 1 0 5 0 1 1 1 198 | 40 18 0 0 3 1 1 1 1 199 | 32 5 0 0 3 1 1 1 1 200 | 29 20 0 0 5 1 1 1 1 201 | 25 31 1 0 4 1 1 1 1 202 | 32 15 0 0 2 1 1 1 1 203 | 37 4 0 1 2 1 1 1 1 204 | 38 15 0 0 8 1 1 1 1 205 | 31 14 0 1 9 1 1 1 1 206 | 30 27 0 0 3 0 1 1 1 207 | 34 30 1 0 4 0 1 1 0 208 | 33 23 0 0 4 1 0 1 0 209 | 36 13 0 1 10 0 0 1 1 210 | 32 26 1 0 0 1 0 1 0 211 | 29 10 0 0 2 0 0 1 0 212 | 32 4 1 0 4 0 0 1 1 213 | 34 0 1 0 7 1 0 1 0 214 | 26 35 0 0 31 1 0 1 1 215 | 25 32 0 0 5 0 0 1 1 216 | 30 2 1 0 2 0 0 1 1 217 | 33 15 0 1 6 1 0 1 1 218 | 40 23 0 1 6 1 0 1 1 219 | 26 13 1 0 12 1 0 1 1 220 | 26 29 0 0 5 0 0 1 1 221 | 35 22.105 0 0 4 1 0 1 1 222 | 26 15 0 1 11 1 0 1 1 223 | 33 7 1 0 3 0 0 1 0 224 | 27 7 0 0 4 1 0 1 1 225 | 29 33 0 0 3 1 0 1 0 226 | 29 23 0 0 9 1 0 1 1 227 | 39 21 0 0 7 1 0 1 1 228 | 43 19 0 1 2 0 0 1 1 229 | 35 8 0 0 3 1 0 1 0 230 | 26 24 1 0 2 0 0 1 1 231 | 27 28.737 1 0 3 1 0 1 1 232 | 28 20 1 0 2 0 0 1 1 233 | 30 14 1 0 4 1 0 1 1 234 | 31 17 0 1 1 0 0 1 0 235 | 26 19 0 0 16 1 0 1 1 236 | 36 5 0 1 4 1 0 1 1 237 | 25 8 0 0 3 1 0 1 1 238 | 26 22 1 0 0 0 0 1 0 239 | 30 11 0 0 5 1 1 1 1 240 | 28 13 1 0 5 1 1 1 1 241 | 34 11.053 1 0 0 0 1 1 1 242 | 31 24 1 0 2 1 1 1 0 243 | 30 19 0 0 1 1 1 1 0 244 | 35 27 0 1 5 0 1 1 0 245 | 30 4 0 1 3 0 1 1 1 246 | 37 38 0 0 7 1 1 1 1 247 | 29 11 1 0 12 0 1 1 1 248 | 23 21 1 0 8 1 1 1 1 249 | 23 1 1 0 4 1 1 1 1 250 | 44 4 1 0 0 1 1 1 1 251 | 43 7 0 1 8 0 1 1 0 252 | 38 20 0 0 3 1 1 1 1 253 | 33 17 1 0 3 0 1 1 1 254 | 36 6.3 0 0 9 1 1 1 1 255 | 26 12 0 0 2 1 1 1 0 256 | 30 16 1 0 0 1 1 1 1 257 | 34 31.5 1 0 0 1 1 1 1 258 | 32 30 0 0 6 1 1 1 1 259 | 30 1 1 0 1 1 1 1 0 260 | 37 32 0 0 10 0 1 1 1 261 | 35 29 0 0 7 1 1 1 1 262 | 30 6 1 0 0 1 1 1 1 263 | 34 17 1 0 6 0 1 1 1 264 | 40 13 0 1 6 1 1 1 1 265 | 28 15 0 1 3 0 1 1 1 266 | 32 11 1 0 6 1 1 1 1 267 | 45 17 0 0 2 0 1 1 1 268 | 24 23 1 0 0 1 0 1 1 269 | 43 23 0 0 5 0 0 1 1 270 | 38 15 0 0 0 0 0 1 1 271 | 33 19 0 0 1 1 0 1 0 272 | 26 21 0 1 2 0 0 1 1 273 | 40 8 0 0 3 1 0 1 1 274 | 27 34 0 1 0 1 0 1 1 275 | 39 21 0 0 12 1 0 1 1 276 | 29 27 0 1 3 0 0 1 1 277 | 28 32 0 1 4 1 0 1 1 278 | 37 29 0 0 20 1 1 1 1 279 | 37 22 0 0 20 1 1 1 1 280 | 40 12 0 1 9 1 1 1 1 281 | 25 36 0 0 5 1 1 1 1 282 | 40 15 1 0 2 1 1 1 0 283 | 40 3 0 0 4 0 1 1 1 284 | 34 24 0 0 8 1 1 1 0 285 | 41 18 0 0 7 1 1 1 1 286 | 23 2 1 0 1 1 0 1 1 287 | 36 14 1 0 3 1 0 1 1 288 | 28 19 1 0 2 0 0 1 0 289 | 23 7 1 0 3 1 0 1 1 290 | 27 8 1 0 3 1 0 1 0 291 | 32 27 0 1 0 1 0 1 1 292 | 38 25 0 0 15 1 0 1 1 293 | 38 28 1 0 6 0 0 1 1 294 | 45 39 0 0 8 1 0 1 1 295 | 26 18 0 1 1 1 0 1 1 296 | 29 8 0 0 35 1 0 1 1 297 | 33 31 1 0 3 1 0 1 1 298 | 25 6 1 0 0 0 0 1 1 299 | 36 19 1 0 2 1 0 1 1 300 | 37 19 0 0 4 1 0 1 1 301 | 29 16 1 0 0 0 0 1 0 302 | 29 15 1 0 3 0 0 1 1 303 | 35 54 0 1 1 1 0 1 0 304 | 33 19 1 0 1 1 0 1 1 305 | 31 12 0 0 2 1 0 1 0 306 | 37 24 0 1 5 0 0 1 1 307 | 32 37 0 0 4 1 0 1 1 308 | 33 9 0 1 13 1 0 1 1 309 | 36 18 1 0 14 0 0 1 1 310 | 26 4 1 0 5 1 0 1 1 311 | 35 15 1 0 0 0 0 1 1 312 | 25 19 0 0 6 0 1 1 1 313 | 33 26 0 0 30 1 1 1 1 314 | 36 28 0 0 8 1 1 1 1 315 | 38 14 0 0 6 1 1 1 1 316 | 36 15 0 1 3 0 1 1 0 317 | 36 18 0 0 10 1 1 1 1 318 | 35 29 0 0 6 1 1 1 0 319 | 35 10 1 0 3 0 1 1 0 320 | 39 16 0 0 4 1 1 1 1 321 | 37 0 0 0 6 1 1 1 1 322 | 30 31 0 0 5 1 1 1 0 323 | 26 33 0 0 7 0 1 1 1 324 | 39 21 1 0 5 1 1 1 1 325 | 32 18 1 0 4 1 1 1 0 326 | 26 37.8 1 0 4 0 1 1 1 327 | 33 20 0 0 6 1 1 1 1 328 | 36 11 0 1 5 1 1 1 1 329 | 42 26 0 0 3 1 0 1 1 330 | 37 43 0 0 22 1 0 1 1 331 | 37 12 0 1 1 0 0 1 1 332 | 32 22 1 0 4 0 0 1 0 333 | 23 36 1 0 3 0 0 1 0 334 | 21 16 1 0 10 1 0 1 1 335 | 23 41 1 0 1 1 0 1 0 336 | 34 16 0 1 1 1 0 1 1 337 | 33 8 0 1 3 1 0 1 0 338 | 33 10 1 0 4 0 0 1 1 339 | 26 18 0 0 0 1 0 1 1 340 | 28 27 1 0 2 0 0 1 1 341 | 27 28 0 0 3 1 1 1 1 342 | 22 23 0 0 2 1 1 1 1 343 | 31 32 0 0 6 0 1 1 1 344 | 29 23.1 1 0 4 1 1 1 1 345 | 44 11 0 0 12 1 1 1 1 346 | 26 7 1 0 0 0 1 1 0 347 | 44 24 0 0 16 1 1 1 1 348 | 34 12 0 0 1 1 1 1 1 349 | 36 25 0 0 6 1 1 1 1 350 | 43 4 0 0 20 1 1 1 0 351 | 37 5 1 0 1 1 1 1 1 352 | 44 13 0 1 17 1 0 1 1 353 | 31 17 0 0 30 0 0 1 1 354 | 24 24 1 0 3 1 0 1 1 355 | 37 32 0 0 4 1 0 1 1 356 | 41 19 0 0 12 0 0 1 0 357 | 32 9 1 0 3 0 0 1 1 358 | 23 6 1 0 2 1 0 1 1 359 | 33 10 0 0 3 1 0 1 1 360 | 43 11 1 0 9 1 0 1 0 361 | 33 16 0 0 8 1 0 1 1 362 | 41 25 0 1 3 1 0 1 0 363 | 41 17 0 0 2 1 0 1 1 364 | 37 24 0 0 3 1 0 1 0 365 | 26 27 1 0 3 1 1 1 1 366 | 33 24 0 0 6 1 1 1 0 367 | 30 26 1 0 2 1 1 1 1 368 | 33 17 1 0 6 0 1 1 1 369 | 33 26 0 0 3 1 1 1 1 370 | 37 13 1 0 6 1 1 1 1 371 | 44 11 0 0 20 1 1 1 1 372 | 20 8 1 0 1 1 1 1 1 373 | 33 12 0 0 4 1 1 1 1 374 | 36 31 0 0 3 1 1 1 0 375 | 34 8.4 0 0 3 1 1 1 1 376 | 35 10 0 0 17 1 0 1 1 377 | 38 16 0 0 26 1 0 1 1 378 | 24 13 1 0 3 1 0 1 1 379 | 24 18 1 0 4 1 0 1 1 380 | 32 13 1 0 4 1 0 1 1 381 | 35 11 0 1 3 1 0 1 0 382 | 33 21 0 0 5 1 0 1 1 383 | 29 37 0 1 4 0 0 1 1 384 | 42 32 0 0 30 1 0 1 1 385 | 23 33 1 0 1 1 0 1 1 386 | 28 11 0 0 16 1 0 1 1 387 | 43 29 0 0 4 1 0 1 1 388 | 33 23 1 0 0 1 1 1 1 389 | 37 15 0 0 20 1 1 1 1 390 | 49 22 0 0 7 1 1 1 1 391 | 36 25 1 0 1 0 1 1 1 392 | 27 30 0 0 13 1 1 1 1 393 | 35 23 0 0 1 1 1 1 1 394 | 25 10 0 1 3 1 1 1 1 395 | 33 8 0 0 3 1 1 1 0 396 | 34 16 0 0 7 1 1 1 1 397 | 38 9 0 0 10 0 1 1 1 398 | 36 12.158 0 0 0 0 1 1 1 399 | 27 5 0 0 1 1 1 1 0 400 | 40 19 0 0 0 0 1 1 0 401 | 32 23 0 0 3 1 1 0 1 402 | 38 28 0 0 1 0 1 0 0 403 | 38 16 0 0 6 1 1 0 1 404 | 23 25 1 0 0 1 1 0 0 405 | 26 22 0 1 2 1 1 0 0 406 | 36 28 0 0 7 1 1 0 1 407 | 30 28 1 0 5 1 1 0 1 408 | 31 18 0 1 3 1 0 0 0 409 | 23 15 1 0 1 1 0 0 1 410 | 43 9 0 0 0 0 0 0 1 411 | 24 26 1 0 1 1 0 0 0 412 | 42 19 1 0 1 1 0 0 0 413 | 35 26 0 1 1 1 0 0 0 414 | 21 10 1 0 0 1 0 0 1 415 | 45 1 0 1 0 0 0 0 1 416 | 43 30 0 0 6 1 0 0 0 417 | 24 7 1 0 0 0 0 0 1 418 | 37 11 0 0 1 1 0 0 1 419 | 40 10 0 1 0 1 0 0 0 420 | 27 11 0 1 2 1 1 0 1 421 | 29 11 0 0 1 1 1 0 1 422 | 34 12 0 0 6 1 1 0 1 423 | 29 29 0 0 20 1 1 0 1 424 | 35 27 0 0 5 1 1 0 1 425 | 39 20 0 0 4 1 0 0 0 426 | 41 9 0 1 0 1 0 0 1 427 | 37 18 1 0 6 0 0 0 1 428 | 30 10 0 1 7 1 0 0 1 429 | 31 1 1 0 0 1 0 0 1 430 | 40 5 0 1 8 1 1 0 1 431 | 32 20 1 0 0 1 1 0 1 432 | 32 7 0 1 3 0 1 0 1 433 | 27 7 1 0 0 1 1 0 0 434 | 23 26 1 0 0 1 1 0 1 435 | 23 4 1 0 2 1 1 0 1 436 | 43 11 0 0 12 1 1 0 1 437 | 24 20 1 0 0 1 1 0 1 438 | 36 11 1 0 2 0 1 0 1 439 | 29 31 0 0 1 1 1 0 1 440 | 39 13 0 1 1 1 0 0 1 441 | 23 6 1 0 0 1 0 0 0 442 | 27 17 0 0 4 1 0 0 1 443 | 26 5 0 1 5 1 0 0 0 444 | 26 27 1 0 1 0 0 0 1 445 | 25 9 1 0 0 1 0 0 1 446 | 34 10 1 0 0 1 0 0 0 447 | 45 5 0 0 2 1 0 0 0 448 | 23 17 1 0 1 1 1 0 0 449 | 26 7 1 0 0 1 1 0 0 450 | 24 27 0 1 2 1 1 0 1 451 | 30 23 0 0 2 0 1 0 1 452 | 22 26 1 0 0 1 1 0 0 453 | 25 10 1 0 1 1 1 0 1 454 | 30 8.4 0 1 40 1 1 0 1 455 | 33 23 1 0 0 0 0 0 1 456 | 34 15 0 1 8 1 0 0 0 457 | 29 24 1 0 2 1 0 0 1 458 | 39 33 0 1 6 1 0 0 1 459 | 26 21 1 0 4 1 0 0 0 460 | 32 23 0 0 6 1 0 0 1 461 | 42 23.1 0 0 2 1 1 0 1 462 | 39 25 0 1 8 1 1 0 1 463 | 36 2 1 0 0 0 1 0 0 464 | 22 20 1 0 1 1 1 0 1 465 | 27 23 1 0 1 1 1 0 1 466 | 28 9 1 0 0 1 1 0 0 467 | 36 28 0 1 1 1 0 0 0 468 | 31 13 1 0 3 1 0 0 1 469 | 27 22 0 1 4 1 0 0 1 470 | 23 17 1 0 1 1 0 0 1 471 | 24 20 0 1 20 1 1 0 0 472 | 38 5 0 1 1 1 1 0 1 473 | 25 8 1 0 1 1 0 0 0 474 | 26 20 1 0 0 1 1 0 1 475 | 22 34 1 0 2 1 1 0 1 476 | 33 13 1 0 2 1 0 0 0 477 | 30 23 0 0 7 1 0 0 1 478 | 45 8 0 0 3 1 1 0 1 479 | 24 15 0 1 0 1 1 0 1 480 | 27 22 1 0 0 1 0 0 1 481 | 36 19 0 1 10 1 0 0 1 482 | 38 23 0 1 2 0 1 0 1 483 | 31 17 0 0 2 1 0 0 1 484 | 40 22 0 1 7 1 0 0 1 485 | 22 12 1 0 0 0 0 0 1 486 | 31 13 1 0 0 0 0 0 1 487 | 39 7 0 0 3 0 1 0 1 488 | 33 14 1 0 1 1 1 0 1 489 | 27 10 0 0 2 1 0 0 1 490 | 37 7 1 0 2 0 0 0 1 491 | 35 16 0 1 25 1 1 0 1 492 | 25 11 1 0 5 1 1 0 1 493 | 27 11 1 0 1 0 0 0 0 494 | 34 15 1 0 0 1 1 0 0 495 | 30 15 1 0 3 1 1 0 1 496 | 35 17 0 0 7 1 1 0 1 497 | 34 23 1 0 0 1 1 0 1 498 | 25 23 0 1 5 1 1 0 1 499 | 34 18 1 0 1 1 1 0 1 500 | 24 23 0 0 3 1 1 0 1 501 | 24 20 1 0 2 1 1 0 1 502 | 40 36 1 0 3 1 1 0 0 503 | 33 9 1 0 1 0 1 0 0 504 | 38 14 0 1 1 0 0 0 1 505 | 32 1 1 0 0 1 0 0 0 506 | 33 3 1 0 1 1 1 0 0 507 | 28 40 1 0 2 0 1 0 1 508 | 31 13 0 0 2 1 1 0 0 509 | 31 39 0 0 4 1 0 0 1 510 | 33 24 1 0 0 1 0 0 0 511 | 24 26 1 0 11 1 1 0 1 512 | 26 18 1 0 3 1 1 0 0 513 | 31 19 0 0 7 1 0 0 1 514 | 40 14.7 0 0 4 1 0 0 1 515 | 34 2 1 0 3 1 0 0 0 516 | 30 11 0 1 7 1 1 0 1 517 | 36 0 0 1 3 1 1 0 1 518 | 38 17 0 0 6 1 0 0 0 519 | 31 20 0 0 6 0 0 0 1 520 | 27 22 0 1 2 1 1 0 0 521 | 32 21 0 0 15 1 0 0 1 522 | 35 23 1 0 5 0 1 0 0 523 | 44 29 0 0 13 1 1 0 1 524 | 31 5 0 0 10 1 0 0 1 525 | 28 23 0 1 20 1 1 0 1 526 | 40 8 0 1 1 1 1 0 1 527 | 25 12 1 0 10 0 0 0 1 528 | 32 10 0 0 6 1 0 0 1 529 | 29 15.75 1 0 2 1 1 0 1 530 | 40 2 0 1 5 1 0 0 1 531 | 27 9 0 1 0 1 0 0 1 532 | 26 2 1 0 1 1 0 0 0 533 | 34 15 1 0 4 0 0 0 0 534 | 49 4 0 1 2 1 1 0 0 535 | 21 25 0 0 1 1 0 0 1 536 | 39 23 0 0 2 1 0 0 1 537 | 33 15 0 1 4 1 0 0 1 538 | 32 3 1 0 1 1 0 0 0 539 | 35 9 0 1 6 1 1 0 0 540 | 31 20 1 0 0 0 0 0 1 541 | 28 5 1 0 3 1 1 0 0 542 | 27 29 0 1 5 1 0 0 1 543 | 29 21 1 0 1 0 0 0 1 544 | 30 1 1 0 20 1 1 0 1 545 | 27 18 1 0 3 0 1 0 1 546 | 40 15 0 1 1 1 0 0 1 547 | 37 20 1 0 2 0 0 0 1 548 | 33 10 1 0 0 1 1 0 1 549 | 28 20 1 0 2 1 1 0 1 550 | 40 15 0 1 8 1 0 0 1 551 | 48 20 1 0 0 0 1 0 1 552 | 38 25 1 0 1 1 1 0 1 553 | 35 13 1 0 0 1 1 0 1 554 | 37 13 0 1 0 1 1 0 1 555 | 25 15 1 0 0 0 0 0 0 556 | 26 8 1 0 2 1 0 0 1 557 | 30 9 0 0 3 1 1 0 1 558 | 28 16 0 1 2 1 1 0 0 559 | 23 11 0 0 4 1 1 0 1 560 | 36 31 1 0 1 1 0 0 0 561 | 36 13 0 1 4 1 0 0 0 562 | 24 5 1 0 0 0 1 0 1 563 | 33 9 0 1 5 1 1 0 1 564 | 38 15 0 1 6 1 1 0 1 565 | 41 20 0 0 21 1 0 0 1 566 | 31 21 1 0 0 0 0 0 1 567 | 31 23 0 1 11 1 0 0 1 568 | 37 5 1 0 0 0 0 0 1 569 | 37 17 0 1 4 0 1 0 1 570 | 33 13 1 0 0 1 1 0 1 571 | 53 9 0 1 6 1 1 0 1 572 | 37 20 0 0 4 1 1 0 1 573 | 28 10 0 1 3 1 0 0 1 574 | 35 17 0 0 2 1 1 0 0 575 | 46 31.5 0 0 15 0 0 0 0 -------------------------------------------------------------------------------- /foo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/foo -------------------------------------------------------------------------------- /libHELR.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/libHELR.a -------------------------------------------------------------------------------- /src/CZZ.cpp: -------------------------------------------------------------------------------- 1 | #include "CZZ.h" 2 | #include 3 | 4 | 5 | CZZ CZZ::operator+(const CZZ& o) { 6 | ZZ resr = r + o.r; 7 | ZZ resi = i + o.i; 8 | CZZ res(resr, resi); 9 | return res; 10 | } 11 | 12 | CZZ CZZ::operator+(const ZZ& o) { 13 | ZZ resr = r + o; 14 | CZZ res(resr, i); 15 | return res; 16 | } 17 | 18 | void CZZ::operator+=(const CZZ& o) { 19 | r += o.r; 20 | i += o.i; 21 | } 22 | 23 | CZZ CZZ::operator-() { 24 | CZZ res(-r, -i); 25 | return res; 26 | } 27 | 28 | CZZ CZZ::operator-(const CZZ& o) { 29 | ZZ resr = r - o.r; 30 | ZZ resi = i - o.i; 31 | CZZ res(resr, resi); 32 | return res; 33 | } 34 | 35 | CZZ CZZ::operator-(const ZZ& o) { 36 | ZZ resr = r - o; 37 | CZZ res(resr, i); 38 | return res; 39 | } 40 | 41 | void CZZ::operator-=(const CZZ& o) { 42 | r -= o.r; 43 | i -= o.i; 44 | } 45 | 46 | CZZ CZZ::operator *(const CZZ& o) { 47 | ZZ tmpProd = (r + i) * o.r; 48 | 49 | ZZ resr = tmpProd - (o.r + o.i) * i; 50 | ZZ resi = tmpProd + (o.i - o.r) * r; 51 | CZZ res(resr, resi); 52 | return res; 53 | } 54 | 55 | CZZ CZZ::operator *(const ZZ& o) { 56 | ZZ resr = r * o; 57 | ZZ resi = i * o; 58 | CZZ res(resr, resi); 59 | return res; 60 | } 61 | 62 | CZZ CZZ::operator *(const long& o) { 63 | ZZ resr = r * o; 64 | ZZ resi = i * o; 65 | CZZ res(resr, resi); 66 | return res; 67 | } 68 | 69 | void CZZ::operator*=(const CZZ& o) { 70 | ZZ tmpProd = (r + i) * o.r; 71 | 72 | ZZ tr = tmpProd - (o.r + o.i) * i; 73 | i = tmpProd + (o.i - o.r) * r; 74 | r = tr; 75 | } 76 | 77 | CZZ CZZ::operator /(const ZZ& o) { 78 | ZZ resr = r / o; 79 | ZZ resi = i / o; 80 | CZZ res(resr, resi); 81 | return res; 82 | } 83 | 84 | CZZ CZZ::operator /(const long& o) { 85 | ZZ resr = r / o; 86 | ZZ resi = i / o; 87 | CZZ res(resr, resi); 88 | return res; 89 | } 90 | 91 | void CZZ::operator /=(const long& o) { 92 | r /= o; 93 | i /= o; 94 | } 95 | 96 | CZZ CZZ::operator %(const ZZ& o) { 97 | ZZ tr = r % o; 98 | ZZ to = i % o; 99 | return CZZ(tr, to); 100 | } 101 | 102 | void CZZ::operator%=(const ZZ& o) { 103 | r %= o; 104 | i %= o; 105 | } 106 | 107 | CZZ CZZ::operator <<(const long& s) { 108 | ZZ tr = r << s; 109 | ZZ to = i << s; 110 | return CZZ(tr, to); 111 | } 112 | 113 | void CZZ::operator <<=(const long& s) { 114 | r <<= s; 115 | i <<= s; 116 | } 117 | 118 | CZZ CZZ::operator >>(const long& s) { 119 | ZZ tr = r >> s; 120 | ZZ to = i >> s; 121 | return CZZ(tr, to); 122 | } 123 | 124 | void CZZ::operator >>=(const long& s) { 125 | r >>= s; 126 | i >>= s; 127 | } 128 | 129 | CZZ CZZ::sqr() { 130 | ZZ resr = (r + i) * (r - i); 131 | ZZ resi = (r << 1) * i; 132 | CZZ res(resr, resi); 133 | return res; 134 | } 135 | 136 | void CZZ::sqrThis() { 137 | ZZ tr = (r + i) * (r - i); 138 | i *= (r << 1); 139 | r = tr; 140 | } 141 | 142 | ZZ CZZ::norm() { 143 | return SqrRoot(r*r + i*i); 144 | } 145 | 146 | CZZ CZZ::conjugate() { 147 | CZZ res = CZZ(r, -i); 148 | return res; 149 | } 150 | 151 | string CZZ::toString() { 152 | stringstream ss; 153 | ss << " [r = " << r; 154 | ss << " , i = " << i; 155 | ss << " ] "; 156 | return ss.str(); 157 | } 158 | -------------------------------------------------------------------------------- /src/CZZ.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_CZZ_H_ 2 | #define UTILS_CZZ_H_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace NTL; 9 | 10 | class CZZ { 11 | public: 12 | ZZ r; 13 | ZZ i; 14 | 15 | CZZ(long r, long i) : r(ZZ(r)), i(ZZ(i)) {}; 16 | 17 | CZZ(ZZ r = ZZ::zero(), ZZ i = ZZ::zero()) : r(r), i(i) {}; 18 | 19 | CZZ(const CZZ& o) : r(o.r), i(o.i) {}; 20 | 21 | CZZ operator-(); 22 | CZZ operator+(const CZZ& o); 23 | CZZ operator+(const ZZ& m); 24 | void operator+=(const CZZ& o); 25 | 26 | CZZ operator-(const CZZ& o); 27 | CZZ operator-(const ZZ& m); 28 | void operator-=(const CZZ& o); 29 | 30 | CZZ operator *(const CZZ& o); 31 | CZZ operator *(const ZZ& o); 32 | CZZ operator *(const long& o); 33 | void operator *=(const CZZ& o); 34 | 35 | CZZ operator /(const ZZ& o); 36 | CZZ operator /(const long& o); 37 | void operator /=(const long& o); 38 | 39 | CZZ operator %(const ZZ& o); 40 | void operator %=(const ZZ& o); 41 | 42 | CZZ operator <<(const long& s); 43 | void operator <<=(const long& s); 44 | CZZ operator >>(const long& s); 45 | void operator >>=(const long& s); 46 | 47 | CZZ sqr(); 48 | void sqrThis(); 49 | ZZ norm(); 50 | CZZ conjugate(); 51 | 52 | string toString(); 53 | }; 54 | 55 | #endif /* UTILS_CZZ_H_ */ 56 | -------------------------------------------------------------------------------- /src/CZZ.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/CZZ.o -------------------------------------------------------------------------------- /src/CZZX.cpp: -------------------------------------------------------------------------------- 1 | #include "CZZX.h" 2 | 3 | #include 4 | #include 5 | 6 | CZZX CZZX::operator+(const CZZX& o) { 7 | ZZX resr = rx + o.rx; 8 | ZZX resi = ix + o.ix; 9 | CZZX res(resr, resi); 10 | return res; 11 | } 12 | 13 | void CZZX::operator+=(const CZZX& o) { 14 | rx += o.rx; 15 | ix += o.ix; 16 | } 17 | 18 | CZZX CZZX::operator-(const CZZX& o) { 19 | ZZX resr = rx - o.rx; 20 | ZZX resi = ix - o.ix; 21 | CZZX res(resr, resi); 22 | return res; 23 | } 24 | 25 | void CZZX::operator-=(const CZZX& o) { 26 | rx -= o.rx; 27 | ix -= o.ix; 28 | } 29 | 30 | CZZX CZZX::operator -() { 31 | return CZZX(-rx, -ix); 32 | } 33 | 34 | CZZX CZZX::operator *(const CZZX& o) { 35 | ZZX tmpProd = (rx + ix) * o.rx; 36 | 37 | ZZX resr = tmpProd - (o.rx + o.ix) * ix; 38 | ZZX resi = tmpProd + (o.ix - o.rx) * rx; 39 | CZZX res(resr, resi); 40 | return res; 41 | } 42 | 43 | void CZZX::operator*=(const CZZX& o) { 44 | ZZX tmpProd = (rx + ix) * o.rx; 45 | 46 | ZZX tr = tmpProd - (o.rx + o.ix) * ix; 47 | ix = tmpProd + (o.ix - o.rx) * rx; 48 | rx = tr; 49 | } 50 | 51 | CZZX CZZX::operator >>(const long& s) { 52 | ZZX resr = rx >> s; 53 | ZZX resi = ix >> s; 54 | return CZZX(resr, resi); 55 | } 56 | 57 | void CZZX::operator >>=(const long& s) { 58 | rx >>= s; 59 | ix >>= s; 60 | } 61 | 62 | CZZX CZZX::operator <<(const long& s) { 63 | ZZX resr = rx << s; 64 | ZZX resi = ix << s; 65 | return CZZX(resr, resi); 66 | } 67 | 68 | void CZZX::operator <<=(const long& s) { 69 | rx <<= s; 70 | ix <<= s; 71 | } 72 | 73 | CZZX CZZX::sqr() { 74 | ZZX resr = (rx + ix) * (rx - ix); 75 | ZZX resi = (rx << 1) * ix; 76 | CZZX res(resr, resi); 77 | return res; 78 | } 79 | 80 | void CZZX::sqrThis() { 81 | ZZX tr = (rx + ix) * (rx - ix); 82 | ix *= (rx << 1); 83 | rx = tr; 84 | } 85 | 86 | void CZZX::SetMaxLength(long d) { 87 | rx.SetMaxLength(d); 88 | ix.SetMaxLength(d); 89 | } 90 | 91 | void CZZX::SetLength(long d) { 92 | rx.SetLength(d); 93 | ix.SetLength(d); 94 | } 95 | 96 | void CZZX::normalize() { 97 | rx.normalize(); 98 | ix.normalize(); 99 | } 100 | 101 | CZZ coeff(CZZX& cx, long s) { 102 | ZZ r = NTL::coeff(cx.rx, s); 103 | ZZ i = NTL::coeff(cx.ix, s); 104 | CZZ res(r, i); 105 | return res; 106 | } 107 | 108 | void SetCoeff(CZZX& cx, long s, CZZ& c) { 109 | NTL::SetCoeff(cx.rx, s, c.r); 110 | NTL::SetCoeff(cx.ix, s, c.i); 111 | } 112 | 113 | void GetCoeff(CZZ& c, CZZX& cx, long s) { 114 | GetCoeff(c.r, cx.rx, s); 115 | GetCoeff(c.i, cx.ix, s); 116 | } 117 | 118 | long deg(CZZX& cx) { 119 | return deg(cx.rx); 120 | } 121 | 122 | string CZZX::toString() { 123 | stringstream ss; 124 | ss << " [rx = " << rx << "\n"; 125 | ss << " ,ix = " << ix; 126 | ss << " ] "; 127 | return ss.str(); 128 | } 129 | -------------------------------------------------------------------------------- /src/CZZX.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_CZZX_H_ 2 | #define UTILS_CZZX_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include "CZZ.h" 8 | 9 | using namespace std; 10 | using namespace NTL; 11 | 12 | class CZZX { 13 | public: 14 | 15 | ZZX rx; 16 | ZZX ix; 17 | 18 | CZZX(ZZX rx = ZZX::zero(), ZZX ix = ZZX::zero()) : rx(rx), ix(ix) {} 19 | 20 | CZZX(const CZZX& o) : rx(o.rx), ix(o.ix) {} 21 | 22 | CZZX operator+(const CZZX& o); 23 | void operator+=(const CZZX& o); 24 | 25 | CZZX operator-(const CZZX& o); 26 | void operator-=(const CZZX& o); 27 | CZZX operator -(); 28 | 29 | CZZX operator *(const CZZX& o); 30 | void operator *=(const CZZX& o); 31 | 32 | CZZX operator >>(const long& s); 33 | void operator >>=(const long& s); 34 | 35 | CZZX operator <<(const long& s); 36 | void operator <<=(const long& s); 37 | 38 | CZZX sqr(); 39 | void sqrThis(); 40 | void SetMaxLength(long d); 41 | void SetLength(long d); 42 | void normalize(); 43 | 44 | string toString(); 45 | }; 46 | 47 | CZZ coeff(CZZX& cx, long s); 48 | void SetCoeff(CZZX& cx, long s, CZZ& c); 49 | void GetCoeff(CZZ& c, CZZX& cx, long s); 50 | long deg(CZZX& cx); 51 | 52 | #endif /* UTILS_CZZX_H_ */ 53 | -------------------------------------------------------------------------------- /src/CZZX.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/CZZX.o -------------------------------------------------------------------------------- /src/Cipher.cpp: -------------------------------------------------------------------------------- 1 | #include "Cipher.h" 2 | -------------------------------------------------------------------------------- /src/Cipher.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_CIPHER_H_ 2 | #define SCHEME_CIPHER_H_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace NTL; 9 | 10 | /** 11 | * Cipher consist a pair of elements (ax, bx) of ring Z_qi[X] / (X^N + 1) 12 | * 13 | */ 14 | class Cipher { 15 | public: 16 | 17 | ZZX ax; 18 | ZZX bx; 19 | 20 | ZZ mod; ///< mod in cipher 21 | long cbits; ///< bits in cipher 22 | long slots; ///< number of slots 23 | 24 | //----------------------------------------- 25 | 26 | /** 27 | * Ciphertext = (bx = mx + ex - ax * sx, ax) for secret key sx and error ex 28 | * @param[in] bits: bits in cipher 29 | * @param[in] slots: number of slots 30 | */ 31 | Cipher(ZZX ax = ZZX::zero(), ZZX bx = ZZX::zero(), ZZ mod = ZZ::zero(), long cbits = 0, long slots = 1) : ax(ax), bx(bx), mod(mod), cbits(cbits), slots(slots) {} 32 | 33 | Cipher(const Cipher& o) : ax(o.ax), bx(o.bx), mod(o.mod), cbits(o.cbits), slots(o.slots) {} 34 | 35 | }; 36 | 37 | #endif /* SCHEME_CIPHER_H_ */ 38 | -------------------------------------------------------------------------------- /src/Cipher.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/Cipher.o -------------------------------------------------------------------------------- /src/EvaluatorUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "EvaluatorUtils.h" 2 | 3 | #include 4 | #include 5 | 6 | ZZ EvaluatorUtils::evaluateVal(const double& x, const long& bits) { 7 | return evaluateVal(to_RR(x), bits); 8 | } 9 | 10 | ZZ EvaluatorUtils::evaluateVal(const RR& x, const long& bits) { 11 | RR xp = MakeRR(x.x, x.e + bits); 12 | return RoundToZZ(xp); 13 | } 14 | 15 | CZZ EvaluatorUtils::evaluateVal(const double& xr, const double& xi, const long& bits) { 16 | return evaluateVal(to_RR(xr), to_RR(xi), bits); 17 | } 18 | 19 | CZZ EvaluatorUtils::evaluateVal(const RR& xr, const RR& xi, const long& bits) { 20 | RR xrp = MakeRR(xr.x, xr.e + bits); 21 | RR xip = MakeRR(xi.x, xi.e + bits); 22 | return CZZ(RoundToZZ(xrp), RoundToZZ(xip)); 23 | } 24 | 25 | void EvaluatorUtils::evaluateRRVal(RR& xr, RR& xi, CZZ& x, const long& bits) { 26 | xr = to_RR(x.r); 27 | xr.e -= bits; 28 | xi = to_RR(x.i); 29 | xr.e -= bits; 30 | } 31 | 32 | CZZ EvaluatorUtils::evaluateRandomVal(const long& bits) { 33 | return CZZ(RandomBits_ZZ(bits), RandomBits_ZZ(bits)); 34 | } 35 | 36 | CZZ EvaluatorUtils::evaluateRandomCircleVal(const long& bits) { 37 | RR angle = random_RR(); 38 | RR mr = cos(angle * 2 * Pi); 39 | RR mi = sin(angle * 2 * Pi); 40 | return evaluateVal(mr, mi, bits); 41 | } 42 | 43 | CZZ* EvaluatorUtils::evaluateRandomVals(const long& size, const long& bits) { 44 | CZZ* res = new CZZ[size]; 45 | for (long i = 0; i < size; i++) { 46 | res[i] = CZZ(RandomBits_ZZ(bits), RandomBits_ZZ(bits)); 47 | } 48 | return res; 49 | } 50 | 51 | CZZ* EvaluatorUtils::evaluateRandomZZVals(const long& size, const long& bits) { 52 | CZZ* res = new CZZ[size]; 53 | for (long i = 0; i < size; i++) { 54 | res[i].r = RandomBits_ZZ(bits); 55 | } 56 | return res; 57 | } 58 | 59 | CZZ EvaluatorUtils::evaluatePow(const double& xr, const double& xi, const long& degree, const long& bits) { 60 | long logDegree = log2(degree); 61 | long po2Degree = 1 << logDegree; 62 | CZZ res = evaluatePow2(xr, xi, logDegree, bits); 63 | long remDegree = degree - po2Degree; 64 | if(remDegree > 0) { 65 | CZZ tmp = evaluatePow(xr, xi, remDegree, bits); 66 | res *= tmp; 67 | res >>= bits; 68 | } 69 | return res; 70 | } 71 | 72 | CZZ EvaluatorUtils::evaluatePow(const RR& xr, const RR& xi, const long& degree, const long& bits) { 73 | long logDegree = log2(degree); 74 | long po2Degree = 1 << logDegree; 75 | CZZ res = evaluatePow2(xr, xi, logDegree, bits); 76 | long remDegree = degree - po2Degree; 77 | if(remDegree > 0) { 78 | CZZ tmp = evaluatePow(xr, xi, remDegree, bits); 79 | res *= tmp; 80 | res >>= bits; 81 | } 82 | return res; 83 | } 84 | 85 | CZZ EvaluatorUtils::evaluatePow2(const double& xr, const double& xi, const long& logDegree, const long& bits) { 86 | return evaluatePow2(to_RR(xr), to_RR(xi), logDegree, bits); 87 | } 88 | 89 | CZZ EvaluatorUtils::evaluatePow2(const RR& xr, const RR& xi, const long& logDegree, const long& bits) { 90 | CZZ res = evaluateVal(xr, xi, bits); 91 | for (int i = 0; i < logDegree; ++i) { 92 | res *= res; 93 | res >>= bits; 94 | } 95 | return res; 96 | } 97 | 98 | CZZ* EvaluatorUtils::evaluatePowvec(const double& xr, const double& xi, const long& degree, const long& bits) { 99 | return evaluatePowvec(to_RR(xr), to_RR(xi), degree, bits); 100 | } 101 | 102 | CZZ* EvaluatorUtils::evaluatePowvec(const RR& xr, const RR& xi, const long& degree, const long& bits) { 103 | CZZ* res = new CZZ[degree]; 104 | CZZ m = evaluateVal(xr, xi, bits); 105 | res[0] = m; 106 | for (long i = 0; i < degree - 1; ++i) { 107 | res[i + 1] = (res[i] * m) >> bits; 108 | } 109 | return res; 110 | } 111 | 112 | CZZ* EvaluatorUtils::evaluatePow2vec(const double& xr, const double& xi, const long& logDegree, const long& bits) { 113 | return evaluatePow2vec(to_RR(xr), to_RR(xi), logDegree, bits); 114 | } 115 | 116 | CZZ* EvaluatorUtils::evaluatePow2vec(const RR& xr, const RR& xi, const long& logDegree, const long& bits) { 117 | CZZ* res = new CZZ[logDegree + 1]; 118 | CZZ m = evaluateVal(xr, xi, bits); 119 | res[0] = m; 120 | for (long i = 0; i < logDegree; ++i) { 121 | res[i + 1] = (res[i] * res[i]) >> bits; 122 | } 123 | return res; 124 | } 125 | 126 | CZZ EvaluatorUtils::evaluateInverse(const double& xr, const double& xi, const long& bits) { 127 | return evaluateInverse(to_RR(xr), to_RR(xi), bits); 128 | } 129 | 130 | CZZ EvaluatorUtils::evaluateInverse(const RR& xr, const RR& xi, const long& bits) { 131 | RR xinvr = xr / (xr * xr + xi * xi); 132 | RR xinvi = -xi / (xr * xr + xi * xi); 133 | 134 | return evaluateVal(xinvr, xinvi, bits); 135 | } 136 | 137 | CZZ EvaluatorUtils::evaluateLogarithm(const double& xr, const double& xi, const long& bits) { 138 | double xlogr = log(xr * xr + xi * xi) / 2; 139 | double xlogi = atan(xi / xr); 140 | 141 | return evaluateVal(xlogr, xlogi, bits); 142 | } 143 | 144 | CZZ EvaluatorUtils::evaluateExponent(const double& xr, const double& xi, const long& bits) { 145 | double xrexp = exp(xr); 146 | double xexpr = xrexp * cos(xi); 147 | double xexpi = xrexp * sin(xi); 148 | 149 | return evaluateVal(xexpr, xexpi, bits); 150 | } 151 | 152 | CZZ EvaluatorUtils::evaluateExponent(const RR& xr, const RR& xi, const long& bits) { 153 | RR xrexp = exp(xr); 154 | RR xexpr = xrexp * cos(xi); 155 | RR xexpi = xrexp * sin(xi); 156 | 157 | return evaluateVal(xexpr, xexpi, bits); 158 | } 159 | 160 | CZZ EvaluatorUtils::evaluateSigmoid(const double& xr, const double& xi, const long& bits) { 161 | double xrexp = exp(xr); 162 | double xexpr = xrexp * cos(xi); 163 | double xexpi = xrexp * sin(xi); 164 | 165 | double xsigmoidr = (xexpr * (xexpr + 1) + (xexpi * xexpi)) / ((xexpr + 1) * (xexpr + 1) + (xexpi * xexpi)); 166 | double xsigmoidi = xexpi / ((xexpr + 1) * (xexpr + 1) + (xexpi * xexpi)); 167 | 168 | return evaluateVal(xsigmoidr, xsigmoidi, bits); 169 | } 170 | 171 | CZZ EvaluatorUtils::evaluateSigmoid(const RR& xr, const RR& xi, const long& bits) { 172 | RR xrexp = exp(xr); 173 | RR xexpr = xrexp * cos(xi); 174 | RR xexpi = xrexp * sin(xi); 175 | 176 | RR xsigmoidr = (xexpr * (xexpr + 1) + (xexpi * xexpi)) / ((xexpr + 1) * (xexpr + 1) + (xexpi * xexpi)); 177 | RR xsigmoidi = xexpi / ((xexpr + 1) * (xexpr + 1) + (xexpi * xexpi)); 178 | 179 | return evaluateVal(xsigmoidr, xsigmoidi, bits); 180 | } 181 | 182 | void EvaluatorUtils::leftShiftAndEqual(CZZ*& vals, const long& size, const long& bits) { 183 | for (long i = 0; i < size; ++i) { 184 | vals[i] <<= bits; 185 | } 186 | } 187 | 188 | void EvaluatorUtils::leftRotateAndEqual(CZZ*& vals, const long& size, const long& rotSize) { 189 | long remrotSize = rotSize % size; 190 | if(remrotSize != 0) { 191 | long divisor = GCD(remrotSize, size); 192 | long steps = size / divisor; 193 | for (long i = 0; i < divisor; ++i) { 194 | CZZ tmp = vals[i]; 195 | long idx = i; 196 | for (long j = 0; j < steps - 1; ++j) { 197 | vals[idx] = vals[(idx + remrotSize) % size]; 198 | idx = (idx + remrotSize) % size; 199 | } 200 | vals[idx] = tmp; 201 | } 202 | } 203 | } 204 | 205 | void EvaluatorUtils::rightRotateAndEqual(CZZ*& vals, const long& size, const long& rotSize) { 206 | long remrotSize = rotSize % size; 207 | long leftremrotSize = (size - remrotSize) % size; 208 | leftRotateAndEqual(vals, size, leftremrotSize); 209 | } 210 | -------------------------------------------------------------------------------- /src/EvaluatorUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_EVALUATORUTILS_H_ 2 | #define UTILS_EVALUATORUTILS_H_ 3 | 4 | #include 5 | 6 | #include "SchemeAux.h" 7 | #include "CZZ.h" 8 | 9 | using namespace NTL; 10 | 11 | class EvaluatorUtils { 12 | public: 13 | 14 | /** 15 | * evaluates RR values x.r >> bits, x.i >> bits 16 | * @param[out] real part x.r >> bits 17 | * @param[out] imaginary part x.i >> bits 18 | * @param[in] shifting bits 19 | */ 20 | static void evaluateRRVal(RR& xr, RR& xi, CZZ& x, const long& bits); 21 | 22 | /** 23 | * evaluates value xr << bits 24 | * @param[in] x 25 | * @param[in] bits 26 | * @return x << bits 27 | */ 28 | static ZZ evaluateVal(const double& x, const long& bits); 29 | 30 | /** 31 | * evaluates value xr << bits 32 | * @param[in] x 33 | * @param[in] bits 34 | * @return x << bits 35 | */ 36 | static ZZ evaluateVal(const RR& x, const long& bits); 37 | 38 | /** 39 | * evaluates Z[i] value (xr + i * xi) << bits 40 | * @param[in] real part 41 | * @param[in] imaginary part 42 | * @param[in] bits 43 | * @return Z[i] value (xr + i * xi) << bits 44 | */ 45 | static CZZ evaluateVal(const double& xr, const double& xi, const long& bits); 46 | 47 | /** 48 | * evaluates Z[i] value (xr + i * xi) << bits 49 | * @param[in] real part 50 | * @param[in] imaginary part 51 | * @param[in] bits 52 | * @return Z[i] value (xr + i * xi) << bits 53 | */ 54 | static CZZ evaluateVal(const RR& xr, const RR& xi, const long& bits); 55 | 56 | /** 57 | * evaluates random bits in Z[i] 58 | * @param[in] bits 59 | * @return random bits in Z[i] 60 | */ 61 | static CZZ evaluateRandomVal(const long& bits); 62 | 63 | /** 64 | * evaluates random bits in Z[i] 65 | * @param[in] bits 66 | * @return random bits in Z[i] 67 | */ 68 | static CZZ evaluateRandomCircleVal(const long& bits); 69 | 70 | /** 71 | * evaluates array of random bits in Z[i] 72 | * @param[in] size of array 73 | * @param[in] bits 74 | * @return array of random bits in Z[i] 75 | */ 76 | static CZZ* evaluateRandomVals(const long& size, const long& bits); 77 | 78 | static CZZ* evaluateRandomZZVals(const long& size, const long& bits); 79 | //----------------------------------------- 80 | 81 | /** 82 | * evaluates Z[i] value (xr + i * xi)^d << bits 83 | * @param[in] real part 84 | * @param[in] imaginary part 85 | * @param[in] power degree 86 | * @param[in] bits 87 | * @return Z[i] value (xr + i * xi)^d << bits 88 | */ 89 | static CZZ evaluatePow(const double& xr, const double& xi, const long& degree, const long& bits); 90 | 91 | /** 92 | * evaluates Z[i] value (xr + i * xi)^d << bits 93 | * @param[in] real part 94 | * @param[in] imaginary part 95 | * @param[in] power degree 96 | * @param[in] bits 97 | * @return Z[i] value (xr + i * xi)^d << bits 98 | */ 99 | static CZZ evaluatePow(const RR& xr, const RR& xi, const long& degree, const long& bits); 100 | 101 | /** 102 | * evaluates Z[i] value (xr + i * xi)^d << bits 103 | * @param[in] real part 104 | * @param[in] imaginary part 105 | * @param[in] log(degree) 106 | * @param[in] bits 107 | * @return Z[i] value (xr + i * xi)^d << bits 108 | */ 109 | static CZZ evaluatePow2(const double& xr, const double& xi, const long& logDegree, const long& bits); 110 | 111 | /** 112 | * evaluates Z[i] value (xr + i * xi)^d << bits 113 | * @param[in] real part 114 | * @param[in] imaginary part 115 | * @param[in] log(degree) 116 | * @param[in] bits 117 | * @return Z[i] value (xr + i * xi)^d << bits 118 | */ 119 | static CZZ evaluatePow2(const RR& xr, const RR& xi, const long& logDegree, const long& bits); 120 | 121 | //----------------------------------------- 122 | 123 | /** 124 | * evaluates array of Z[i] values (xr + i * xi)^j << bits for j=1,...,d 125 | * @param[in] real part 126 | * @param[in] imaginary part 127 | * @param[in] power degree 128 | * @param[in] bits 129 | * @return array of Z[i] values (xr + i * xi)^j << bits for j=1,...,d 130 | */ 131 | static CZZ* evaluatePowvec(const double& xr, const double& xi, const long& degree, const long& bits); 132 | 133 | /** 134 | * evaluates array of Z[i] values (xr + i * xi)^j << bits for j=1,...,d 135 | * @param[in] real part 136 | * @param[in] imaginary part 137 | * @param[in] power degree 138 | * @param[in] bits 139 | * @return array of Z[i] values (xr + i * xi)^j << bits for j=1,...,d 140 | */ 141 | static CZZ* evaluatePowvec(const RR& xr, const RR& xi, const long& degree, const long& bits); 142 | 143 | /** 144 | * evaluates array of Z[i] values (xr + i * xi)^j << bits for j=1,2,2^2,...,d 145 | * @param[in] real part 146 | * @param[in] imaginary part 147 | * @param[in] log(d) 148 | * @param[in] bits 149 | * @return array of Z[i] values (xr + i * xi)^j << bits for j=1,2,2^2,...,d 150 | */ 151 | static CZZ* evaluatePow2vec(const double& xr, const double& xi, const long& logDegree, const long& bits); 152 | 153 | /** 154 | * evaluates array of Z[i] values (xr + i * xi)^j << bits for j=1,2,2^2,...,d 155 | * @param[in] real part 156 | * @param[in] imaginary part 157 | * @param[in] log(d) 158 | * @param[in] bits 159 | * @return array of Z[i] values (xr + i * xi)^j << bits for j=1,2,2^2,...,d 160 | */ 161 | static CZZ* evaluatePow2vec(const RR& xr, const RR& xi, const long& logDegree, const long& bits); 162 | 163 | //----------------------------------------- 164 | 165 | /** 166 | * evaluates Z[i] value 1 / (xr + i * xi) << (2 * bits) 167 | * @param[in] real part 168 | * @param[in] imaginary part 169 | * @param[in] bits 170 | * @return Z[i] value 1 / (xr + i * xi) << (2 * bits) 171 | */ 172 | static CZZ evaluateInverse(const double& xr, const double& xi, const long& bits); 173 | 174 | /** 175 | * evaluates Z[i] value 1 / (xr + i * xi) << (2 * bits) 176 | * @param[in] real part 177 | * @param[in] imaginary part 178 | * @param[in] log(p) 179 | * @return Z[i] value 1 / (xr + i * xi) << (2 * bits) 180 | */ 181 | static CZZ evaluateInverse(const RR& xr, const RR& xi, const long& bits); 182 | 183 | /** 184 | * evaluates Z[i] value log(xr + i * xi) << bits 185 | * @param[in] real part 186 | * @param[in] imaginary part 187 | * @param[in] bits 188 | * @return Z[i] value log(xr + i * xi) << bits 189 | */ 190 | static CZZ evaluateLogarithm(const double& xr, const double& xi, const long& bits); 191 | 192 | /** 193 | * evaluates Z[i] value exp(xr + i * xi) << bits 194 | * @param[in] real part 195 | * @param[in] imaginary part 196 | * @param[in] bits 197 | * @return Z[i] value exp(xr + i * xi) << bits 198 | */ 199 | static CZZ evaluateExponent(const double& xr, const double& xi, const long& bits); 200 | 201 | /** 202 | * evaluates Z[i] value exp(xr + i * xi) << bits 203 | * @param[in] real part 204 | * @param[in] imaginary part 205 | * @param[in] bits 206 | * @return Z[i] value exp(xr + i * xi) << bits 207 | */ 208 | static CZZ evaluateExponent(const RR& xr, const RR& xi, const long& bits); 209 | 210 | /** 211 | * evaluates Z[i] value sigmoid(xr + i * xi) << bits 212 | * @param[in] real part 213 | * @param[in] imaginary part 214 | * @param[in] bits 215 | * @return Z[i] value sigmoid(xr + i * xi) << bits 216 | */ 217 | static CZZ evaluateSigmoid(const double& xr, const double& xi, const long& bits); 218 | 219 | /** 220 | * evaluates Z[i] value sigmoid(xr + i * xi) << bits 221 | * @param[in] real part 222 | * @param[in] imaginary part 223 | * @param[in] bits 224 | * @return Z[i] value sigmoid(xr + i * xi) << bits 225 | */ 226 | static CZZ evaluateSigmoid(const RR& xr, const RR& xi, const long& bits); 227 | 228 | //----------------------------------------- 229 | 230 | /** 231 | * left shift array of values by bits 232 | * @param[in, out] array of values 233 | * @param[in] array size 234 | * @param[in] bits 235 | */ 236 | static void leftShiftAndEqual(CZZ*& vals, const long& size, const long& bits); 237 | 238 | //----------------------------------------- 239 | 240 | /** 241 | * left indexes rotation of values 242 | * @param[in, out] array of values 243 | * @param[in] array size 244 | * @param[in] rotation size 245 | */ 246 | static void leftRotateAndEqual(CZZ*& vals, const long& size, const long& rotSize); 247 | 248 | /** 249 | * right indexes rotation of values 250 | * @param[in, out] array of values 251 | * @param[in] array size 252 | * @param[in] rotation size 253 | */ 254 | static void rightRotateAndEqual(CZZ*& vals, const long& size, const long& rotSize); 255 | //----------------------------------------- 256 | }; 257 | 258 | #endif /* UTILS_EVALUATORUTILS_H_ */ 259 | -------------------------------------------------------------------------------- /src/EvaluatorUtils.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/EvaluatorUtils.o -------------------------------------------------------------------------------- /src/HEAAN.cpp: -------------------------------------------------------------------------------- 1 | #include "TestScheme.h" 2 | 3 | int main() { 4 | 5 | //----------------------------------------- 6 | 7 | /* 8 | * Params: logN, logq, precisionBits, logSlots 9 | * Suggested: 13, 65, 30, 3 10 | */ 11 | 12 | // TestScheme::testEncodeBatch(13, 65, 30, 3); 13 | 14 | /* 15 | * Params: logN, logq, precisionBits, logSlots 16 | * Suggested: 13, 65, 30, 3 17 | */ 18 | 19 | // TestScheme::testConjugateBatch(13, 65, 30, 3); 20 | 21 | /* 22 | * Params: logN, logq, precisionBits, logSlots 23 | * Suggested: 13, 65, 30, 3 24 | */ 25 | 26 | // TestScheme::testimultBatch(13, 65, 30, 3); 27 | 28 | //----------------------------------------- 29 | 30 | /* 31 | * Params: logN, logq, precisionBits, rotlogSlots, logSlots, isLeft 32 | * Suggested: 13, 65, 30, 2, 5, true 33 | */ 34 | 35 | // TestScheme::testRotateByPo2Batch(13, 65, 30, 2, 5, true); 36 | // TestScheme::testRotateBatch(13, 65, 30, 17, 5, true); 37 | 38 | /* 39 | * Params: logN, logq, precisionBits, logSlots 40 | * Suggested: 13, 65, 30, 3 41 | */ 42 | 43 | // TestScheme::testSlotsSum(13, 65, 30, 3); 44 | 45 | //----------------------------------------- 46 | 47 | /* 48 | * Params: logN, logq, precisionBits, logDegree, logSlots 49 | * Suggested: 13, 155, 30, 4, 3 50 | * Suggested: 15, 618, 56, 10, 3 51 | */ 52 | 53 | // TestScheme::testPowerOf2Batch(15, 618, 56, 10, 14); 54 | 55 | //----------------------------------------- 56 | 57 | /* 58 | * Params: logN, logq, precisionBits, degree, logSlots 59 | * Suggested: 13, 155, 30, 13, 3 60 | * Suggested: 15, 618, 56, 903, 3 61 | */ 62 | 63 | // TestScheme::testPowerBatch(15, 618, 56, 903, 3); 64 | 65 | //----------------------------------------- 66 | 67 | /* 68 | * Params: logN, logq, precisionBits, logDegree, logSlots 69 | * Suggested: 13, 155, 30, 4, 3 70 | * Suggested: 15, 618, 56, 10, 3 71 | */ 72 | 73 | // TestScheme::testProdOfPo2Batch(13, 155, 30, 4, 3); 74 | 75 | /* 76 | * Params: logN, logq, precisionBits, degree, logSlots 77 | * Suggested: 13, 155, 30, 13, 3 78 | * Suggested: 15, 618, 56, 903, 3 79 | */ 80 | 81 | // TestScheme::testProdBatch(13, 155, 30, 13, 3); 82 | 83 | //----------------------------------------- 84 | 85 | /* 86 | * Params: logN, logq, precisionBits, invSteps, logSlots 87 | * Suggested: 14, 255, 25, 8, 3 88 | * Suggested: 15, 325, 32, 8, 3 89 | */ 90 | 91 | // TestScheme::testInverseBatch(14, 285, 25, 8, 3); 92 | 93 | //----------------------------------------- 94 | 95 | /* 96 | * Params: logN, logq, long precisionBits, degree, logSlots 97 | * Suggested: 13, 155, 30, 7, 3 98 | */ 99 | 100 | // TestScheme::testLogarithmBatch(13, 155, 30, 7, 3); 101 | 102 | //----------------------------------------- 103 | 104 | /* 105 | * Params: logN, logl, logp, L, degree, logSlots 106 | * Suggested: 13, 155, 30, 7, 3 107 | */ 108 | 109 | // TestScheme::testExponentBatch(13, 155, 30, 7, 3); 110 | 111 | //----------------------------------------- 112 | 113 | /* 114 | * Params: logN, logl, logp, L, degree, logSlots 115 | * Suggested: 13, 155, 30, 7, 3 116 | */ 117 | 118 | // TestScheme::testSigmoidBatch(13, 155, 30, 7, 3); 119 | // TestScheme::testSigmoidBatchLazy(13, 155, 30, 7, 3); 120 | 121 | //----------------------------------------- 122 | 123 | /* 124 | * Params: logN, logl, logp, L, logSlots, logfftdim 125 | * Suggested: 13, 120, 50, 3, 4; 126 | */ 127 | 128 | // TestScheme::testFFTBatch(13, 120, 50, 3, 4); 129 | // TestScheme::testFFTBatchLazy(13, 120, 50, 3, 12); 130 | 131 | /* 132 | * Params: logN, logl, logp, L, logSlots, logfftdim, logHdim 133 | * Suggested: 13, 170, 50, 3, 4, 2; 134 | */ 135 | // TestScheme::testFFTBatchLazyMultipleHadamard(13, 122, 50, 3, 13, 1); 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /src/HEAAN.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/HEAAN.o -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -c -I/usr/local/include -I. -std=c++11 *.cpp 3 | ar rc libheaan.a ../src/*.o 4 | -------------------------------------------------------------------------------- /src/Message.cpp: -------------------------------------------------------------------------------- 1 | #include "Message.h" 2 | -------------------------------------------------------------------------------- /src/Message.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_MESSAGE_H_ 2 | #define SCHEME_MESSAGE_H_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace NTL; 9 | 10 | class Message { 11 | public: 12 | 13 | ZZX mx; ///< message mod X^N + 1 14 | 15 | ZZ mod; 16 | long cbits; ///< bits in cipher 17 | long slots; ///< number of slots 18 | 19 | //----------------------------------------- 20 | 21 | /** 22 | * Message: mx 23 | * @param[in] polynomial mx 24 | * @param[in] bits: bits in cipher 25 | * @param[in] slots: number of slots 26 | */ 27 | Message(ZZX mx = ZZX::zero(), ZZ mod = ZZ::zero(), long cbits = 0, long slots = 1) : mx(mx), mod(mod), cbits(cbits), slots(slots) {} 28 | 29 | Message(const Message& o) : mx(o.mx), mod(o.mod), cbits(o.cbits), slots(o.slots) {} 30 | }; 31 | 32 | #endif /* SCHEME_MESSAGE_H_ */ 33 | -------------------------------------------------------------------------------- /src/Message.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/Message.o -------------------------------------------------------------------------------- /src/NumUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "NumUtils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "CZZ.h" 10 | 11 | void NumUtils::sampleGauss(ZZX& res, const long& size, const double& stdev) { 12 | static double const Pi = 4.0 * atan(1.0); 13 | static long const bignum = 0xfffffff; 14 | res.SetLength(size); 15 | 16 | for (long i = 0; i < size; i+=2) { 17 | double r1 = (1 + RandomBnd(bignum)) / ((double)bignum + 1); 18 | double r2 = (1 + RandomBnd(bignum)) / ((double)bignum + 1); 19 | double theta=2 * Pi * r1; 20 | double rr= sqrt(-2.0 * log(r2)) * stdev; 21 | assert(rr < 8 * stdev); // sanity-check, no more than 8 standard deviations 22 | // Generate two Gaussians RV's, rounded to integers 23 | long x1 = (long) floor(rr * cos(theta) + 0.5); 24 | SetCoeff(res, i, x1); 25 | if(i + 1 < size) { 26 | long x2 = (long) floor(rr * sin(theta) + 0.5); 27 | SetCoeff(res, i + 1, x2); 28 | } 29 | } 30 | } 31 | 32 | void NumUtils::sampleHWT(ZZX& res, const long& size, const long& h) { 33 | res.SetLength(size); 34 | long idx = 0; 35 | ZZ tmp = RandomBits_ZZ(h); 36 | while(idx < h) { 37 | long i = RandomBnd(size); 38 | if(res.rep[i] == 0) { 39 | res.rep[i] = (bit(tmp, idx) == 0) ? ZZ(1) : ZZ(-1); 40 | idx++; 41 | } 42 | } 43 | } 44 | 45 | void NumUtils::sampleZO(ZZX& res, const long& size) { 46 | res.SetLength(size); 47 | ZZ tmp = RandomBits_ZZ(2 * size); 48 | for (long i = 0; i < size; ++i) { 49 | res.rep[i] = (bit(tmp, 2 * i) == 0) ? ZZ(0) : (bit(tmp, 2 * i + 1) == 0) ? ZZ(1) : ZZ(-1); 50 | } 51 | } 52 | 53 | void NumUtils::sampleBinary(ZZX& res, const long& size, const long& h) { 54 | res.SetLength(size); 55 | long idx = 0; 56 | while(idx < h) { 57 | long i = RandomBnd(size); 58 | if(res.rep[i] == 0) { 59 | res.rep[i] = ZZ(1); 60 | idx++; 61 | } 62 | } 63 | } 64 | 65 | void NumUtils::sampleBinary(ZZX& res, const long& size) { 66 | res.SetLength(size); 67 | ZZ tmp = RandomBits_ZZ(size); 68 | for (long i = 0; i < size; ++i) { 69 | res.rep[i] = (bit(tmp, i) == 0) ? ZZ(0) : ZZ(1); 70 | } 71 | } 72 | 73 | void NumUtils::sampleUniform2(ZZX& res, const long& size, const long& logBnd) { 74 | res.SetLength(size); 75 | for (long i = 0; i < size; i++) { 76 | res.rep[i] = RandomBits_ZZ(logBnd); 77 | } 78 | } 79 | 80 | void NumUtils::fftRaw(CZZ*& vals, const long& size, SchemeAux& aux, const bool& isForward) { 81 | for (long i = 1, j = 0; i < size; ++i) { 82 | long bit = size >> 1; 83 | for (; j >= bit; bit>>=1) { 84 | j -= bit; 85 | } 86 | j += bit; 87 | if(i < j) { 88 | swap(vals[i], vals[j]); 89 | } 90 | } 91 | if(isForward) { 92 | for (long len = 2; len <= size; len <<= 1) { 93 | long MoverLen = aux.M / len; 94 | for (long i = 0; i < size; i += len) { 95 | for (long j = 0; j < len / 2; ++j) { 96 | CZZ u = vals[i + j]; 97 | CZZ v = vals[i + j + len / 2]; 98 | RR tmp1 = to_RR(v.r) * (aux.ksiPowsr[j * MoverLen] + aux.ksiPowsi[j * MoverLen]); 99 | RR tmpr = tmp1 - to_RR(v.r + v.i) * aux.ksiPowsi[j * MoverLen]; 100 | RR tmpi = tmp1 + to_RR(v.i - v.r) * aux.ksiPowsr[j * MoverLen]; 101 | v.r = to_ZZ(tmpr); 102 | v.i = to_ZZ(tmpi); 103 | vals[i + j] = u + v; 104 | vals[i + j + len / 2] = u - v; 105 | } 106 | } 107 | } 108 | } else { 109 | for (long len = 2; len <= size; len <<= 1) { 110 | long MoverLen = aux.M / len; 111 | for (long i = 0; i < size; i += len) { 112 | for (long j = 0; j < len / 2; ++j) { 113 | CZZ u = vals[i + j]; 114 | CZZ v = vals[i + j + len / 2]; 115 | RR tmp1 = to_RR(v.r) * (aux.ksiPowsr[(len - j) * MoverLen] + aux.ksiPowsi[(len - j) * MoverLen]); 116 | RR tmpr = tmp1 - to_RR(v.r + v.i) * aux.ksiPowsi[(len - j) * MoverLen]; 117 | RR tmpi = tmp1 + to_RR(v.i - v.r) * aux.ksiPowsr[(len - j) * MoverLen]; 118 | v.r = to_ZZ(tmpr); 119 | v.i = to_ZZ(tmpi); 120 | vals[i + j] = u + v; 121 | vals[i + j + len / 2] = u - v; 122 | } 123 | } 124 | } 125 | } 126 | } 127 | 128 | void NumUtils::fft(CZZ*& vals, const long& size, SchemeAux& aux) { 129 | fftRaw(vals, size, aux, true); 130 | } 131 | 132 | void NumUtils::fftInv(CZZ*& vals, const long& size, SchemeAux& aux) { 133 | fftRaw(vals, size, aux, false); 134 | long logSize = log2(size); 135 | for (long i = 0; i < size; ++i) { 136 | vals[i] >>= logSize; 137 | } 138 | } 139 | 140 | void NumUtils::fftInvLazy(CZZ*& vals, const long& size, SchemeAux& aux) { 141 | fftRaw(vals, size, aux, false); 142 | } 143 | 144 | void NumUtils::fftSpecial(CZZ*& vals, const long& size, SchemeAux& aux) { 145 | for (int i = 1, j = 0; i < size; ++i) { 146 | long bit = size >> 1; 147 | for (; j>=bit; bit>>=1) { 148 | j -= bit; 149 | } 150 | j += bit; 151 | if(i < j) { 152 | swap(vals[i], vals[j]); 153 | } 154 | } 155 | for (long len = 2; len <= size; len <<= 1) { 156 | long loglen = log2(len); 157 | long Mover2Len = aux.M / len / 2; 158 | for (long i = 0; i < size; i += len) { 159 | for (long j = 0; j < len / 2; ++j) { 160 | CZZ u = vals[i + j]; 161 | CZZ v = vals[i + j + len / 2]; 162 | RR tmp1 = to_RR(v.r) * (aux.ksiPowsr[(2 * j + 1) * Mover2Len] + aux.ksiPowsi[(2 * j + 1) * Mover2Len]); 163 | RR tmpr = tmp1 - to_RR(v.r + v.i) * aux.ksiPowsi[(2 * j + 1) * Mover2Len]; 164 | RR tmpi = tmp1 + to_RR(v.i - v.r) * aux.ksiPowsr[(2 * j + 1) * Mover2Len]; 165 | v.r = to_ZZ(tmpr); 166 | v.i = to_ZZ(tmpi); 167 | vals[i + j] = u + v; 168 | vals[i + j + len / 2] = u - v; 169 | } 170 | } 171 | } 172 | } 173 | 174 | void NumUtils::fftSpecialInv(CZZ*& vals, const long& size, SchemeAux& aux) { 175 | fftRaw(vals, size, aux, false); 176 | long logsize = log2(size); 177 | long Mover2size = aux.M / size / 2; 178 | for (long i = 0; i < size; ++i) { 179 | RR tmp1 = to_RR(vals[i].r) * (aux.ksiPowsr[(2 * size - i) * Mover2size] + aux.ksiPowsi[(2 * size - i) * Mover2size]); 180 | RR tmpr = tmp1 - to_RR(vals[i].r + vals[i].i) * aux.ksiPowsi[(2 * size - i) * Mover2size]; 181 | RR tmpi = tmp1 + to_RR(vals[i].i - vals[i].r) * aux.ksiPowsr[(2 * size - i) * Mover2size]; 182 | vals[i].r = to_ZZ(tmpr); 183 | vals[i].i = to_ZZ(tmpi); 184 | vals[i] >>= logsize; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/NumUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_NUMUTILS_H_ 2 | #define UTILS_NUMUTILS_H_ 3 | 4 | #include 5 | #include 6 | #include "SchemeAux.h" 7 | #include "CZZ.h" 8 | 9 | using namespace NTL; 10 | 11 | class NumUtils { 12 | public: 13 | 14 | //----------------------------------------- 15 | 16 | /** 17 | * samples polynomial with random Gaussians coefficients 18 | * @param[out] ZZX polynomial 19 | * @param[in] long polynomial degree 20 | * @param[in] standard deviation 21 | */ 22 | static void sampleGauss(ZZX& res, const long& size, const double& stdev); 23 | 24 | /** 25 | * samples polynomial with random {-1,0,1} coefficients 26 | * @param[out] ZZX polynomial 27 | * @param[in] long polynomial degree 28 | * @param[in] number of nonzero coefficients 29 | */ 30 | static void sampleHWT(ZZX& res, const long& size, const long& h); 31 | 32 | /** 33 | * samples polynomial with random {-1,0,1} coefficients 34 | * @param[out] ZZX polynomial 35 | * @param[in] long polynomial degree 36 | */ 37 | static void sampleZO(ZZX& res, const long& size); 38 | 39 | /** 40 | * samples polynomial with random {0,1} coefficients 41 | * @param[out] ZZX polynomial 42 | * @param[in] long polynomial degree 43 | * @param[in] number of nonzero coefficients 44 | */ 45 | static void sampleBinary(ZZX& res, const long& size, const long& h); 46 | 47 | /** 48 | * samples polynomial with random {0,1} coefficients 49 | * @param[out] ZZX polynomial 50 | * @param[in] long polynomial degree 51 | */ 52 | static void sampleBinary(ZZX& res, const long& size); 53 | 54 | /** 55 | * samples polynomial with random uniform coefficients in [0, 2^logBnd-1] 56 | * @param[out] ZZX polynomial 57 | * @param[in] long polynomial degree 58 | * @param[in] long log(bound) 59 | */ 60 | static void sampleUniform2(ZZX& res, const long& size, const long& logBnd); 61 | 62 | //----------------------------------------- 63 | 64 | /** 65 | * calculates pre fft in Z_q[X] / (X^N + 1) 66 | * @param[in, out] arrays of vals 67 | * @param[in] size of array 68 | * @param[in] auxiliary information 69 | * @param[in] auxiliary information 70 | * @return pre fft 71 | */ 72 | static void fftRaw(CZZ*& vals, const long& size, SchemeAux& aux, const bool& isForward); 73 | 74 | /** 75 | * calculates fft in Z_q[X] / (X^N + 1) 76 | * @param[in, out] arrays of vals 77 | * @param[in] size of array 78 | * @param[in] auxiliary information 79 | * @param[in] auxiliary information 80 | */ 81 | static void fft(CZZ*& vals, const long& size, SchemeAux& aux); 82 | 83 | /** 84 | * calculates fft inverse in Z_q[X] / (X^N + 1) 85 | * @param[in, out] arrays of vals 86 | * @param[in] size of array 87 | * @param[in] auxiliary information 88 | * @param[in] auxiliary information 89 | */ 90 | static void fftInv(CZZ*& vals, const long& size, SchemeAux& aux); 91 | 92 | /** 93 | * calculates fft inverse without last division by size in Z_q[X] / (X^N + 1) 94 | * @param[in, out] arrays of vals 95 | * @param[in] size of array 96 | * @param[in] auxiliary information 97 | * @param[in] auxiliary information 98 | */ 99 | static void fftInvLazy(CZZ*& vals, const long& size, SchemeAux& aux); 100 | 101 | //----------------------------------------- 102 | 103 | /** 104 | * calculates special fft in Z_q[X] / (X^N + 1) needed for encoding/decoding 105 | * @param[in] arrays of vals 106 | * @param[in] size of array 107 | * @param[in] auxiliary information 108 | * @param[in] auxiliary information 109 | */ 110 | static void fftSpecial(CZZ*& vals, const long& size, SchemeAux& aux); 111 | 112 | /** 113 | * calculates special fft inverse in Z_q[X] / (X^N + 1) needed for encoding/decoding 114 | * @param[in] arrays of vals 115 | * @param[in] size of array 116 | * @param[in] auxiliary information 117 | * @param[in] auxiliary information 118 | */ 119 | static void fftSpecialInv(CZZ*& vals, const long& size, SchemeAux& aux); 120 | 121 | //----------------------------------------- 122 | }; 123 | 124 | #endif /* UTILS_NUMUTILS_H_ */ 125 | -------------------------------------------------------------------------------- /src/NumUtils.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/NumUtils.o -------------------------------------------------------------------------------- /src/Params.cpp: -------------------------------------------------------------------------------- 1 | #include "Params.h" 2 | 3 | #include 4 | 5 | Params::Params(long logN, long logq, double sigma, long h) : 6 | logN(logN), logq(logq), sigma(sigma), h(h) { 7 | //----------------------------------------- 8 | N = 1 << logN; 9 | logqq = 2 * logq; 10 | q = power2_ZZ(logq); 11 | qq = power2_ZZ(logqq); 12 | 13 | rotGroup = new long[N / 2]; 14 | 15 | long val = 1; 16 | long N2 = N << 1; 17 | for (long i = 0; i < N / 2; ++i) { 18 | rotGroup[i] = val; 19 | val *= 5; 20 | val %= N2; 21 | } 22 | } 23 | 24 | long Params::suggestlogN(long lambda, long logq) { 25 | long res = 2 * logq * (lambda + 110) / 7.2; 26 | double logres = log2(res); 27 | return (long)ceil(logres); 28 | } 29 | -------------------------------------------------------------------------------- /src/Params.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_PARAMS_H_ 2 | #define SCHEME_PARAMS_H_ 3 | 4 | #include 5 | 6 | using namespace std; 7 | using namespace NTL; 8 | 9 | class Params { 10 | public: 11 | 12 | long logN; ///< N is a power of 2 that corresponds to the ring Z[X] / (X^N + 1) 13 | long logq; ///< q corresponds to the highest modulus 14 | double sigma; ///< sigma corresponds to standard deviation for error and secret key coefficients generation from Gaussian distribution 15 | long h; ///< hamming weight of secret key 16 | 17 | 18 | long N; 19 | long logqq; ///< qq = q * q 20 | 21 | ZZ q; 22 | ZZ qq; 23 | 24 | long* rotGroup; ///< auxiliary information about rotation group indexes for batch encoding 25 | 26 | 27 | /** 28 | *@param[in] N is a power of 2 that corresponds to the ring Z[X] / (X^N + 1) 29 | *@param[in] q is a power of 2 that corresponds to the highest modulus 30 | *@param[in] sigma corresponds to standard deviation for error and secret key coefficients generation from Gaussian distribution 31 | */ 32 | Params(long logN, long logq, double sigma = 3.2, long h = 64); 33 | 34 | 35 | /** 36 | * suggests logN value. 37 | * @param[in] lambda - security parameter 38 | * @param[in] logq value 39 | */ 40 | static long suggestlogN(long lambda, long logq); 41 | 42 | }; 43 | 44 | #endif /* SCHEME_PARAMS_H_ */ 45 | -------------------------------------------------------------------------------- /src/Params.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/Params.o -------------------------------------------------------------------------------- /src/PubKey.cpp: -------------------------------------------------------------------------------- 1 | #include "PubKey.h" 2 | 3 | #include "NumUtils.h" 4 | #include "Params.h" 5 | #include "Ring2Utils.h" 6 | 7 | PubKey::PubKey(Params& params, SecKey& secretKey) { 8 | ZZX ex, sxsx; 9 | 10 | NumUtils::sampleUniform2(ax, params.N, params.logq); 11 | NumUtils::sampleGauss(ex, params.N, params.sigma); 12 | Ring2Utils::mult(bx, secretKey.sx, ax, params.q, params.N); 13 | Ring2Utils::sub(bx, ex, bx, params.q, params.N); 14 | 15 | //----------------------------------------- 16 | 17 | axLeftRot = new ZZX[params.logN - 1]; 18 | bxLeftRot = new ZZX[params.logN - 1]; 19 | 20 | for (long i = 0; i < (params.logN - 1); ++i) { 21 | ZZX spow; 22 | long ipow = (1 << i); 23 | Ring2Utils::inpower(spow, secretKey.sx, params.rotGroup[ipow], params.q, params.N); 24 | Ring2Utils::leftShiftAndEqual(spow, params.logq, params.qq, params.N); 25 | NumUtils::sampleUniform2(axLeftRot[i], params.N, params.logqq); 26 | NumUtils::sampleGauss(ex, params.N, params.sigma); 27 | Ring2Utils::addAndEqual(ex, spow, params.qq, params.N); 28 | Ring2Utils::mult(bxLeftRot[i], secretKey.sx, axLeftRot[i], params.qq, params.N); 29 | Ring2Utils::sub(bxLeftRot[i], ex, bxLeftRot[i], params.qq, params.N); 30 | } 31 | 32 | axRightRot = new ZZX[params.logN - 1]; 33 | bxRightRot = new ZZX[params.logN - 1]; 34 | 35 | for (long i = 0; i < (params.logN - 1); ++i) { 36 | ZZX spow; 37 | long ipow = params.N/2 - (1 << i); 38 | Ring2Utils::inpower(spow, secretKey.sx, params.rotGroup[ipow], params.q, params.N); 39 | Ring2Utils::leftShiftAndEqual(spow, params.logq, params.qq, params.N); 40 | NumUtils::sampleUniform2(axRightRot[i], params.N, params.logqq); 41 | NumUtils::sampleGauss(ex, params.N, params.sigma); 42 | Ring2Utils::addAndEqual(ex, spow, params.qq, params.N); 43 | Ring2Utils::mult(bxRightRot[i], secretKey.sx, axRightRot[i], params.qq, params.N); 44 | Ring2Utils::sub(bxRightRot[i], ex, bxRightRot[i], params.qq, params.N); 45 | } 46 | 47 | //----------------------------------------- 48 | 49 | Ring2Utils::mult(sxsx, secretKey.sx, secretKey.sx, params.q, params.N); 50 | Ring2Utils::leftShiftAndEqual(sxsx, params.logq, params.qq, params.N); 51 | NumUtils::sampleUniform2(axStar, params.N, params.logqq); 52 | NumUtils::sampleGauss(ex, params.N, params.sigma); 53 | Ring2Utils::addAndEqual(ex, sxsx, params.qq, params.N); 54 | Ring2Utils::mult(bxStar, secretKey.sx, axStar, params.qq, params.N); 55 | Ring2Utils::sub(bxStar, ex, bxStar, params.qq, params.N); 56 | 57 | ZZX sxconj; 58 | Ring2Utils::conjugate(sxconj, secretKey.sx, params.N); 59 | Ring2Utils::leftShiftAndEqual(sxconj, params.logq, params.qq, params.N); 60 | NumUtils::sampleUniform2(axConj, params.N, params.logqq); 61 | NumUtils::sampleGauss(ex, params.N, params.sigma); 62 | Ring2Utils::addAndEqual(ex, sxconj, params.qq, params.N); 63 | Ring2Utils::mult(bxConj, secretKey.sx, axConj, params.qq, params.N); 64 | Ring2Utils::sub(bxConj, ex, bxConj, params.qq, params.N); 65 | 66 | //----------------------------------------- 67 | } 68 | -------------------------------------------------------------------------------- /src/PubKey.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_PUBKEY_H_ 2 | #define SCHEME_PUBKEY_H_ 3 | 4 | #include 5 | 6 | #include "SecKey.h" 7 | 8 | using namespace std; 9 | using namespace NTL; 10 | 11 | class PubKey { 12 | public: 13 | 14 | ZZX ax; ///<< information for symmetric encryption 15 | ZZX bx; ///<< information for symmetric encryption 16 | 17 | ZZX axStar; ///<< auxiliary information for multiplication 18 | ZZX bxStar; ///<< auxiliary information for multiplication 19 | 20 | ZZX axConj; ///<< auxiliary information for conjugation 21 | ZZX bxConj; ///<< auxiliary information for conjugation 22 | 23 | ZZX* axLeftRot; ///< auxiliary information for rotation 24 | ZZX* bxLeftRot; ///< auxiliary information for rotation 25 | 26 | ZZX* axRightRot; ///< auxiliary information for rotation 27 | ZZX* bxRightRot; ///< auxiliary information for rotation 28 | 29 | //----------------------------------------- 30 | 31 | PubKey(Params& params, SecKey& secretKey); 32 | 33 | //----------------------------------------- 34 | 35 | }; 36 | 37 | #endif /* SCHEME_PUBKEY_H_ */ 38 | -------------------------------------------------------------------------------- /src/PubKey.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/PubKey.o -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | This is our underlying homomorphic encryption scheme, 2 | which is “Homomorphic Encryption for Arithmetic of Approximate Numbers” (HEAAN). 3 | 4 | We referred to its library in gitHub (https://github.com/kimandrik/HEAAN) and 5 | here is the version at 2017/09. 6 | 7 | $ gcc -c -I/usr/local/include -I. -std=c++11 *.cpp 8 | 9 | $ ar rc libheaan.a ../src/*.o 10 | 11 | This will build the HEAAN library “libheaan.a”. 12 | -------------------------------------------------------------------------------- /src/Ring2Utils.cpp: -------------------------------------------------------------------------------- 1 | #include "Ring2Utils.h" 2 | 3 | //----------------------------------------- 4 | 5 | void Ring2Utils::mod(ZZX& res, ZZX& p, ZZ& mod, const long& degree) { 6 | res.SetLength(degree); 7 | for (long i = 0; i < degree; ++i) { 8 | res.rep[i] = p.rep[i] % mod; 9 | } 10 | } 11 | 12 | void Ring2Utils::modAndEqual(ZZX& p, ZZ& mod, const long& degree) { 13 | for (long i = 0; i < degree; ++i) { 14 | p.rep[i] %= mod; 15 | } 16 | } 17 | 18 | void Ring2Utils::add(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 19 | res.SetLength(degree); 20 | for (long i = 0; i < degree; ++i) { 21 | AddMod(res.rep[i], p1.rep[i], p2.rep[i], mod); 22 | } 23 | } 24 | 25 | ZZX Ring2Utils::add(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 26 | ZZX res; 27 | add(res, p1, p2, mod, degree); 28 | return res; 29 | } 30 | 31 | //void Ring2Utils::add(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 32 | // add(res.rx, p1.rx, p2.rx, mod, degree); 33 | // add(res.ix, p1.ix, p2.ix, mod, degree); 34 | //} 35 | 36 | void Ring2Utils::addAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 37 | for (long i = 0; i < degree; ++i) { 38 | AddMod(p1.rep[i], p1.rep[i], p2.rep[i], mod); 39 | } 40 | } 41 | 42 | //void Ring2Utils::addAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 43 | // addAndEqual(p1.rx, p2.rx, mod, degree); 44 | // addAndEqual(p1.ix, p2.ix, mod, degree); 45 | //} 46 | 47 | //----------------------------------------- 48 | 49 | void Ring2Utils::sub(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 50 | res.SetLength(degree); 51 | for (long i = 0; i < degree; ++i) { 52 | AddMod(res.rep[i], p1.rep[i], -p2.rep[i], mod); 53 | } 54 | } 55 | 56 | ZZX Ring2Utils::sub(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 57 | ZZX res; 58 | sub(res, p1, p2, mod, degree); 59 | return res; 60 | } 61 | 62 | //void Ring2Utils::sub(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 63 | // sub(res.rx, p1.rx, p2.rx, mod, degree); 64 | // sub(res.ix, p1.ix, p2.ix, mod, degree); 65 | //} 66 | 67 | void Ring2Utils::subAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 68 | for (long i = 0; i < degree; ++i) { 69 | AddMod(p1.rep[i], p1.rep[i], -p2.rep[i], mod); 70 | } 71 | } 72 | 73 | void Ring2Utils::subAndEqual2(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 74 | for (long i = 0; i < degree; ++i) { 75 | AddMod(p2.rep[i], p1.rep[i], -p2.rep[i], mod); 76 | } 77 | } 78 | 79 | void Ring2Utils::conjugate(ZZX& res, ZZX& p, const long& degree) { 80 | res.SetLength(degree); 81 | res.rep[0] = p.rep[0]; 82 | for (long i = 1; i < degree; ++i) { 83 | res.rep[i] = -p.rep[degree - i]; 84 | } 85 | } 86 | 87 | void Ring2Utils::conjugateAndEqual(ZZX& p, const long& degree) { 88 | for (long i = 0; i < degree / 2; ++i) { 89 | ZZ tmp = p.rep[i]; 90 | p.rep[i] = p.rep[degree - i]; 91 | p.rep[degree - i] = tmp; 92 | } 93 | p.rep[degree / 2] = -p.rep[degree / 2]; 94 | } 95 | 96 | //void Ring2Utils::subAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 97 | // subAndEqual(p1.rx, p2.rx, mod, degree); 98 | // subAndEqual(p1.ix, p2.ix, mod, degree); 99 | //} 100 | 101 | //----------------------------------------- 102 | 103 | void Ring2Utils::mult(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 104 | res.SetLength(degree); 105 | ZZX p; 106 | mul(p, p1, p2); 107 | p.SetLength(2 * degree); 108 | for (long i = 0; i < degree; ++i) { 109 | p.rep[i] %= mod; 110 | p.rep[i + degree] %= mod; 111 | SubMod(res.rep[i], p.rep[i], p.rep[i + degree], mod); 112 | } 113 | } 114 | 115 | ZZX Ring2Utils::mult(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 116 | ZZX res; 117 | mult(res, p1, p2, mod, degree); 118 | return res; 119 | } 120 | 121 | //void Ring2Utils::mult(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 122 | // ZZX tmp1, tmp2, tmp3; 123 | // 124 | // add(tmp1, p1.rx, p1.ix, mod, degree); 125 | // multAndEqual(tmp1, p2.rx, mod, degree); 126 | // 127 | // add(tmp2, p2.rx, p2.ix, mod, degree); 128 | // multAndEqual(tmp2, p1.ix, mod, degree); 129 | // sub(res.rx, tmp1, tmp2, mod, degree); 130 | // 131 | // sub(tmp2, p2.ix, p2.rx, mod, degree); 132 | // multAndEqual(tmp2, p1.rx, mod, degree); 133 | // add(res.ix, tmp1, tmp2, mod, degree); 134 | //} 135 | 136 | //void Ring2Utils::mult(CZZX& res, CZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 137 | // mult(res.rx, p1.rx, p2, mod, degree); 138 | // mult(res.ix, p1.ix, p2, mod, degree); 139 | //} 140 | 141 | void Ring2Utils::multAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 142 | ZZX p; 143 | mul(p, p1, p2); 144 | p.SetLength(2 * degree); 145 | 146 | for (long i = 0; i < degree; ++i) { 147 | p.rep[i] %= mod; 148 | p.rep[i + degree] %= mod; 149 | SubMod(p1.rep[i], p.rep[i], p.rep[i + degree], mod); 150 | } 151 | } 152 | 153 | //void Ring2Utils::multAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree) { 154 | // ZZX tmp1, tmp2, tmp3; 155 | // 156 | // add(tmp1, p1.rx, p1.ix, mod, degree); 157 | // multAndEqual(tmp1, p2.rx, mod, degree); 158 | // 159 | // add(tmp2, p2.rx, p2.ix, mod, degree); 160 | // multAndEqual(tmp2, p1.ix, mod, degree); 161 | // 162 | // sub(tmp3, p2.ix, p2.rx, mod, degree); 163 | // multAndEqual(tmp3, p1.rx, mod, degree); 164 | // 165 | // sub(p1.rx, tmp1, tmp2, mod, degree); 166 | // add(p2.ix, tmp1, tmp3, mod, degree); 167 | //} 168 | 169 | //void Ring2Utils::multAndEqual(CZZX& p1, ZZX& p2, ZZ& mod, const long& degree) { 170 | // multAndEqual(p1.rx, p2, mod, degree); 171 | // multAndEqual(p1.ix, p2, mod, degree); 172 | //} 173 | 174 | //----------------------------------------- 175 | 176 | void Ring2Utils::square(ZZX& res, ZZX& p, ZZ& mod, const long& degree) { 177 | res.SetLength(degree); 178 | ZZX pp; 179 | mul(pp, p, p); 180 | pp.SetLength(2 * degree); 181 | 182 | for (long i = 0; i < degree; ++i) { 183 | pp.rep[i] %= mod; 184 | pp.rep[i + degree] %= mod; 185 | AddMod(res.rep[i], pp.rep[i], -pp.rep[i + degree], mod); 186 | } 187 | } 188 | 189 | ZZX Ring2Utils::square(ZZX& p, ZZ& mod, const long& degree) { 190 | ZZX res; 191 | square(res, p, mod, degree); 192 | return res; 193 | } 194 | 195 | //void Ring2Utils::square(CZZX& res, CZZX& p, ZZ& mod, const long& degree) { 196 | // ZZX tmp1, tmp2; 197 | // 198 | // add(tmp1, p.rx, p.ix, mod, degree); 199 | // sub(tmp2, p.rx, p.ix, mod, degree); 200 | // mult(res.rx, tmp1, tmp2, mod, degree); 201 | // mult(tmp2, p.rx, p.ix, mod, degree); 202 | // add(res.ix, tmp2, tmp2, mod, degree); 203 | //} 204 | 205 | void Ring2Utils::squareAndEqual(ZZX& p, ZZ& mod, const long& degree) { 206 | ZZX pp; 207 | mul(pp, p, p); 208 | pp.SetLength(2 * degree); 209 | 210 | for (long i = 0; i < degree; ++i) { 211 | pp.rep[i] %= mod; 212 | pp.rep[i + degree] %= mod; 213 | AddMod(p.rep[i], pp.rep[i], -pp.rep[i + degree], mod); 214 | } 215 | } 216 | 217 | //void Ring2Utils::squareAndEqual(CZZX& p, ZZ& mod, const long& degree) { 218 | // ZZX tmp1, tmp2; 219 | // 220 | // add(tmp1, p.rx, p.ix, mod, degree); 221 | // sub(tmp2, p.rx, p.ix, mod, degree); 222 | // 223 | // mult(p.rx, tmp1, tmp2, mod, degree); 224 | // multAndEqual(p.ix, p.rx, mod, degree); 225 | // addAndEqual(p.ix, p.ix, mod, degree); 226 | //} 227 | 228 | //----------------------------------------- 229 | 230 | void Ring2Utils::multByMonomial(ZZX& res, ZZX& p, const long& monomialDeg, const long& degree) { 231 | long shift = monomialDeg % (2 * degree); 232 | if(shift == 0) { 233 | res = p; 234 | } 235 | ZZX tmpx; 236 | tmpx.SetLength(degree); 237 | tmpx = (shift < degree) ? p : -p; 238 | shift %= degree; 239 | 240 | res.SetLength(degree); 241 | 242 | for (long i = 0; i < shift; ++i) { 243 | res.rep[i] = -tmpx.rep[degree - shift + i]; 244 | } 245 | 246 | for (long i = shift; i < degree; ++i) { 247 | res.rep[i] = tmpx.rep[i - shift]; 248 | } 249 | } 250 | 251 | ZZX Ring2Utils::multByMonomial(ZZX& p, const long& monomialDeg, const long& degree) { 252 | ZZX res; 253 | multByMonomial(res, p, monomialDeg, degree); 254 | return res; 255 | } 256 | 257 | //void Ring2Utils::multByMonomial(CZZX& res, CZZX& p, const long& monomialDeg, const long& degree) { 258 | // multByMonomial(res.rx, p.rx, monomialDeg, degree); 259 | // multByMonomial(res.ix, p.ix, monomialDeg, degree); 260 | //} 261 | 262 | void Ring2Utils::multByMonomialAndEqual(ZZX& p, const long& monomialDeg, const long& degree) { 263 | long shift = monomialDeg % (2 * degree); 264 | if(shift == 0) { 265 | return; 266 | } 267 | ZZX tmpx; 268 | tmpx.SetLength(degree); 269 | tmpx = (shift < degree) ? p : -p; 270 | shift %= degree; 271 | for (long i = 0; i < shift; ++i) { 272 | p.rep[i] = -tmpx.rep[degree - shift + i]; 273 | } 274 | 275 | for (long i = shift; i < degree; ++i) { 276 | p.rep[i] = tmpx.rep[i - shift]; 277 | } 278 | } 279 | 280 | //void Ring2Utils::multByMonomialAndEqual(CZZX& p, const long& monomialDeg, const long& degree) { 281 | // multByMonomialAndEqual(p.rx, monomialDeg, degree); 282 | // multByMonomialAndEqual(p.ix, monomialDeg, degree); 283 | //} 284 | 285 | //----------------------------------------- 286 | 287 | void Ring2Utils::multByConst(ZZX& res, ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree) { 288 | res.SetLength(degree); 289 | for (long i = 0; i < degree; ++i) { 290 | MulMod(res.rep[i], p.rep[i], cnst, mod); 291 | } 292 | } 293 | 294 | ZZX Ring2Utils::multByConst(ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree) { 295 | ZZX res; 296 | multByConst(res, p, cnst, mod, degree); 297 | return res; 298 | } 299 | 300 | //void Ring2Utils::multByConst(CZZX& res, CZZX& p, const ZZ& cnst, ZZ& mod, const long& degree) { 301 | // multByConst(res.rx, p.rx, cnst, mod, degree); 302 | // multByConst(res.ix, p.ix, cnst, mod, degree); 303 | //} 304 | 305 | //void Ring2Utils::multByConst(CZZX& res, CZZX& p, const CZZ& cnst, ZZ& mod, const long& degree) { 306 | // ZZX tmp1, tmp2, tmp3, tmp4; 307 | // 308 | // add(tmp1, p.rx, p.ix, mod, degree); 309 | // multByConst(tmp2, tmp1, cnst.r, mod, degree); 310 | // 311 | // ZZ tmp = cnst.r + cnst.i; 312 | // multByConst(tmp4, p.ix, tmp, mod, degree); 313 | // 314 | // tmp = cnst.i - cnst.r; 315 | // multByConst(tmp3, p.rx, tmp, mod, degree); 316 | // 317 | // sub(res.rx, tmp2, tmp4, mod, degree); 318 | // add(res.ix, tmp2, tmp3, mod, degree); 319 | //} 320 | 321 | void Ring2Utils::multByConstAndEqual(ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree) { 322 | for (long i = 0; i < degree; ++i) { 323 | MulMod(p.rep[i], p.rep[i], cnst, mod); 324 | } 325 | } 326 | 327 | //void Ring2Utils::multByConstAndEqual(CZZX& p, const ZZ& cnst, ZZ& mod, const long& degree) { 328 | // multByConstAndEqual(p.rx, cnst, mod, degree); 329 | // multByConstAndEqual(p.ix, cnst, mod, degree); 330 | //} 331 | 332 | //void Ring2Utils::multByConstAndEqual(CZZX& p, const CZZ& cnst, ZZ& mod, const long& degree) { 333 | // ZZX tmp1, tmp2, tmp3; 334 | // ZZ tmp; 335 | // add(tmp1, p.rx, p.ix, mod, degree); 336 | // multByConstAndEqual(tmp1, cnst.r, mod, degree); 337 | // 338 | // tmp = cnst.r + cnst.i; 339 | // multByConst(tmp2, p.ix, tmp, mod, degree); 340 | // 341 | // tmp = cnst.i - cnst.r; 342 | // multByConst(tmp3, p.rx, tmp, mod, degree); 343 | // 344 | // sub(p.rx, tmp1, tmp2, mod, degree); 345 | // add(p.ix, tmp1, tmp3, mod, degree); 346 | //} 347 | 348 | //----------------------------------------- 349 | 350 | void Ring2Utils::leftShift(ZZX& res, ZZX& p, const long& bits, ZZ& mod, const long& degree) { 351 | res.SetLength(degree); 352 | for (long i = 0; i < degree; ++i) { 353 | res.rep[i] = p.rep[i] << bits; 354 | res.rep[i] %= mod; 355 | } 356 | } 357 | 358 | //void Ring2Utils::leftShift(CZZX& res, CZZX& p, const long& bits, const long& logMod, const long& degree) { 359 | // leftShift(res.rx, p.rx, bits, logMod, degree); 360 | // leftShift(res.ix, p.ix, bits, logMod, degree); 361 | //} 362 | 363 | void Ring2Utils::leftShiftAndEqual(ZZX& p, const long& bits, ZZ& mod, const long& degree) { 364 | for (long i = 0; i < degree; ++i) { 365 | p.rep[i] <<= bits; 366 | p.rep[i] %= mod; 367 | } 368 | } 369 | 370 | void Ring2Utils::doubleAndEqual(ZZX& p, ZZ& mod, const long& degree) { 371 | for (long i = 0; i < degree; ++i) { 372 | p.rep[i] <<= 1; 373 | p.rep[i] %= mod; 374 | } 375 | } 376 | 377 | //void Ring2Utils::leftShiftAndEqual(CZZX& p, const long& bits, const long& logMod, const long& degree) { 378 | // leftShiftAndEqual(p.rx, bits, logMod, degree); 379 | // leftShiftAndEqual(p.ix, bits, logMod, degree); 380 | //} 381 | 382 | //----------------------------------------- 383 | 384 | void Ring2Utils::rightShift(ZZX& res, ZZX& p, const long& bits, const long& degree) { 385 | res.SetLength(degree); 386 | for (long i = 0; i < degree; ++i) { 387 | res.rep[i] = p.rep[i] >> bits; 388 | } 389 | } 390 | 391 | //void Ring2Utils::rightShift(CZZX& res, CZZX& p, const long& bits, const long& logMod, const long& degree) { 392 | // rightShift(res.rx, p.rx, bits, logMod, degree); 393 | // rightShift(res.ix, p.ix, bits, logMod, degree); 394 | //} 395 | 396 | void Ring2Utils::rightShiftAndEqual(ZZX& p, const long& bits, const long& degree) { 397 | for (long i = 0; i < degree; ++i) { 398 | p.rep[i] >>= bits; 399 | } 400 | } 401 | 402 | //void Ring2Utils::rightShiftAndEqual(CZZX& p, const long& bits, const long& logMod, const long& degree) { 403 | // rightShiftAndEqual(p.rx, bits, logMod, degree); 404 | // rightShiftAndEqual(p.ix, bits, logMod, degree); 405 | //} 406 | 407 | //----------------------------------------- 408 | 409 | void Ring2Utils::inpower(ZZX& res, ZZX& p, const long& pow, ZZ& mod, const long& degree) { 410 | res.SetLength(degree); 411 | for (long i = 0; i < degree; ++i) { 412 | long ipow = i * pow; 413 | long shift = ipow % (2 * degree); 414 | if(shift < degree) { 415 | AddMod(res.rep[shift % degree], res.rep[shift % degree], p.rep[i], mod); 416 | } else { 417 | AddMod(res.rep[shift % degree], res.rep[shift % degree], -p.rep[i], mod); 418 | } 419 | } 420 | } 421 | 422 | ZZX Ring2Utils::inpower(ZZX& p, const long& pow, ZZ& mod, const long& degree) { 423 | ZZX res; 424 | inpower(res, p, pow, mod, degree); 425 | return res; 426 | } 427 | 428 | ZZX* Ring2Utils::bitDecomposition(ZZX& p, const long& logMod, const long& degree) { 429 | ZZX* res = new ZZX[logMod]; 430 | for (long i = 0; i < logMod; ++i) { 431 | res[i].SetLength(degree); 432 | } 433 | 434 | for (long j = 0; j < degree; ++j) { 435 | ZZ coeff = p.rep[j]; 436 | for (long i = 0; i < logMod; ++i) { 437 | res[i].rep[j] = bit(coeff, j); 438 | } 439 | } 440 | return res; 441 | } 442 | 443 | ZZX Ring2Utils::innerProduct(ZZX*& pvec1, ZZX*& pvec2, const long& size, ZZ& mod, const long& degree) { 444 | ZZX res = mult(pvec1[0], pvec2[0], mod, degree); 445 | for (long i = 1; i < size; ++i) { 446 | ZZX termi = mult(pvec1[i], pvec2[i], mod, degree); 447 | addAndEqual(res, termi, mod, degree); 448 | } 449 | return res; 450 | } 451 | -------------------------------------------------------------------------------- /src/Ring2Utils.h: -------------------------------------------------------------------------------- 1 | #ifndef POLYSCHEME_ZRINGUTILS_H_ 2 | #define POLYSCHEME_ZRINGUTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | using namespace NTL; 8 | 9 | class Ring2Utils { 10 | public: 11 | 12 | //----------------------------------------- 13 | 14 | static void mod(ZZX& res, ZZX& p, ZZ& mod, const long& degree); 15 | 16 | static void modAndEqual(ZZX& p, ZZ& mod, const long& degree); 17 | 18 | /** 19 | * addition in ring Z_q[X] / (X^N + 1) 20 | * @param[out] p1 + p2 in Z_q[X] / (X^N + 1) 21 | * @param[in] p1 in Z_q[X] / (X^N + 1) 22 | * @param[in] p2 in Z_q[X] / (X^N + 1) 23 | * @param[in] mod q 24 | * @param[in] degree N 25 | */ 26 | static void add(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 27 | 28 | /** 29 | * addition in ring Z_q[X] / (X^N + 1) 30 | * @param[in] p1 in Z_q[X] / (X^N + 1) 31 | * @param[in] p2 in Z_q[X] / (X^N + 1) 32 | * @param[in] mod q 33 | * @param[in] degree N 34 | * @return p1 + p2 in Z_q[X] / (X^N + 1) 35 | */ 36 | static ZZX add(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 37 | // static void add(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 38 | 39 | /** 40 | * addition in ring Z_q[X] / (X^N + 1) 41 | * @param[in, out] p1 -> p1 + p2 in Z_q[X] / (X^N + 1) 42 | * @param[in] p2 in Z_q[X] / (X^N + 1) 43 | * @param[in] mod q 44 | * @param[in] degree N 45 | */ 46 | static void addAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 47 | 48 | // static void addAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 49 | 50 | //----------------------------------------- 51 | 52 | /** 53 | * substraction in ring Z_q[X] / (X^N + 1) 54 | * @param[out] p1 - p2 in Z_q[X] / (X^N + 1) 55 | * @param[in] p1 in Z_q[X] / (X^N + 1) 56 | * @param[in] p2 in Z_q[X] / (X^N + 1) 57 | * @param[in] mod q 58 | * @param[in] degree N 59 | */ 60 | static void sub(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 61 | 62 | /** 63 | * substraction in ring Z_q[X] / (X^N + 1) 64 | * @param[in] p1 in Z_q[X] / (X^N + 1) 65 | * @param[in] p2 in Z_q[X] / (X^N + 1) 66 | * @param[in] mod q 67 | * @param[in] degree N 68 | * @result p1 - p2 in Z_q[X] / (X^N + 1) 69 | */ 70 | static ZZX sub(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 71 | 72 | // static void sub(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 73 | 74 | 75 | /** 76 | * substraction in ring Z_q[X] / (X^N + 1) 77 | * @param[in, out] p1 -> p1 - p2 in Z_q[X] / (X^N + 1) 78 | * @param[in] p2 in Z_q[X] / (X^N + 1) 79 | * @param[in] mod q 80 | * @param[in] degree N 81 | */ 82 | static void subAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 83 | 84 | /** 85 | * substraction in ring Z_q[X] / (X^N + 1) 86 | * @param[in] p1 in Z_q[X] / (X^N + 1) 87 | * @param[in, out] p2 -> p1 - p2 in Z_q[X] / (X^N + 1) 88 | * @param[in] mod q 89 | * @param[in] degree N 90 | */ 91 | static void subAndEqual2(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 92 | 93 | /** 94 | * conjugation 95 | * @param[out] conj(p) in Z_q[X] / (X^N + 1) 96 | * @param[in] p in Z_q[X] / (X^N + 1) 97 | * @param[in] degree N 98 | */ 99 | static void conjugate(ZZX& res, ZZX& p, const long& degree); 100 | 101 | /** 102 | * conjugation 103 | * @param[in, out] p -> conj(p) in Z_q[X] / (X^N + 1) 104 | * @param[in] p in Z_q[X] / (X^N + 1) 105 | * @param[in] degree N 106 | */ 107 | static void conjugateAndEqual(ZZX& p, const long& degree); 108 | 109 | // static void subAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 110 | 111 | //----------------------------------------- 112 | 113 | /** 114 | * multiplication in ring Z_q[X] / (X^N + 1) 115 | * @param[out] p1 * p2 in Z_q[X] / (X^N + 1) 116 | * @param[in] p1 in Z_q[X] / (X^N + 1) 117 | * @param[in] p2 in Z_q[X] / (X^N + 1) 118 | * @param[in] mod q 119 | * @param[in] degree N 120 | */ 121 | static void mult(ZZX& res, ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 122 | 123 | /** 124 | * multiplication in ring Z_q[X] / (X^N + 1) 125 | * @param[in] p1 in Z_q[X] / (X^N + 1) 126 | * @param[in] p2 in Z_q[X] / (X^N + 1) 127 | * @param[in] mod q 128 | * @param[in] degree N 129 | * @result p1 * p2 in Z_q[X] / (X^N + 1) 130 | */ 131 | static ZZX mult(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 132 | 133 | // static void mult(CZZX& res, CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 134 | // static void mult(CZZX& res, CZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 135 | 136 | /** 137 | * multiplication in ring Z_q[X] / (X^N + 1) 138 | * @param[in, out] p1 -> p1 * p2 in Z_q[X] / (X^N + 1) 139 | * @param[in] p2 in Z_q[X] / (X^N + 1) 140 | * @param[in] mod q 141 | * @param[in] degree N 142 | */ 143 | static void multAndEqual(ZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 144 | 145 | // static void multAndEqual(CZZX& p1, CZZX& p2, ZZ& mod, const long& degree); 146 | // static void multAndEqual(CZZX& p1, ZZX& p2, ZZ& mod, const long& degree); 147 | 148 | //----------------------------------------- 149 | 150 | /** 151 | * square in ring Z_q[X] / (X^N + 1) 152 | * @param[out] p^2 in Z_q[X] / (X^N + 1) 153 | * @param[in] p in Z_q[X] / (X^N + 1) 154 | * @param[in] mod q 155 | * @param[in] degree N 156 | */ 157 | static void square(ZZX& res, ZZX& p, ZZ& mod, const long& degree); 158 | 159 | /** 160 | * square in ring Z_q[X] / (X^N + 1) 161 | * @param[in] p in Z_q[X] / (X^N + 1) 162 | * @param[in] mod q 163 | * @param[in] degree N 164 | * @result p^2 in Z_q[X] / (X^N + 1) 165 | */ 166 | static ZZX square(ZZX& p, ZZ& mod, const long& degree); 167 | 168 | // static void square(CZZX& res, CZZX& p, ZZ& mod, const long& degree); 169 | 170 | /** 171 | * square in ring Z_q[X] / (X^N + 1) 172 | * @param[in, out] p -> p^2 in Z_q[X] / (X^N + 1) 173 | * @param[in] mod q 174 | * @param[in] degree N 175 | */ 176 | static void squareAndEqual(ZZX& p, ZZ& mod, const long& degree); 177 | // static void squareAndEqual(CZZX& p, ZZ& mod, const long& degree); 178 | 179 | //----------------------------------------- 180 | 181 | /** 182 | * multiplication by monomial in ring Z_q[X] / (X^N + 1) 183 | * @param[out] p * X^d in Z_q[X] / (X^N + 1) 184 | * @param[in] p in Z_q[X] / (X^N + 1) 185 | * @param[in] monomial degree d 186 | * @param[in] degree N 187 | */ 188 | static void multByMonomial(ZZX& res, ZZX& p, const long& monomialDeg, const long& degree); 189 | 190 | /** 191 | * multiplication by monomial in ring Z_q[X] / (X^N + 1) 192 | * @param[in] p in Z_q[X] / (X^N + 1) 193 | * @param[in] monomial degree d 194 | * @param[in] degree N 195 | * @result p * X^d in Z_q[X] / (X^N + 1) 196 | */ 197 | static ZZX multByMonomial(ZZX& p, const long& monomialDeg, const long& degree); 198 | 199 | // static void multByMonomial(CZZX& res, CZZX& p, const long& monomialDeg, const long& degree); 200 | 201 | /** 202 | * multiplication by monomial in ring Z_q[X] / (X^N + 1) 203 | * @param[in, out] p -> p * X^d in Z_q[X] / (X^N + 1) 204 | * @param[in] monomial degree d 205 | * @param[in] degree N 206 | */ 207 | static void multByMonomialAndEqual(ZZX& p, const long& monomialDeg, const long& degree); 208 | 209 | // static void multByMonomialAndEqual(CZZX& p, const long& monomialDeg, const long& degree); 210 | 211 | //----------------------------------------- 212 | 213 | /** 214 | * multiplication by constant in ring Z_q[X] / (X^N + 1) 215 | * @param[out] p * c in Z_q[X] / (X^N + 1) 216 | * @param[in] p in Z_q[X] / (X^N + 1) 217 | * @param[in] constant c 218 | * @param[in] mod q 219 | * @param[in] degree N 220 | */ 221 | static void multByConst(ZZX& res, ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree); 222 | 223 | /** 224 | * multiplication by constant in ring Z_q[X] / (X^N + 1) 225 | * @param[in] p in Z_q[X] / (X^N + 1) 226 | * @param[in] constant c 227 | * @param[in] mod q 228 | * @param[in] degree N 229 | * @result p * c in Z_q[X] / (X^N + 1) 230 | */ 231 | static ZZX multByConst(ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree); 232 | 233 | // static void multByConst(CZZX& res, CZZX& p, const ZZ& cnst, ZZ& mod, const long& degree); 234 | // static void multByConst(CZZX& res, CZZX& p, const CZZ& cnst, ZZ& mod, const long& degree); 235 | 236 | /** 237 | * multiplication by constant in ring Z_q[X] / (X^N + 1) 238 | * @param[in, out] p -> p * c in Z_q[X] / (X^N + 1) 239 | * @param[in] constant c 240 | * @param[in] mod q 241 | * @param[in] degree N 242 | */ 243 | static void multByConstAndEqual(ZZX& p, const ZZ& cnst, ZZ& mod, const long& degree); 244 | 245 | // static void multByConstAndEqual(CZZX& p, const ZZ& cnst, ZZ& mod, const long& degree); 246 | // static void multByConstAndEqual(CZZX& p, const CZZ& cnst, ZZ& mod, const long& degree); 247 | 248 | //----------------------------------------- 249 | 250 | /** 251 | * multiplication by 2^b in ring Z_q[X] / (X^N + 1) 252 | * @param[out] p * 2^b in Z_q[X] / (X^N + 1) 253 | * @param[in] p in Z_q[X] / (X^N + 1) 254 | * @param[in] degree b 255 | * @param[in] mod q 256 | * @param[in] degree N 257 | */ 258 | static void leftShift(ZZX& res, ZZX& p, const long& bits, ZZ& mod, const long& degree); 259 | 260 | // static void leftShift(CZZX& res, CZZX& p, const long& bits, ZZ& mod, const long& degree); 261 | 262 | /** 263 | * multiplication by 2^b in ring Z_q[X] / (X^N + 1) 264 | * @param[in, out] p -> p * 2^b in Z_q[X] / (X^N + 1) 265 | * @param[in] degree b 266 | * @param[in] mod q 267 | * @param[in] degree N 268 | */ 269 | static void leftShiftAndEqual(ZZX& p, const long& bits, ZZ& mod, const long& degree); 270 | 271 | /** 272 | * multiplication by 2 in ring Z_q[X] / (X^N + 1) 273 | * @param[in, out] p -> 2p in Z_q[X] / (X^N + 1) 274 | * @param[in] mod q 275 | * @param[in] degree N 276 | */ 277 | static void doubleAndEqual(ZZX& p, ZZ& mod, const long& degree); 278 | // static void leftShiftAndEqual(CZZX& p, const long& bits, const long& logMod, const long& degree); 279 | 280 | //----------------------------------------- 281 | 282 | /** 283 | * division by 2^b in ring Z_q[X] / (X^N + 1) 284 | * @param[out] p / 2^b in Z_q[X] / (X^N + 1) 285 | * @param[in] p in Z_q[X] / (X^N + 1) 286 | * @param[in] degree b 287 | * @param[in] degree N 288 | */ 289 | static void rightShift(ZZX& res, ZZX& p, const long& bits, const long& degree); 290 | // static void rightShift(CZZX& res, CZZX& p, const long& bits, const long& logMod, const long& degree); 291 | 292 | /** 293 | * division by 2^b in ring Z_q[X] / (X^N + 1) 294 | * @param[in,out] p -> p / 2^b in Z_q[X] / (X^N + 1) 295 | * @param[in] degree b 296 | * @param[in] degree N 297 | */ 298 | static void rightShiftAndEqual(ZZX& p, const long& bits, const long& degree); 299 | // static void rightShiftAndEqual(CZZX& p, const long& bits, const long& logMod, const long& degree); 300 | 301 | //----------------------------------------- 302 | 303 | /** 304 | * changing p(X) to p(X^pow) in Z_q[X] / (X^N + 1) 305 | * @param[out] p(X^pow) in Z_q[X] / (X^N + 1) 306 | * @param[in] p(X) in Z_q[X] / (X^N + 1) 307 | * @param[in] power pow 308 | * @param[in] mod q 309 | * @param[in] degree N 310 | */ 311 | static void inpower(ZZX& res, ZZX& p, const long& pow, ZZ& mod, const long& degree); 312 | 313 | /** 314 | * changing p(X) to p(X^pow) in Z_q[X] / (X^N + 1) 315 | * @param[in] p(X) in Z_q[X] / (X^N + 1) 316 | * @param[in] power pow 317 | * @param[in] mod q 318 | * @param[in] degree N 319 | * @result p(X^pow) in Z_q[X] / (X^N + 1) 320 | */ 321 | static ZZX inpower(ZZX& p, const long& pow, ZZ& mod, const long& degree); 322 | 323 | /** 324 | * calculates array of polynomials with bits coefficients of coefficients of p 325 | * @param[in] p(X) in Z_q[X] / (X^N + 1) 326 | * @param[in] log of modulus q 327 | * @param[in] degree N 328 | * @result array of ZZX 329 | */ 330 | static ZZX* bitDecomposition(ZZX& p, const long& logMod, const long& degree); 331 | 332 | /** 333 | * calculates inner product of two arrays of polynomials in ring Z_q[X] / (X^N + 1) 334 | * @param[in] array pvec1 in (Z_q[X] / (X^N + 1))^size 335 | * @param[in] array pvec2 in (Z_q[X] / (X^N + 1))^size 336 | * @param[in] size of array 337 | * @param[in] mod q 338 | * @param[in] degree N 339 | * @result 340 | */ 341 | static ZZX innerProduct(ZZX*& pvec1, ZZX*& pvec2, const long& size, ZZ& mod, const long& degree); 342 | //----------------------------------------- 343 | 344 | }; 345 | 346 | #endif /* POLYSCHEME_ZRINGUTILS_H_ */ 347 | -------------------------------------------------------------------------------- /src/Ring2Utils.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/Ring2Utils.o -------------------------------------------------------------------------------- /src/Scheme.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/Scheme.o -------------------------------------------------------------------------------- /src/SchemeAlgo.cpp: -------------------------------------------------------------------------------- 1 | #include "SchemeAlgo.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "CZZ.h" 9 | #include "EvaluatorUtils.h" 10 | #include "Message.h" 11 | #include "Params.h" 12 | #include "SchemeAux.h" 13 | #include "SecKey.h" 14 | 15 | Cipher* SchemeAlgo::encryptSingleArray(CZZ*& vals, long size) { 16 | Cipher* res = new Cipher[size]; 17 | for (long i = 0; i < size; ++i) { 18 | res[i] = scheme.encryptSingle(vals[i]); 19 | } 20 | return res; 21 | } 22 | 23 | CZZ* SchemeAlgo::decryptSingleArray(SecKey& secretKey, Cipher*& ciphers, long size) { 24 | CZZ* res = new CZZ[size]; 25 | for (int i = 0; i < size; ++i) { 26 | Message msg = scheme.decryptMsg(secretKey, ciphers[i]); 27 | CZZ* gvals = scheme.decode(msg); 28 | res[i] = gvals[0]; 29 | } 30 | return res; 31 | } 32 | 33 | Cipher SchemeAlgo::powerOf2(Cipher& cipher, const long precisionBits, const long logDegree) { 34 | Cipher res = cipher; 35 | for (long i = 0; i < logDegree; ++i) { 36 | scheme.squareAndEqual(res); 37 | scheme.modSwitchAndEqual(res, precisionBits); 38 | } 39 | return res; 40 | } 41 | 42 | Cipher* SchemeAlgo::powerOf2Extended(Cipher& cipher, const long precisionBits, const long logDegree) { 43 | Cipher* res = new Cipher[logDegree + 1]; 44 | res[0] = cipher; 45 | for (long i = 1; i < logDegree + 1; ++i) { 46 | res[i] = scheme.square(res[i-1]); 47 | scheme.modSwitchAndEqual(res[i], precisionBits); 48 | } 49 | return res; 50 | } 51 | 52 | //----------------------------------------- 53 | 54 | Cipher SchemeAlgo::power(Cipher& cipher, const long precisionBits, const long degree) { 55 | long logDegree = log2(degree); 56 | long po2Degree = 1 << logDegree; 57 | 58 | Cipher res = powerOf2(cipher, precisionBits, logDegree); 59 | long remDegree = degree - po2Degree; 60 | if(remDegree > 0) { 61 | Cipher tmp = power(cipher, precisionBits, remDegree); 62 | long bitsDown = tmp.cbits - res.cbits; 63 | scheme.modEmbedAndEqual(tmp, bitsDown); 64 | scheme.multAndEqual(res, tmp); 65 | scheme.modSwitchAndEqual(res, precisionBits); 66 | } 67 | return res; 68 | } 69 | 70 | Cipher* SchemeAlgo::powerExtended(Cipher& cipher, const long precisionBits, const long degree) { 71 | Cipher* res = new Cipher[degree]; 72 | long logDegree = log2(degree); 73 | Cipher* cpows = powerOf2Extended(cipher, precisionBits, logDegree); 74 | long idx = 0; 75 | for (long i = 0; i < logDegree; ++i) { 76 | long powi = (1 << i); 77 | res[idx++] = cpows[i]; 78 | for (int j = 0; j < powi-1; ++j) { 79 | long bitsDown = res[j].cbits - cpows[i].cbits; 80 | res[idx] = scheme.modEmbed(res[j], bitsDown); 81 | scheme.multAndEqual(res[idx], cpows[i]); 82 | scheme.modSwitchAndEqual(res[idx++], precisionBits); 83 | } 84 | } 85 | res[idx++] = cpows[logDegree]; 86 | long degree2 = (1 << logDegree); 87 | for (int i = 0; i < (degree - degree2); ++i) { 88 | long bitsDown = res[i].cbits - cpows[logDegree].cbits; 89 | res[idx] = scheme.modEmbed(res[i], bitsDown); 90 | scheme.multAndEqual(res[idx], cpows[logDegree]); 91 | scheme.modSwitchAndEqual(res[idx++], precisionBits); 92 | } 93 | return res; 94 | } 95 | 96 | //----------------------------------------- 97 | 98 | Cipher SchemeAlgo::prodOfPo2(Cipher*& ciphers, const long precisionBits, const long logDegree) { 99 | Cipher* res = ciphers; 100 | for (long i = logDegree - 1; i >= 0; --i) { 101 | long powih = (1 << i); 102 | Cipher* tmp = new Cipher[powih]; 103 | NTL_EXEC_RANGE(powih, first, last); 104 | for (long j = first; j < last; ++j) { 105 | tmp[j] = scheme.mult(res[2 * j], res[2 * j + 1]); 106 | scheme.modSwitchAndEqual(tmp[j], precisionBits); 107 | } 108 | NTL_EXEC_RANGE_END; 109 | res = tmp; 110 | } 111 | return res[0]; 112 | } 113 | 114 | Cipher SchemeAlgo::prod(Cipher*& ciphers, const long precisionBits, const long degree) { 115 | long logDegree = log2(degree) + 1; 116 | long idx = 0; 117 | bool isinit = false; 118 | Cipher res; 119 | for (long i = 0; i < logDegree; ++i) { 120 | if(bit(degree, i)) { 121 | long powi = (1 << i); 122 | Cipher* tmp = new Cipher[powi]; 123 | for (long j = 0; j < powi; ++j) { 124 | tmp[j] = ciphers[idx + j]; 125 | } 126 | Cipher iprod = prodOfPo2(tmp, precisionBits, i); 127 | if(isinit) { 128 | long bitsDown = res.cbits - iprod.cbits; 129 | scheme.modEmbedAndEqual(res, bitsDown); 130 | scheme.multAndEqual(res, iprod); 131 | scheme.modSwitchAndEqual(res, precisionBits); 132 | } else { 133 | res = iprod; 134 | isinit = true; 135 | } 136 | idx += powi; 137 | } 138 | } 139 | return res; 140 | } 141 | 142 | Cipher SchemeAlgo::sum(Cipher*& ciphers, const long size) { 143 | Cipher res = ciphers[0]; 144 | for (long i = 1; i < size; ++i) { 145 | scheme.addAndEqual(res, ciphers[i]); 146 | } 147 | return res; 148 | } 149 | 150 | Cipher SchemeAlgo::distance(Cipher& cipher1, Cipher& cipher2, const long precisionBits) { 151 | Cipher cres = scheme.sub(cipher1, cipher2); 152 | scheme.squareAndEqual(cres); 153 | scheme.modSwitchAndEqual(cres, precisionBits); 154 | partialSlotsSumAndEqual(cres, cres.slots); 155 | return cres; 156 | } 157 | 158 | Cipher* SchemeAlgo::multVec(Cipher*& ciphers1, Cipher*& ciphers2, const long size) { 159 | Cipher* res = new Cipher[size]; 160 | NTL_EXEC_RANGE(size, first, last); 161 | for (long i = first; i < last; ++i) { 162 | res[i] = scheme.mult(ciphers1[i], ciphers2[i]); 163 | } 164 | NTL_EXEC_RANGE_END; 165 | return res; 166 | } 167 | 168 | void SchemeAlgo::multAndEqualVec(Cipher*& ciphers1, Cipher*& ciphers2, const long size) { 169 | NTL_EXEC_RANGE(size, first, last); 170 | for (long i = first; i < last; ++i) { 171 | scheme.multAndEqual(ciphers1[i], ciphers2[i]); 172 | } 173 | NTL_EXEC_RANGE_END; 174 | } 175 | 176 | 177 | Cipher* SchemeAlgo::multAndModSwitchVec(Cipher*& ciphers1, Cipher*& ciphers2, const long precisionBits, const long size) { 178 | Cipher* res = new Cipher[size]; 179 | NTL_EXEC_RANGE(size, first, last); 180 | for (long i = first; i < last; ++i) { 181 | res[i] = scheme.mult(ciphers1[i], ciphers2[i]); 182 | scheme.modSwitchAndEqual(res[i], precisionBits); 183 | } 184 | NTL_EXEC_RANGE_END; 185 | return res; 186 | } 187 | 188 | void SchemeAlgo::multModSwitchAndEqualVec(Cipher*& ciphers1, Cipher*& ciphers2, const long precisionBits, const long size) { 189 | NTL_EXEC_RANGE(size, first, last); 190 | for (long i = first; i < last; ++i) { 191 | scheme.multAndEqual(ciphers1[i], ciphers2[i]); 192 | scheme.modSwitchAndEqual(ciphers1[i], precisionBits); 193 | } 194 | NTL_EXEC_RANGE_END; 195 | } 196 | 197 | Cipher SchemeAlgo::innerProd(Cipher*& ciphers1, Cipher*& ciphers2, const long precisionBits, const long size) { 198 | Cipher cip = scheme.mult(ciphers1[size-1], ciphers2[size-1]); 199 | 200 | NTL_EXEC_RANGE(size-1, first, last); 201 | for (long i = first; i < last; ++i) { 202 | Cipher cprodi = scheme.mult(ciphers1[i], ciphers2[i]); 203 | scheme.addAndEqual(cip, cprodi); 204 | } 205 | NTL_EXEC_RANGE_END; 206 | 207 | scheme.modSwitchAndEqual(cip, precisionBits); 208 | return cip; 209 | } 210 | 211 | Cipher SchemeAlgo::partialSlotsSum(Cipher& cipher, const long slots) { 212 | long logslots = log2(slots); 213 | Cipher res = cipher; 214 | for (long i = 0; i < logslots; ++i) { 215 | Cipher rot = scheme.leftRotateByPo2(cipher, i); 216 | scheme.addAndEqual(res, rot); 217 | } 218 | return res; 219 | } 220 | 221 | void SchemeAlgo::partialSlotsSumAndEqual(Cipher& cipher, const long slots) { 222 | long logslots = log2(slots); 223 | for (long i = 0; i < logslots; ++i) { 224 | Cipher rot = scheme.leftRotateByPo2(cipher, i); 225 | scheme.addAndEqual(cipher, rot); 226 | } 227 | } 228 | 229 | //----------------------------------------- 230 | 231 | Cipher SchemeAlgo::inverse(Cipher& cipher, const long precisionBits, const long steps) { 232 | ZZ precision = power2_ZZ(precisionBits); 233 | Cipher cpow = cipher; 234 | Cipher tmp = scheme.addConst(cipher, precision); 235 | scheme.modEmbedAndEqual(tmp, precisionBits); 236 | Cipher res = tmp; 237 | 238 | for (long i = 1; i < steps; ++i) { 239 | scheme.squareAndEqual(cpow); 240 | scheme.modSwitchAndEqual(cpow, precisionBits); 241 | tmp = cpow; 242 | scheme.addConstAndEqual(tmp, precision); 243 | scheme.multAndEqual(tmp, res); 244 | scheme.modSwitchAndEqual(tmp, precisionBits); 245 | res = tmp; 246 | } 247 | return res; 248 | } 249 | 250 | Cipher* SchemeAlgo::inverseExtended(Cipher& cipher, const long precisionBits, const long steps) { 251 | ZZ precision = power2_ZZ(precisionBits); 252 | 253 | Cipher* res = new Cipher[steps]; 254 | Cipher cpow = cipher; 255 | Cipher tmp = scheme.addConst(cipher, precision); 256 | scheme.modEmbedAndEqual(tmp, precisionBits); 257 | res[0] = tmp; 258 | 259 | for (long i = 1; i < steps; ++i) { 260 | scheme.squareAndEqual(cpow); 261 | scheme.modSwitchAndEqual(cpow, precisionBits); 262 | tmp = cpow; 263 | scheme.addConstAndEqual(tmp, precision); 264 | scheme.multAndEqual(tmp, res[i - 1]); 265 | scheme.modSwitchAndEqual(tmp, precisionBits); 266 | res[i] = tmp; 267 | } 268 | return res; 269 | } 270 | 271 | //----------------------------------------- 272 | 273 | Cipher SchemeAlgo::function(Cipher& cipher, string& funcName, const long precisionBits, const long degree) { 274 | Cipher* cpows = powerExtended(cipher, precisionBits, degree); 275 | 276 | long dprecisionBits = 2 * precisionBits; 277 | 278 | double* coeffs = scheme.aux.taylorCoeffsMap.at(funcName); 279 | 280 | ZZ tmp = EvaluatorUtils::evaluateVal(coeffs[1], precisionBits); 281 | Cipher res = scheme.multByConst(cpows[0], tmp); 282 | 283 | tmp = EvaluatorUtils::evaluateVal(coeffs[0], dprecisionBits); 284 | scheme.addConstAndEqual(res, tmp); 285 | 286 | for (int i = 1; i < degree; ++i) { 287 | if(abs(coeffs[i + 1]) > 1e-27) { 288 | tmp = EvaluatorUtils::evaluateVal(coeffs[i + 1], precisionBits); 289 | Cipher aixi = scheme.multByConst(cpows[i], tmp); 290 | long bitsDown = res.cbits - aixi.cbits; 291 | scheme.modEmbedAndEqual(res, bitsDown); 292 | scheme.addAndEqual(res, aixi); 293 | } 294 | } 295 | scheme.modSwitchAndEqual(res, precisionBits); 296 | return res; 297 | } 298 | 299 | Cipher SchemeAlgo::functionLazy(Cipher& cipher, string& funcName, const long precisionBits, const long degree) { 300 | Cipher* cpows = powerExtended(cipher, precisionBits, degree); 301 | 302 | long dprecisionBits = 2 * precisionBits; 303 | 304 | double* coeffs = scheme.aux.taylorCoeffsMap.at(funcName); 305 | 306 | ZZ tmp = EvaluatorUtils::evaluateVal(coeffs[1], precisionBits); 307 | Cipher res = scheme.multByConst(cpows[0], tmp); 308 | 309 | tmp = EvaluatorUtils::evaluateVal(coeffs[0], dprecisionBits); 310 | scheme.addConstAndEqual(res, tmp); 311 | 312 | for (int i = 1; i < degree; ++i) { 313 | if(abs(coeffs[i + 1]) > 1e-27) { 314 | tmp = EvaluatorUtils::evaluateVal(coeffs[i + 1], precisionBits); 315 | Cipher aixi = scheme.multByConst(cpows[i], tmp); 316 | long bitsDown = res.cbits - aixi.cbits; 317 | scheme.modEmbedAndEqual(res, bitsDown); 318 | scheme.addAndEqual(res, aixi); 319 | } 320 | } 321 | return res; 322 | } 323 | 324 | Cipher* SchemeAlgo::functionExtended(Cipher& cipher, string& funcName, const long precisionBits, const long degree) { 325 | Cipher* cpows = powerExtended(cipher, precisionBits, degree); 326 | 327 | long dprecisionBits = 2 * precisionBits; 328 | double* coeffs = scheme.aux.taylorCoeffsMap.at(funcName); 329 | 330 | ZZ tmp = EvaluatorUtils::evaluateVal(coeffs[1], precisionBits); 331 | Cipher aixi = scheme.multByConst(cpows[0], tmp); 332 | 333 | tmp = EvaluatorUtils::evaluateVal(coeffs[0], dprecisionBits); 334 | scheme.addConstAndEqual(aixi, tmp); 335 | 336 | Cipher* res = new Cipher[degree]; 337 | res[0] = aixi; 338 | for (long i = 1; i < degree; ++i) { 339 | if(abs(coeffs[i + 1]) > 1e-27) { 340 | tmp = EvaluatorUtils::evaluateVal(coeffs[i + 1], precisionBits); 341 | aixi = scheme.multByConst(cpows[i], tmp); 342 | long bitsDown = res[i - 1].cbits - aixi.cbits; 343 | Cipher ctmp = scheme.modEmbed(res[i - 1], bitsDown); 344 | scheme.addAndEqual(aixi, ctmp); 345 | res[i] = aixi; 346 | } else { 347 | res[i] = res[i - 1]; 348 | } 349 | } 350 | NTL_EXEC_RANGE(degree, first, last); 351 | for (long i = first; i < last; ++i) { 352 | scheme.modSwitchAndEqual(res[i], precisionBits); 353 | } 354 | NTL_EXEC_RANGE_END; 355 | return res; 356 | } 357 | 358 | void SchemeAlgo::fftRaw(Cipher*& ciphers, const long size, const bool isForward) { 359 | for (long i = 1, j = 0; i < size; ++i) { 360 | long bit = size >> 1; 361 | for (; j >= bit; bit>>=1) { 362 | j -= bit; 363 | } 364 | j += bit; 365 | if(i < j) { 366 | swap(ciphers[i], ciphers[j]); 367 | } 368 | } 369 | 370 | for (long len = 2; len <= size; len <<= 1) { 371 | long shift = isForward ? ((scheme.params.N / len) << 1) : ((scheme.params.N - scheme.params.N / len) << 1); 372 | for (long i = 0; i < size; i += len) { 373 | NTL_EXEC_RANGE(len / 2, first, last); 374 | for (long j = first; j < last; ++j) { 375 | Cipher u = ciphers[i + j]; 376 | scheme.multByMonomialAndEqual(ciphers[i + j + len / 2], shift * j); 377 | scheme.addAndEqual(ciphers[i + j], ciphers[i + j + len / 2]); 378 | scheme.subAndEqual2(u, ciphers[i + j + len / 2]); 379 | } 380 | NTL_EXEC_RANGE_END; 381 | } 382 | } 383 | } 384 | 385 | void SchemeAlgo::fft(Cipher*& ciphers, const long size) { 386 | fftRaw(ciphers, size, true); 387 | } 388 | 389 | void SchemeAlgo::fftInv(Cipher*& ciphers, const long size) { 390 | fftRaw(ciphers, size, false); 391 | long logsize = log2(size); 392 | 393 | NTL_EXEC_RANGE(size, first, last); 394 | for (long i = first; i < last; ++i) { 395 | scheme.modSwitchAndEqual(ciphers[i], logsize); 396 | } 397 | NTL_EXEC_RANGE_END; 398 | } 399 | 400 | void SchemeAlgo::fftInvLazy(Cipher*& ciphers, const long size) { 401 | return fftRaw(ciphers, size, false); 402 | } 403 | -------------------------------------------------------------------------------- /src/SchemeAlgo.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_SCHEMEALGO_H_ 2 | #define SCHEME_SCHEMEALGO_H_ 3 | 4 | #include 5 | 6 | #include "Cipher.h" 7 | #include "Scheme.h" 8 | 9 | class SchemeAlgo { 10 | public: 11 | Scheme& scheme; 12 | 13 | //----------------------------------------- 14 | 15 | SchemeAlgo(Scheme& scheme) : scheme(scheme) {}; 16 | 17 | //----------------------------------------- 18 | 19 | /** 20 | * encrypting array of vals, each to one cipher 21 | * @param[in] [m_1, m_2,...,m_size] 22 | * @param[in] size 23 | * @return [cipher(m_1), cipher(m_2),...,cipher(m_size)] 24 | */ 25 | Cipher* encryptSingleArray(CZZ*& vals, long size); 26 | 27 | /** 28 | * decrypting array of ciphers with single val encrypted in each 29 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 30 | * @param[in] size 31 | * @return [m_1, m_2,...,m_size] 32 | */ 33 | CZZ* decryptSingleArray(SecKey& secretKey, Cipher*& ciphers, long size); 34 | 35 | /** 36 | * Calculating power of 2 cipher 37 | * @param[in] cipher(m) 38 | * @param[in] precision of initial m 39 | * @param[in] logdeg 40 | * @return cipher(m^2^logdeg) 41 | */ 42 | Cipher powerOf2(Cipher& cipher, const long precisionBits, const long logDegree); 43 | 44 | /** 45 | * Calculating and storing all power of 2 ciphers up to 2^logdeg 46 | * @param[in] cipher(m) 47 | * @param[in] precision of initial m 48 | * @param[in] logdeg 49 | * @return [cipher(m), cipher(m^2), cipher(m^4), ... , cipher(m^2^logdeg)] 50 | */ 51 | Cipher* powerOf2Extended(Cipher& cipher, const long precisionBits, const long logDegree); 52 | 53 | //----------------------------------------- 54 | 55 | /** 56 | * Calculating power of cipher 57 | * @param[in] cipher(m) 58 | * @param[in] precision of initial m 59 | * @param[in] deg 60 | * @return cipher(m^deg) 61 | */ 62 | Cipher power(Cipher& cipher, const long precisionBits, const long degree); 63 | 64 | /** 65 | * Calculating and storing powers of cipher up to deg 66 | * @param[in] cipher(m) 67 | * @param[in] precision of initial m 68 | * @param[in] deg 69 | * @return [cipher(m), cipher(m^2), ... , cipher(m^deg)] 70 | */ 71 | Cipher* powerExtended(Cipher& cipher, const long precisionBits, const long degree); 72 | 73 | //----------------------------------------- 74 | 75 | /** 76 | * Calculating product of ciphers, number of ciphers here is power of 2 77 | * @param[in] [cipher(m_1), cipher(m_2), ... ,cipher(m_{2^logdeg})] 78 | * @param[in] precision of initial m_i 79 | * @param[in] logdeg 80 | * @return cipher(m_1 * m_2 *...*m_{2^logdeg}) 81 | */ 82 | Cipher prodOfPo2(Cipher*& ciphers, const long precisionBits, const long logDegree); 83 | 84 | /** 85 | * Calculating product of ciphers 86 | * @param[in] [cipher(m_1), cipher(m_2), ... ,cipher(m_{degree})] 87 | * @param[in] precision of initial m_i 88 | * @param[in] degree 89 | * @return cipher(m_1 * m_2 *...*m_{degree}) 90 | */ 91 | Cipher prod(Cipher*& ciphers, const long precisionBits, const long degree); 92 | 93 | //----------------------------------------- 94 | 95 | /** 96 | * Calculating sum of ciphers 97 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 98 | * @param[in] size 99 | * @return cipher(m_1 + m_2 + ... + m_size) 100 | */ 101 | Cipher sum(Cipher*& ciphers, const long size); 102 | 103 | /** 104 | * Calculating distance of ciphers 105 | * @param[in] cipher(m_1, m_2, ..., m_slots) 106 | * @param[in] cipher(m'_1, m'_2, ..., m'_slots) 107 | * @return cipher(sum((m_i-m'_i)^2) >> precisionBits) 108 | */ 109 | Cipher distance(Cipher& cipher1, Cipher& cipher2, const long precisionBits); 110 | //----------------------------------------- 111 | 112 | /** 113 | * Pairwise ciphers multiplication 114 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 115 | * @param[in] [cipher(n_1), cipher(n_2),...,cipher(n_size)] 116 | * @param[in] size 117 | * @return [cipher(m_1 * n_1), cipher(m_2 * n_2),...,cipher(m_size * n_size)] 118 | */ 119 | Cipher* multVec(Cipher*& ciphers1, Cipher*& ciphers2, const long size); 120 | 121 | /** 122 | * Pairwise ciphers multiplication 123 | * @param[in, out] [cipher(m_1), cipher(m_2),...,cipher(m_size)] -> [cipher(m_1 * n_1), cipher(m_2 * n_2),...,cipher(m_size * n_size)] 124 | * @param[in] [cipher(n_1), cipher(n_2),...,cipher(n_size)] 125 | * @param[in] size 126 | */ 127 | void multAndEqualVec(Cipher*& ciphers1, Cipher*& ciphers2, const long size); 128 | 129 | /** 130 | * Pairwise ciphers multiplication and modulus switching 131 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 132 | * @param[in] [cipher(n_1), cipher(n_2),...,cipher(n_size)] 133 | * @param[in] precision of initial m_i, n_i 134 | * @param[in] size 135 | * @return [cipher(m_1 * n_1 / p), cipher(m_2 * n_2 / p),...,cipher(m_size * n_size / p)] one level higher 136 | */ 137 | Cipher* multAndModSwitchVec(Cipher*& ciphers1, Cipher*& ciphers2, const long precisionBits, const long size); 138 | 139 | /** 140 | * Pairwise ciphers multiplication and modulus switching 141 | * @param[in, out] [cipher(m_1), cipher(m_2),...,cipher(m_size)] -> [cipher(m_1 * n_1 / p), cipher(m_2 * n_2 / p),...,cipher(m_size * n_size / p)] 142 | * @param[in] [cipher(n_1), cipher(n_2),...,cipher(n_size)] 143 | * @param[in] precision of initial m_i, n_i 144 | * @param[in] size 145 | */ 146 | void multModSwitchAndEqualVec(Cipher*& ciphers1, Cipher*& ciphers2, const long precisionBits, const long size); 147 | 148 | //----------------------------------------- 149 | 150 | /** 151 | * Calculating inner product of ciphers 152 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 153 | * @param[in] [cipher(n_1), cipher(n_2),...,cipher(n_size)] 154 | * @param[in] precision of initial m_i, n_i 155 | * @param[in] size 156 | * @return cipher(m_1 * n_1 + m_2 * n_2 + ... + m_size * n_size) 157 | */ 158 | Cipher innerProd(Cipher*& ciphers1, Cipher*& ciphers2, const long precision, const long size); 159 | 160 | /** 161 | * Calculating cipher of partial sums 162 | * @param[in] cipher(m_1, m_2,..., m_size) 163 | * @param[in] slots summed in partial sums 164 | * @return cipher(m_1 + ... + m_slots, m_2 + ... + m_{slots + 1},...,m_size + m_1 + ... + m_{slots - 1}) 165 | * 166 | */ 167 | Cipher partialSlotsSum(Cipher& cipher, const long slots); 168 | 169 | /** 170 | * Calculating cipher of partial sums 171 | * @param[in, out] cipher(m_1, m_2,..., m_size) -> cipher(m_1 + ... + m_slots, m_2 + ... + m_{slots + 1},...,m_size + m_1 + ... + m_{slots - 1}) 172 | * @param[in] slots summed in partial sums 173 | */ 174 | void partialSlotsSumAndEqual(Cipher& cipher, const long slots); 175 | 176 | //----------------------------------------- 177 | 178 | /** 179 | * Calculating inverse of a cipher, using steps number of approximations 180 | * @param[in] cipher(m) 181 | * @param[in] precision of initial m 182 | * @param[in] steps 183 | * @return cipher(1 / m << (2 * precisionBits)) 184 | */ 185 | Cipher inverse(Cipher& cipher, const long precisionBits, const long steps); 186 | 187 | /** 188 | * Calculating and storing inverse of a cipher at each step up to stepsNum 189 | * @param[in] cipher(m) 190 | * @param[in] precision of initial m 191 | * @param[in] steps 192 | * @return [cipher(1 / m << (2 * precisionBits)), ... ,cipher(1 / m << (2 * precisionBits))] 193 | */ 194 | Cipher* inverseExtended(Cipher& cipher, const long precisionBits, const long steps); 195 | 196 | //----------------------------------------- 197 | 198 | /** 199 | * Calculating function using Taylor Series approximation, more information in SchemeAux 200 | * @param[in] cipher(m) 201 | * @param[in] funcName 202 | * @param[in] precision of initial m 203 | * @param[in] degree 204 | * @return cipher(funcName(m)) 205 | */ 206 | Cipher function(Cipher& cipher, string& funcName, const long precisionBits, const long degree); 207 | 208 | /** 209 | * Calculating function using Taylor Series approximation, more information in SchemeAux 210 | * @param[in] cipher(m) 211 | * @param[in] funcName 212 | * @param[in] precision of initial m 213 | * @param[in] degee 214 | * @return cipher(funcName(m) * p), but saves one level 215 | */ 216 | Cipher functionLazy(Cipher& cipher, string& funcName, const long precisionBits, const long degree); 217 | 218 | /** 219 | * Calculating function using Taylor Series approximation, and storing intermediate results 220 | * @param[in] cipher(m) 221 | * @param[in] funcName 222 | * @param[in] precision of initial m 223 | * @param[in] degee 224 | * @return [cipher(funcName(m)), ... ,cipher(funcName(m))] 225 | */ 226 | Cipher* functionExtended(Cipher& cipher, string& funcName, const long precisionBits, const long degree); 227 | 228 | //----------------------------------------- 229 | 230 | /** 231 | * Calculating fft of ciphers 232 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 233 | * @param[in] precision of initial m_i 234 | * @param[in] size is a power of 2 235 | * @param[in] boolean is forward? 236 | * @return [cipher(fft_1), ... ,cipher(fft_size)] 237 | */ 238 | void fftRaw(Cipher*& ciphers, const long size, const bool isForward); 239 | 240 | /** 241 | * Calculating fft of ciphers 242 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 243 | * @param[in] precision of initial m_i 244 | * @param[in] size is a power of 2 245 | * @return [cipher(fft_1), ... ,cipher(fft_size)] 246 | */ 247 | void fft(Cipher*& ciphers, const long size); 248 | 249 | /** 250 | * Calculating fft inverse of ciphers 251 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 252 | * @param[in] precision of initial m_i 253 | * @param[in] size is a power of 2 254 | * @return [cipher(fftinv_1), ... ,cipher(fftinv_size)] 255 | */ 256 | void fftInv(Cipher*& ciphers, const long size); 257 | 258 | /** 259 | * Calculating fft inverse of ciphers 260 | * @param[in] [cipher(m_1), cipher(m_2),...,cipher(m_size)] 261 | * @param[in] precision of initial m_i 262 | * @param[in] size is a power of 2 263 | * @return [cipher(fftinv_1 * size), ... ,cipher(fftinv_size * size)] but saves level 264 | */ 265 | void fftInvLazy(Cipher*& ciphers, const long size); 266 | 267 | //----------------------------------------- 268 | 269 | }; 270 | 271 | #endif /* SCHEME_SCHEMEALGO_H_ */ 272 | -------------------------------------------------------------------------------- /src/SchemeAlgo.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/SchemeAlgo.o -------------------------------------------------------------------------------- /src/SchemeAux.cpp: -------------------------------------------------------------------------------- 1 | #include "SchemeAux.h" 2 | 3 | SchemeAux::SchemeAux(long& logN) { 4 | M = 1 << (logN + 1); 5 | 6 | ksiPowsr = new RR[M + 1]; 7 | ksiPowsi = new RR[M + 1]; 8 | 9 | for (long j = 0; j < M; ++j) { 10 | RR angle = 2.0 * Pi * j / M; 11 | ksiPowsr[j] = cos(angle); 12 | ksiPowsi[j] = sin(angle); 13 | } 14 | 15 | ksiPowsr[M] = ksiPowsr[0]; 16 | ksiPowsi[M] = ksiPowsi[0]; 17 | 18 | taylorCoeffsMap.insert(pair(LOGARITHM, new double[11]{0,1,-0.5,1./3,-1./4,1./5,-1./6,1./7,-1./8,1./9,-1./10})); 19 | taylorCoeffsMap.insert(pair(EXPONENT, new double[11]{1,1,0.5,1./6,1./24,1./120,1./720,1./5040, 1./40320,1./362880,1./3628800})); 20 | taylorCoeffsMap.insert(pair(SIGMOID, new double[11]{1./2,1./4,0,-1./48,0,1./480,0,-17./80640,0,31./1451520,0})); 21 | 22 | // taylorCoeffsMap.insert(pair(SIGMOIDBAR, new double[11]{1./2,-1./4,0,1./48,0,-1./480,0,17./80640,0,-31./1451520,0})); 23 | // taylorCoeffsMap.insert(pair(SIGMOIDGOOD, new double[8]{0.5,0.216884,0,-0.00819276,0,0.000165861,0,-0.00000119581})); 24 | // taylorCoeffsMap.insert(pair(SIGMOIDBARGOOD, new double[8]{0.5,-0.216884,0,0.00819276,0,-0.000165861,0,0.00000119581})); 25 | // taylorCoeffsMap.insert(pair(SIGMOIDPRIMEGOOD7, new double[8]{-0.5,0.216884,0,-0.00819276,0,0.000165861,0,-0.00000119581})); 26 | // taylorCoeffsMap.insert(pair(SIGMOIDPRIMEGOOD5, new double[6]{-0.5,0.2166,0,-0.0077,0,0.00011})); 27 | // taylorCoeffsMap.insert(pair(SIGMOIDPRIMEGOOD3, new double[4]{-0.5,0.19,0,-0.0035})); 28 | } 29 | -------------------------------------------------------------------------------- /src/SchemeAux.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_SCHEMEAUX_H_ 2 | #define SCHEME_SCHEMEAUX_H_ 3 | 4 | #include "CZZ.h" 5 | #include "Params.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | using namespace NTL; 13 | 14 | static RR const Pi = ComputePi_RR(); 15 | 16 | class SchemeAux { 17 | public: 18 | 19 | long M; 20 | RR* ksiPowsr; ///< storing ksi pows for fft calculation 21 | RR* ksiPowsi; ///< storing ksi pows for fft calculation 22 | map taylorCoeffsMap; ///< storing taylor coefficients for function calculation 23 | 24 | //----------------------------------------- 25 | 26 | SchemeAux(long& logN); 27 | 28 | //----------------------------------------- 29 | 30 | }; 31 | 32 | static string LOGARITHM = "Logarithm"; ///< log(x) 33 | static string EXPONENT = "Exponent"; ///< exp(x) 34 | static string SIGMOID = "Sigmoid"; ///< sigmoid(x) = exp(x) / (1 + exp(x)) 35 | 36 | //static string SIGMOIDBAR = "Sigmoidbar"; ///< sigmoidbar = 1 - sigmoid(x) 37 | //static string SIGMOIDGOOD = "SigmoidGood"; ///< sigmoid(x) = exp(x) / (1 + exp(x)) 38 | //static string SIGMOIDBARGOOD = "SigmoidbarGood"; ///< sigmoidbar = 1 - sigmoid(x) 39 | //static string SIGMOIDPRIMEGOOD7 = "SigmoidprimeGood7"; ///< sigmoidprime = -1 / (1 + exp(x)) 40 | //static string SIGMOIDPRIMEGOOD5 = "SigmoidprimeGood5"; ///< sigmoidprime = -1 / (1 + exp(x)) 41 | //static string SIGMOIDPRIMEGOOD3 = "SigmoidprimeGood3"; ///< sigmoidprime = -1 / (1 + exp(x)) 42 | 43 | #endif /* SCHEME_SCHEMEAUX_H_ */ 44 | -------------------------------------------------------------------------------- /src/SchemeAux.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/SchemeAux.o -------------------------------------------------------------------------------- /src/SecKey.cpp: -------------------------------------------------------------------------------- 1 | #include "SecKey.h" 2 | 3 | #include "NumUtils.h" 4 | 5 | SecKey::SecKey(Params& params) { 6 | NumUtils::sampleHWT(sx, params.N, params.h); 7 | } 8 | -------------------------------------------------------------------------------- /src/SecKey.h: -------------------------------------------------------------------------------- 1 | #ifndef SCHEME_SECKEY_H_ 2 | #define SCHEME_SECKEY_H_ 3 | 4 | #include 5 | 6 | #include "Params.h" 7 | 8 | using namespace std; 9 | using namespace NTL; 10 | 11 | class SecKey { 12 | public: 13 | 14 | ZZX sx; ///< secret key 15 | 16 | //----------------------------------------- 17 | 18 | SecKey(Params& params); 19 | 20 | //----------------------------------------- 21 | 22 | }; 23 | 24 | #endif /* SCHEME_SECKEY_H_ */ 25 | -------------------------------------------------------------------------------- /src/SecKey.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/SecKey.o -------------------------------------------------------------------------------- /src/StringUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "StringUtils.h" 2 | 3 | #include 4 | 5 | void StringUtils::show(long*& vals, long size) { 6 | cout << "["; 7 | for (long i = 0; i < size; ++i) { 8 | cout << vals[i] << ", "; 9 | } 10 | cout << "]" << endl; 11 | } 12 | 13 | void StringUtils::show(CZZ*& vals, long size) { 14 | cout << "["; 15 | for (long i = 0; i < size; ++i) { 16 | cout << vals[i].toString() << ", "; 17 | } 18 | cout << "]" << endl; 19 | } 20 | 21 | //----------------------------------------- 22 | 23 | void StringUtils::showcompare(CZZ& val1, CZZ& val2, string prefix) { 24 | cout << "------------------------------------" << endl; 25 | cout << "m" + prefix + ":" << val1.toString() << endl; 26 | cout << "d" + prefix + ":" << val2.toString() << endl; 27 | cout << "e" + prefix + ":" << (val1-val2).toString() << endl; 28 | cout << "------------------------------------" << endl; 29 | } 30 | 31 | void StringUtils::showcompare(CZZ*& vals1, CZZ*& vals2, long size, string prefix) { 32 | for (long i = 0; i < size; ++i) { 33 | cout << "------------------------------------" << endl; 34 | cout << "m" + prefix + ": " << i << " :" << vals1[i].toString() << endl; 35 | cout << "d" + prefix + ": " << i << " :" << vals2[i].toString() << endl; 36 | cout << "e" + prefix + ": " << i << " :" << (vals1[i]-vals2[i]).toString() << endl; 37 | cout << "------------------------------------" << endl; 38 | } 39 | } 40 | 41 | void StringUtils::showcompare(CZZ*& vals1, CZZ& val2, long size, string prefix) { 42 | for (long i = 0; i < size; ++i) { 43 | cout << "------------------------------------" << endl; 44 | cout << "m" + prefix + ": " << i << " :" << vals1[i].toString() << endl; 45 | cout << "d" + prefix + ": " << i << " :" << val2.toString() << endl; 46 | cout << "e" + prefix + ": " << i << " :" << (vals1[i]-val2).toString() << endl; 47 | cout << "------------------------------------" << endl; 48 | } 49 | } 50 | 51 | void StringUtils::showcompare(CZZ& val1, CZZ*& vals2, long size, string prefix) { 52 | for (long i = 0; i < size; ++i) { 53 | cout << "------------------------------------" << endl; 54 | cout << "m" + prefix + ": " << i << " :" << val1.toString() << endl; 55 | cout << "d" + prefix + ": " << i << " :" << vals2[i].toString() << endl; 56 | cout << "e" + prefix + ": " << i << " :" << (val1-vals2[i]).toString() << endl; 57 | cout << "------------------------------------" << endl; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/StringUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_STRINGUTILS_H_ 2 | #define UTILS_STRINGUTILS_H_ 3 | 4 | #include 5 | 6 | #include "CZZ.h" 7 | 8 | class StringUtils { 9 | public: 10 | 11 | //----------------------------------------- 12 | 13 | /** 14 | * prints in console array 15 | * @param[in] array 16 | * @param[in] size of array 17 | */ 18 | static void show(long*& vals, long size); 19 | 20 | /** 21 | * prints in console array 22 | * @param[in] array 23 | * @param[in] size of array 24 | */ 25 | static void show(CZZ*& vals, long size); 26 | 27 | //----------------------------------------- 28 | 29 | /** 30 | * prints in console val1, val2 and (val1-val2) 31 | * @param[in] CZZ val 32 | * @param[in] CZZ val 33 | * @param[in] string prefix 34 | */ 35 | static void showcompare(CZZ& val1, CZZ& val2, string prefix); 36 | 37 | /** 38 | * prints in console pairwise val1[i], val2[i] and (val1[i]-val2[i]) 39 | * @param[in] array of CZZ val 40 | * @param[in] array of CZZ val 41 | * @param[in] string prefix 42 | */ 43 | static void showcompare(CZZ*& vals1, CZZ*& vals2, long size, string prefix); 44 | 45 | /** 46 | * prints in console pairwise val1[i], val2 and (val1[i]-val2) 47 | * @param[in] array of CZZ val 48 | * @param[in] CZZ val 49 | * @param[in] string prefix 50 | */ 51 | static void showcompare(CZZ*& vals1, CZZ& val2, long size, string prefix); 52 | 53 | /** 54 | * prints in console pairwise val1, val2[i] and (val1-val2[i]) 55 | * @param[in] CZZ val 56 | * @param[in] array of CZZ val 57 | * @param[in] string prefix 58 | */ 59 | static void showcompare(CZZ& val1, CZZ*& vals2, long size, string prefix); 60 | 61 | //----------------------------------------- 62 | 63 | }; 64 | 65 | #endif /* UTILS_STRINGUTILS_H_ */ 66 | -------------------------------------------------------------------------------- /src/StringUtils.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/StringUtils.o -------------------------------------------------------------------------------- /src/TestScheme.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_TESTSCHEME_H_ 2 | #define TEST_TESTSCHEME_H_ 3 | 4 | class TestScheme { 5 | public: 6 | 7 | //----------------------------------------- 8 | 9 | /** 10 | * Testing encoding and decoding timing of the ciphertext 11 | * c(m_1, ..., m_slots) 12 | * number of levels switched: 0 13 | * @param[in] logN input parameter for Params class 14 | * @param[in] logq input parameter for Params class 15 | * @param[in] log of number of slots 16 | */ 17 | static void testEncodeBatch(long logN, long logq, long precisionBits, long logSlots); 18 | 19 | //----------------------------------------- 20 | 21 | /** 22 | * Testing conjugation timing of the ciphertext 23 | * c(m_1, ..., m_slots) -> c(conjugate(m_1), ...,conjugate(m_slots)) 24 | * number of levels switched: 0 25 | * @param[in] logN input parameter for Params class 26 | * @param[in] logq input parameter for Params class 27 | * @param[in] log of number of slots 28 | */ 29 | static void testConjugateBatch(long logN, long logq, long precisionBits, long logSlots); 30 | 31 | /** 32 | * Testing multiplication by i (imaginary 1) timing of the ciphertext 33 | * c(m_1, ..., m_slots) -> c(i * m_1, ...,i * m_slots) 34 | * number of levels switched: 1 35 | * @param[in] logN input parameter for Params class 36 | * @param[in] logq input parameter for Params class 37 | * @param[in] log of number of slots 38 | */ 39 | static void testimultBatch(long logN, long logq, long precisionBits, long logSlots); 40 | 41 | /** 42 | * Testing left rotation timing in the ciphertext 43 | * number of levels switched: 0 44 | * c(m_1, ..., m_slots) -> c(m_(rotslots+1), m_(rotslots+2), ... m_(rotslots-1)) 45 | * @param[in] logN input parameter for Params class 46 | * @param[in] logq input parameter for Params class 47 | * @param[in] log of rotation number 48 | * @param[in] log of number of slots 49 | */ 50 | static void testRotateByPo2Batch(long logN, long logq, long precisionBits, long rotlogSlots, long logSlots, bool isLeft); 51 | 52 | /** 53 | * Testing left rotation timing in the ciphertext 54 | * c(m_1, ..., m_slots) -> c(m_(rotslots+1), m_(rotslots+2), ... m_(rotslots-1)) 55 | * number of levels switched: 0 56 | * @param[in] logN input parameter for Params class 57 | * @param[in] logq input parameter for Params class 58 | * @param[in] rotation number 59 | * @param[in] log of number of slots 60 | */ 61 | static void testRotateBatch(long logN, long logq, long precisionBits, long rotSlots, long logSlots, bool isLeft); 62 | 63 | /** 64 | * Testing slot summation timing in the ciphertext 65 | * c(m_1, ..., m_slots) -> c(sum(m_i), sum(m_i), ..., sum(m_i)) 66 | * number of levels switched: 0 67 | * @param[in] logN input parameter for Params class 68 | * @param[in] logq input parameter for Params class 69 | * @param[in] log of number of slots 70 | */ 71 | static void testSlotsSum(long logN, long logq, long precisionBits, long logSlots); 72 | 73 | //----------------------------------------- 74 | 75 | 76 | /** 77 | * Testing power of 2 timing of the ciphertext 78 | * c(m_1, ..., m_slots) -> c(m_1^degree/p^{degree-1}, ..., m_slots^degree/p^{degree-1}) 79 | * number of levels switched: logDegree 80 | * @param[in] logN input parameter for Params class 81 | * @param[in] logq input parameter for Params class 82 | * @param[in] log of power degree 83 | * @param[in] log of number of slots 84 | */ 85 | static void testPowerOf2Batch(long logN, long logq, long precisionBits, long logDegree, long logSlots); 86 | 87 | //----------------------------------------- 88 | 89 | /** 90 | * Testing power timing of the ciphertext 91 | * c(m_1, ..., m_slots) -> c(m_1^degree/p^{degree-1}, ..., m_slots^degree/p^{degree-1}) 92 | * number of levels switched: ceil(log(degree)) 93 | * @param[in] logN input parameter for Params class 94 | * @param[in] logq input parameter for Params class 95 | * @param[in] power degree 96 | * @param[in] log of number of slots 97 | */ 98 | static void testPowerBatch(long logN, long logq, long precisionBits, long degree, long logSlots); 99 | 100 | //----------------------------------------- 101 | 102 | /** 103 | * Testing product timing of ciphertexts 104 | * array of c_i(m_1, ..., m_slots) -> c(prod_i(m_1), ..., prod_i(m_slots)) 105 | * number of levels switched: logDegree 106 | * @param[in] logN input parameter for Params class 107 | * @param[in] logq input parameter for Params class 108 | * @param[in] log of number of ciphertexts 109 | * @param[in] log of number of slots 110 | */ 111 | static void testProdOfPo2Batch(long logN, long logq, long precisionBits, long logDegree, long logSlots); 112 | 113 | /** 114 | * Testing product timing of ciphertexts 115 | * array of c_i(m_1, ..., m_slots) -> c(prod_i(m_1), ..., prod_i(m_slots)) 116 | * number of levels switched: ceil(log(degree)) 117 | * @param[in] logN input parameter for Params class 118 | * @param[in] logq input parameter for Params class 119 | * @param[in] number of ciphertexts 120 | * @param[in] log of number of slots 121 | */ 122 | static void testProdBatch(long logN, long logq, long precisionBits, long degree, long logSlots); 123 | //----------------------------------------- 124 | 125 | /** 126 | * Testing inverse timing of ciphertext 127 | * c(m_1, ..., m_slots) -> c(p^2/m_1, ..., p^2/m_slots) 128 | * number of levels switched: invSteps 129 | * @param[in] logN input parameter for Params class 130 | * @param[in] logq input parameter for Params class 131 | * @param[in] number of steps used in method for calculating inverse 132 | * @param[in] log of number of slots 133 | */ 134 | static void testInverseBatch(long logN, long logq, long precisionBits, long invSteps, long logSlots); 135 | 136 | //----------------------------------------- 137 | 138 | /** 139 | * Testing logarithm timing of ciphertext using Taylor series approximation 140 | * c(m_1, ..., m_slots) -> c(log(m_1), ..., log(m_slots)) 141 | * number of levels switched: ceil(log(degree)) 142 | * @param[in] logN input parameter for Params class 143 | * @param[in] logq input parameter for Params class 144 | * @param[in] degree of Taylor series approximation 145 | * @param[in] log of number of slots 146 | */ 147 | static void testLogarithmBatch(long logN, long logq, long precisionBits, long degree, long logSlots); 148 | 149 | //----------------------------------------- 150 | 151 | /** 152 | * Testing exponent timing of ciphertext using Taylor series approximation 153 | * c(m_1, ..., m_slots) -> c(exp(m_1/p) * p, ..., exp(m_slots/p) * p) 154 | * number of levels switched: ceil(log(degree)) 155 | * @param[in] logN input parameter for Params class 156 | * @param[in] logq input parameter for Params class 157 | * @param[in] degree of Taylor series approximation 158 | * @param[in] log of number of slots 159 | */ 160 | static void testExponentBatch(long logN, long logq, long precisionBits, long degree, long logSlots); 161 | 162 | /** 163 | * Testing exponent timing of ciphertext using Taylor series approximation 164 | * c(m_1, ..., m_slots) -> c(exp(m_1/p) * p^2, ..., exp(m_slots/p) * p^2) 165 | * number of levels switched: ceil(log(degree)) - 1 166 | * @param[in] logN input parameter for Params class 167 | * @param[in] logq input parameter for Params class 168 | * @param[in] degree of Taylor series approximation 169 | * @param[in] log of number of slots 170 | */ 171 | static void testExponentBatchLazy(long logN, long logq, long precisionBits, long degree, long logSlots); 172 | 173 | //----------------------------------------- 174 | 175 | /** 176 | * Testing sigmoid timing of ciphertext using Taylor series approximation 177 | * c(m_1, ..., m_slots) -> c(sigmoid(m_1/p) * p, ..., sigmoid(m_slots/p) * p) 178 | * number of levels switched: ceil(log(degree)) 179 | * @param[in] logN input parameter for Params class 180 | * @param[in] logq input parameter for Params class 181 | * @param[in] degree of Taylor series approximation 182 | * @param[in] log of number of slots 183 | */ 184 | static void testSigmoidBatch(long logN, long logq, long precisionBits, long degree, long logSlots); 185 | 186 | /** 187 | * Testing sigmoid timing of ciphertext using Taylor series approximation 188 | * c(m_1, ..., m_slots) -> c(sigmoid(m_1/p) * p^2, ..., sigmoid(m_slots/p) * p^2) 189 | * number of levels switched: ceil(log(degree)) - 1 190 | * @param[in] logN input parameter for Params class 191 | * @param[in] logq input parameter for Params class 192 | * @param[in] degree of Taylor series approximation 193 | * @param[in] log of number of slots 194 | */ 195 | static void testSigmoidBatchLazy(long logN, long logq, long precisionBits, long degree, long logSlots); 196 | 197 | //----------------------------------------- 198 | 199 | /** 200 | * Testing full fft pipeline timing of two ciphertext arrays 201 | * fftinv( mult ( fft(c_1, ..., c_slots), fft(c_1, ..., c_slots) ) ) 202 | * number of levels switched: 2 203 | * @param[in] logN input parameter for Params class 204 | * @param[in] logq input parameter for Params class 205 | * @param[in] log of number of slots 206 | * @param[in] log of fft dimension 207 | */ 208 | static void testFFTBatch(long logN, long logq, long precisionBits, long logfftdim, long logSlots); 209 | 210 | /** 211 | * Testing full fft pipeline timing of two ciphertext arrays 212 | * fftinvlazy( mult ( fft(c_1, ..., c_slots), fft(c_1, ..., c_slots) ) ) 213 | * number of levels switched: 1 214 | * @param[in] logN input parameter for Params class 215 | * @param[in] logq input parameter for Params class 216 | * @param[in] log of number of slots 217 | * @param[in] log of fft dimension 218 | */ 219 | static void testFFTBatchLazy(long logN, long logq, long precisionBits, long logSlots, long logfftdim); 220 | 221 | /** 222 | * Testing full fft pipeline timing of several ciphertext arrays with multiple hadamard multipications 223 | * fftinvlazy( mult ( fft(c_1, ..., c_slots), fft(c_1, ..., c_slots) ) ) 224 | * number of levels switched: 1 225 | * @param[in] logN input parameter for Params class 226 | * @param[in] logq input parameter for Params class 227 | * @param[in] log of number of slots 228 | * @param[in] log of fft dimension 229 | * @param[in] log of number of arrays 230 | */ 231 | static void testFFTBatchLazyMultipleHadamard(long logN, long logq, long precisionBits, long logSlots, long logfftdim, long logHdim); 232 | 233 | //----------------------------------------- 234 | }; 235 | 236 | #endif /* TEST_TESTSCHEME_H_ */ 237 | -------------------------------------------------------------------------------- /src/TestScheme.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/TestScheme.o -------------------------------------------------------------------------------- /src/TimeUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeUtils.h" 2 | 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | TimeUtils::TimeUtils() { 9 | timeElapsed = 0; 10 | } 11 | 12 | void TimeUtils::start(string msg) { 13 | cout << "----------------------------------------------------------------------------------" << endl; 14 | cout <<"Start " + msg << endl; 15 | gettimeofday(&startTime, 0); 16 | } 17 | 18 | void TimeUtils::stop(string msg) { 19 | gettimeofday(&stopTime, 0); 20 | timeElapsed = (stopTime.tv_sec - startTime.tv_sec) * 1000.0; 21 | timeElapsed += (stopTime.tv_usec - startTime.tv_usec) / 1000.0; 22 | cout << msg + " time = "<< timeElapsed << " ms" << endl; 23 | cout << "----------------------------------------------------------------------------------" << endl; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/TimeUtils.h: -------------------------------------------------------------------------------- 1 | #ifndef POLYSCHEME_TIMEUTILS_H_ 2 | #define POLYSCHEME_TIMEUTILS_H_ 3 | 4 | #include 5 | 6 | struct timeval; 7 | 8 | using namespace std; 9 | 10 | class TimeUtils { 11 | public: 12 | 13 | struct timeval startTime, stopTime; 14 | double timeElapsed; 15 | 16 | //----------------------------------------- 17 | 18 | TimeUtils(); 19 | 20 | //----------------------------------------- 21 | 22 | /** 23 | * starts timer 24 | * @param[in] string message 25 | */ 26 | void start(string msg); 27 | 28 | /** 29 | * stops timer and prints time elapsed in console 30 | * @param[in] string message 31 | */ 32 | void stop(string msg); 33 | 34 | //----------------------------------------- 35 | }; 36 | 37 | #endif /* POLYSCHEME_TIMEUTILS_H_ */ 38 | -------------------------------------------------------------------------------- /src/TimeUtils.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/K-miran/HELR/c94951f2691d55defc82f95d3144c831eb6c8796/src/TimeUtils.o --------------------------------------------------------------------------------