diff --git a/ASCPU.txt b/ASCPU.txt new file mode 100644 index 0000000..763c7cb --- /dev/null +++ b/ASCPU.txt @@ -0,0 +1 @@ +AMD Opteron(tm) Processor 3380 diff --git a/CMakeLists.txt b/CMakeLists.txt index 187be4b..acc2d7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) SUBDIRS(src test app) set(CMAKE_CXX_FLAGS "-O9 -Wall") +#set(CMAKE_CXX_FLAGS "-g -O0 -Wall") # add a target to generate API documentation with Doxygen find_package(Doxygen) diff --git a/TODO b/TODO index 9d446bb..1a5bd75 100644 --- a/TODO +++ b/TODO @@ -12,8 +12,36 @@ + átállitani integer programozásra az optimalizálást + induláskor mérjen le 10-et és az alapján irja ki a várható befejezési időt és a végén meg a teljes futái időt (elég egyet is) + grafikonokat készíteni a célfüggvény értékéről illetve a változások arányáról a megtett lépések függvényében -- tudjon a progi megszakítás után elmentett állapotból folytatni ++ tudjon a progi megszakítás után elmentett állapotból folytatni ++ megnézni, hogy a BKZ_QP1 mennyivel gyorsabb mint a BKZ_XD és kipróbálni, hogy lehet-e csak az első körben XD-t használni a többiben meg QP-t (már egy LLL is szépen lecsökkenti a számokat) - viszont ha ez működik, akkor már biztos benne van az NTL-ben (BKZ-t futtattam és LLL hibaüzenetet kaptam), ha meg nem akkor nem akarok ezzel kockáztatni 3 hónapnyi számitást) ++ hogyan lehet helyesen és statisztikailag relevánsan mérni az időket? (magas dimenzióban nincs sok lehetőség a BKZ-t lemérni úgyhogy halottnak tűnik az ötlet) ++ a timingben darmstadt challange-s latticekkel teszteljen ne pedig cjloss-al (a generátor viszonylag egyszerű NTL-es cuccokat használ), mégsem, magas dimenzióban sokkal jobb ha a konkrét lattice-t kezdi el darálni ++ boundtoolba betenni a darmstadt challange-es alapértelmezett korlátot ++ implementálni a konkrét lattice-s timing-ot ++ boundary kimenetet pontosságát maximumra venni ++ lépésközt állithatóra venni ++ valamelyikbe ellenőrzést implementálni: számolja teljesen végig a pruned enumerationt és dobjon egy grafikonfilet az összehasonlitásról ++ végiggondolni hogyan kell helyesen randomizálni a bázist, kell-e javitani rajta ++ az aritmetikát mindenhol ahol kell átirni RR-re (pl gh számitás gyanús, hogy kelleni fog) (100-as challange-el tesztelni) ++ kis progi ami kigenerálja + + full + + linear + + a schneider ++ boundtoolba új funkció: bemeneti fájlban kapott boundary-ról kiirja a várható időtartamot és a sikeresélyt ++ letesztelni, hogy LLL-XD followed by BKZ-FP blocksize 40 mennyivel gyorsabb mint a BKZ-XD simán... (kezdve valamilyen alacsonyabb blokkmérettel pl 30) ++ összevonni a timing-ot és a preprocesst +- egy 110 dimenziós boundary-t számolni és összevetni phong-éval (vagy a Schneider félével, mert ebben e dimenzióban mindkettő ugyanaz) +- átirni a psuccexpet randomra +- megnézni, hogy az psuccexp-ben jó lambdát adok-e meg neki vagy egyel nagyobbat +- a verify-ba olyan opciót, hogy csak a predictiont csinálja meg, ne kelljen várni az enumeration-re +- a végén kiirni az eredmény hermite faktorát (végiggondolni, hogy az utsó sorban valóban a hermite faktorok vannak-e +- állitható gh approx faktort irni a boundary keresőhöz +- a boundary generatort kiegésziteni a schnorr- hörnerrel + + +Majd egyszer: +- a verify programot integrálni az eprune-ba ******** Itt lesz kész az extreme pruning ***** - Megnézni az early termination-ös cikkeket, hogy milyen blokkméretet lenne érdemes használni egy 128 dimenziós bázis előfeldolgozásához - Megirni a pruningos BKZ-t, enumerationt külön függvénybe tenni diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 6a57689..bab1b2b 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -2,6 +2,8 @@ SET(TARGET1 timing) SET(TARGET2 boundtool) SET(TARGET3 genlattice) SET(TARGET4 eprune) +SET(TARGET5 verify) +SET(TARGET6 genbound) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include) LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) @@ -16,3 +18,9 @@ TARGET_LINK_LIBRARIES(${TARGET3} cleanbkz ntl) ADD_EXECUTABLE(${TARGET4} eprune.cpp) TARGET_LINK_LIBRARIES(${TARGET4} cleanbkz ntl) + +ADD_EXECUTABLE(${TARGET5} verify.cpp) +TARGET_LINK_LIBRARIES(${TARGET5} cleanbkz ntl) + +ADD_EXECUTABLE(${TARGET6} genbound.cpp) +TARGET_LINK_LIBRARIES(${TARGET6} cleanbkz ntl) diff --git a/app/boundtool.cpp b/app/boundtool.cpp index 19e0c32..ab81c8f 100644 --- a/app/boundtool.cpp +++ b/app/boundtool.cpp @@ -30,7 +30,9 @@ using namespace std; // Defined in boundary.cpp -extern double ball_vol(int k, double r); +extern RR ball_vol_RR(int k, RR r); +extern void init_factorials(int up_to); +extern RR RR_PI; // Defined in tools.cpp char* get_cmd_option(char** begin, char** end, const string& option); @@ -40,11 +42,14 @@ bool cmd_option_exists(char** begin, char** end, const string& option); int main(int argc, char** argv) { double t_node= 0; double t_reduc= 0; - double delta= 1e-1; unsigned long iterations= 1000; mat_ZZ basis; + int dim; + double* boundary; ZZ v; v= 0; + ZZ delta; + delta= 1; stringstream ss; char* act_arg; @@ -56,28 +61,33 @@ int main(int argc, char** argv) { << "\t-n n\t\tThe (avarage) time the enumeration algorithm takes to process a single node. (required)" << endl << "\t-r n\t\tThe (avarege) running time of the preprocessing reduction algorithm. (required)" << endl << "\t-c n\t\tNumber of random changes to make during the numerical optimization. (default: 1000)" << endl - << "\t-d n\t\tThe size of the single random changes to meke during the optimization. (default: 0.1)" << endl - << "\t-l n\t\tOptimize for shortest vector with length square root of n. (the Gaussian heuristic is default)" << endl; + << "\t-d n\t\tThe size of the single random changes to meke during the optimization. (default: 1)" << endl + << "\t-l n\t\tOptimize for shortest vector with length square root of n. (the Gaussian heuristic is default)" << endl + << "\t-o n\t\tThe name of the file containing the information about previous computation that has to be continued. Just the -c switch can be used in this case." << endl; return 0; } - if (!cmd_option_exists(argv, argv+argc, "-f")) { - cout << "Input basis is missing. Run again with -h for help." << endl; + if (!cmd_option_exists(argv, argv+argc, "-f") && !cmd_option_exists(argv, argv+argc, "-o")) { + cout << "Input basis information is missing. Run again with -h for help." << endl; return 0; } - if (!cmd_option_exists(argv, argv+argc, "-n")) { + if (!cmd_option_exists(argv, argv+argc, "-n") && !cmd_option_exists(argv, argv+argc, "-o")) { cout << "Parameter t_node is missing. Run again with -h for help." << endl; return 0; } - if (!cmd_option_exists(argv, argv+argc, "-r")) { + if (!cmd_option_exists(argv, argv+argc, "-r") && !cmd_option_exists(argv, argv+argc, "-o")) { cout << "Parameter t_reduc is missing. Run again with -h for help." << endl; return 0; } act_arg= get_cmd_option(argv, argv + argc, "-n"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-o")){ + cerr << "ERROR: invalid switch. In the presence of the -o switch the only other switch allowed is the -c" << endl; + return 1; + } ss << act_arg; ss >> t_node; ss.clear(); @@ -89,6 +99,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-r"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-o")){ + cerr << "ERROR: invalid switch. In the presence of the -o switch the only other switch allowed is the -c" << endl; + return 1; + } ss << act_arg; ss >> t_reduc; ss.clear(); @@ -100,10 +114,14 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-d"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-o")){ + cerr << "ERROR: invalid switch. In the presence of the -o switch the only other switch allowed is the -c" << endl; + return 1; + } ss << act_arg; ss >> delta; ss.clear(); - if(delta <= 0) { + if(delta < 1) { cerr << "ERROR: invalid delta. The optimization step should be greater than zero. Aborting." << endl; return 1; } @@ -122,6 +140,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-l"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-o")){ + cerr << "ERROR: invalid switch. In the presence of the -o switch the only other switch allowed is the -c" << endl; + return 1; + } ss << act_arg; ss >> v; ss.clear(); @@ -131,9 +153,23 @@ int main(int argc, char** argv) { } } + act_arg= get_cmd_option(argv, argv + argc, "-o"); + if (act_arg) { + ifstream infile(act_arg); + if (infile.is_open()) { + continue_boundary_gen(infile, iterations, &boundary, dim); + } else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } act_arg= get_cmd_option(argv, argv + argc, "-f"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-o")){ + cerr << "ERROR: invalid switch. In the presence of the -o switch the only other switch allowed is the -c" << endl; + return 1; + } ifstream basis_file(act_arg); if (basis_file.is_open()) basis_file >> basis; @@ -143,54 +179,64 @@ int main(int argc, char** argv) { } } - mat_RR mu1; - vec_RR c1; - ComputeGS(basis,mu1,c1); - - //lengths of the GS basis vectors - RR* c= new RR[mu1.NumRows()]; - for(int i= 0; i < mu1.NumRows(); i++) { - c[i]= SqrRoot(c1[i]); - c[i].SetPrecision(RR_PRECISION); - } - int dim= mu1.NumRows(); - double* boundary= new double[dim]; - cout << "# Generated with cleanbkz " << CBKZ_VERSION << endl << "# Copyright (C) 2014 Janos Follath" << endl << "# This is free software with ABSOLUTELY NO WARRANTY." << endl << "#" << endl; - //length of the shortest vector in the cjloss lattice - if(v>0) { - //v= sqrt(v); - cout << "# Using supplied lambda square: " << v << endl; - } - else { - double tmp,gh= 1; - double* gsghs= new double[dim]; + if(!cmd_option_exists(argv, argv+argc, "-o")){ + mat_RR mu1; + vec_RR c1; + ComputeGS(basis,mu1,c1); + + //lengths of the GS basis vectors + RR* c= new RR[mu1.NumRows()]; for(int i= 0; i < mu1.NumRows(); i++) { - conv(tmp, c[i]); - gh*= tmp; - gsghs[i]= pow(gh/ball_vol(i+1, 1),1.0/(i+1)); + c[i].SetPrecision(RR_PRECISION); + c[i]= SqrRoot(c1[i]); + } + + dim= mu1.NumRows(); + boundary= new double[dim]; + + //length of the shortest vector in the cjloss lattice + if(v>0) { + //v= sqrt(v); + cout << "# Using supplied lambda square: " << v << endl; + } + else { + RR_PI.SetPrecision(RR_PRECISION); + RR_PI= ComputePi_RR(); + init_factorials(2*dim+1); + RR one,gh,exp; + one.SetPrecision(RR_PRECISION); + gh.SetPrecision(RR_PRECISION); + exp.SetPrecision(RR_PRECISION); + gh= one= 1; + for(int i= 0; i < mu1.NumRows(); i++) { + gh*= sqrt(c1[i]); + } + exp= 1.0/dim; + pow(gh, gh/ball_vol_RR(dim, one), exp); + gh*= 1.05; + conv(v, gh*gh); + cout << "# No lambda square supplied, using Gaussian heuristic: " << gh << endl; } - delete gsghs; - gh= pow(gh/ball_vol(dim, 1),1.0/dim); - v= gh*gh; - cout << "# No lambda square supplied, using Gaussian heuristic: " << v << endl; - } + double p_succ; + double t_enum; + //NOTE: gs vector lengths and wanted vector length given + + generate_boundary(c, t_node, t_reduc, dim, boundary, v, delta, iterations, p_succ, t_enum, false); - double p_succ; - double t_enum; - //NOTE: gs vector lengths and wanted vector length given - generate_boundary(c, t_node, t_reduc, dim, boundary, v, delta, iterations, p_succ, t_enum, false); + cout << "# basis: '" << act_arg << "' " << endl + << "# estimated enumeration time: " << t_enum << endl + << "# success probability: " << p_succ << endl; + } - cout << "# basis: '" << act_arg << "' " << endl - << "# estimated enumeration time: " << t_enum << endl - << "# success probability: " << p_succ << endl - << "# boudary function: " << endl; + cout << "# boudary function: " << endl; + vec_RR out; out.SetLength(dim); @@ -198,8 +244,10 @@ int main(int argc, char** argv) { out[i]= boundary[i]; cout << "# " << out << endl << endl; - for(int i= 0; i < dim; i++) - cout << i << " " << boundary[i] << endl; + for(int i= 0; i < dim; i++) { + out[i].SetOutputPrecision(RR_PRECISION); + cout << i << " " << out[i] << endl; + } cout << endl; return 0; diff --git a/app/eprune.cpp b/app/eprune.cpp index c7000fa..7b969a4 100644 --- a/app/eprune.cpp +++ b/app/eprune.cpp @@ -33,6 +33,8 @@ extern void enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& r extern void profile_enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& result); +// The maximum of the coefficients of the random unimodular matrix +#define UNIMOD_SIZE 100 mat_ZZ unimod(int dim){ mat_ZZ L, U; L.SetDims(dim, dim); @@ -43,8 +45,8 @@ mat_ZZ unimod(int dim){ for(int i= 0; i < dim; i++) for(int j= i+1; j < dim; j++) { - U[i][j]= RandomBnd(2); - L[j][i]= RandomBnd(2); + U[i][j]= RandomBnd(UNIMOD_SIZE); + L[j][i]= RandomBnd(UNIMOD_SIZE); } return L*U; @@ -60,7 +62,7 @@ int main(int argc, char** argv) { if (argc==1 || cmd_option_exists(argv, argv+argc, "-h")) { cout << "This program performs lattice enumeration with extreme pruning:" << endl << "\t-h \t\tPrint this help." << endl - << "\t-v \t\tPerforms a single enumeration round and compares the nodes to the prediction." << endl + //<< "\t-v \t\tPerforms a single enumeration round and compares the nodes to the prediction." << endl << "\t-l filename\tReads the lattice from the file filename. (This option is mandatory)" << endl << "\t-b filename\tReads the boundary function from the file filename. (This option is mandatory)" << endl; return 0; @@ -119,7 +121,7 @@ int main(int argc, char** argv) { double* boundary= new double[basis.NumRows()]; for(int i= 0; i < basis.NumRows(); i++){ conv(boundary[i], bnd[i]); - boundary[i]*= boundary[i]; + //boundary[i]*= boundary[i]; } vec_RR solution; @@ -147,7 +149,8 @@ int main(int argc, char** argv) { begin= clock(); basis= basis*unimod(basis.NumRows()); - BKZ_QP1(basis, 0.99, beta); + LLL_XD(basis, 0.99); + BKZ_FP(basis, 0.99, beta); ComputeGS(basis,mu1,c1); @@ -192,7 +195,7 @@ int main(int argc, char** argv) { for(int i= 0; i< basis.NumRows(); i++) sqrdLength+= sol[i]*sol[i]; - cout << "Squared length of the shortest vector: " << sqrdLength << endl << endl; + cout << "Length of the shortest vector: " << sqrt(sqrdLength) << endl << endl; cout << "Time spent with enumeration: " << t_all/CLOCKS_PER_SEC << endl; cout << "Time spent with reduction: " << t_reduc/CLOCKS_PER_SEC << endl; diff --git a/app/genbound.cpp b/app/genbound.cpp new file mode 100644 index 0000000..cc98385 --- /dev/null +++ b/app/genbound.cpp @@ -0,0 +1,238 @@ +/* + Copyright (C) 2014 Janos Follath. + + This file is part of cleanbkz. + + cleanbkz is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cleanbkz is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cleanbkz. If not, see . + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Defined in boundary.cpp +extern RR ball_vol_RR(int k, RR r); +extern void init_factorials(int up_to); +extern RR RR_PI; +extern RR t_extreme_RR(RR Rvec[], RR b_star_norm[], double t_node, double t_reduc, int n); +extern RR p_succ(RR Rvec[], int n); + +// Defined in tools.cpp +char* get_cmd_option(char** begin, char** end, const string& option); +bool cmd_option_exists(char** begin, char** end, const string& option); + + +int main(int argc, char** argv) { + mat_ZZ basis; + int dim; + double* boundary; + ZZ R2; + R2= 0; + double t_node, t_reduc; + t_node= t_reduc= 0; + + stringstream ss; + char* act_arg; + + if (argc==1 || cmd_option_exists(argv, argv+argc, "-h")) { + cout << "This program generates boundary functions for full enumeration, linear pruning and Schneider's polynomial pruning. A preprocessed basis of the lattice is required. Options -f -d and -s are mutually exclusive. Program options:" << endl + << "\t-h \t\tPrint this help." << endl + << "\t-l n\t\tThe name of the file containing the preprocessed lattice basis. (required)" << endl + << "\t-f n\t\tGenerate boundary without pruning" << endl + << "\t-d n\t\tGenerate double step linear boundary" << endl + << "\t-s n\t\tGenerate Schneiders boundary function (default)" << endl + << "\t-n n\t\tThe (avarage) time the enumeration algorithm takes to process a single node. (optional)" << endl + << "\t-r n\t\tThe (avarege) running time of the preprocessing reduction algorithm. (optional)" << endl; + return 0; + } + + act_arg= get_cmd_option(argv, argv + argc, "-n"); + if (act_arg) { + ss << act_arg; + ss >> t_node; + ss.clear(); + if(t_node < 0) { + cerr << "ERROR: invalid t_node. The running time should be greater than or equal to zero. Aborting." << endl; + return 1; + } + } + + act_arg= get_cmd_option(argv, argv + argc, "-r"); + if (act_arg) { + ss << act_arg; + ss >> t_reduc; + ss.clear(); + if(t_reduc < 0) { + cerr << "ERROR: invalid t_reduc. The running time should be greater than or equal to zero. Aborting." << endl; + return 1; + } + } + + if (!cmd_option_exists(argv, argv+argc, "-l")) { + cout << "Input basis information is missing. Run again with -h for help." << endl; + return 0; + } + + if ((cmd_option_exists(argv, argv+argc, "-s") && cmd_option_exists(argv, argv+argc, "-d")) || (cmd_option_exists(argv, argv+argc, "-s") && cmd_option_exists(argv, argv+argc, "-f")) || (cmd_option_exists(argv, argv+argc, "-f") && cmd_option_exists(argv, argv+argc, "-d")) ) { + cout << "Options -f -d and -s are mutually exclusive. Run again with -h for help." << endl; + return 0; + } + + act_arg= get_cmd_option(argv, argv + argc, "-l"); + if (act_arg) { + ifstream basis_file(act_arg); + if (basis_file.is_open()) + basis_file >> basis; + else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } + + + cout << "# Generated with cleanbkz " << CBKZ_VERSION << endl + << "# Copyright (C) 2014 Janos Follath" << endl + << "# This is free software with ABSOLUTELY NO WARRANTY." << endl << "#" << endl; + + mat_RR mu1; + vec_RR c1; + ComputeGS(basis,mu1,c1); + + //lengths of the GS basis vectors + RR* c= new RR[mu1.NumRows()]; + for(int i= 0; i < mu1.NumRows(); i++) { + c[i].SetPrecision(RR_PRECISION); + c[i]= SqrRoot(c1[i]); + } + + dim= mu1.NumRows(); + //dim=110; + boundary= new double[dim]; + + RR_PI.SetPrecision(RR_PRECISION); + RR_PI= ComputePi_RR(); + init_factorials(2*dim+1); + RR one,gh,exp; + one.SetPrecision(RR_PRECISION); + gh.SetPrecision(RR_PRECISION); + exp.SetPrecision(RR_PRECISION); + gh= one= 1; + for(int i= 0; i < mu1.NumRows(); i++) { + gh*= sqrt(c1[i]); + } + exp= 1.0/dim; + pow(gh, gh/ball_vol_RR(dim, one), exp); + gh*= 1.05; + conv(R2, gh*gh); + cout << "# Using Darmstadt bound (Gaussian heuristic times 1.05): " << gh << endl; + cout << "# basis: '" << act_arg << "' " << endl; + + if(cmd_option_exists(argv, argv+argc, "-f")) { + ZZ* act= new ZZ[dim]; + act[0]= act[1]= (2*R2)/dim; + for(int i= 2; i < dim; i+=2) { + act[i]= act[i+1]= act[i-1]+act[0]; + //cout << act[i] << endl; + } + act[dim-1]= R2; + if(dim%2==0) + act[dim-2]= R2; + + for(int i= 0; i < dim; i++) + conv(boundary[i],act[i]); + } else if (cmd_option_exists(argv, argv+argc, "-d")) { + for(int i= 0; i < dim; i++) + conv(boundary[i],R2); + } else { + /*double coeffs[]= {9.1e-4, 4e-2, -4e-3, 2.3e-4, -6.9e-6, 1.21e-7, -1.2e-9, 6.2e-12, -1.29e-14}; + for(int i= 1; i<=dim; i++) { + boundary[i-1]= 0; + for(int j= 0; j<=8; j++) + //boundary[i-1]+= pow(i*110/dim,j)*coeffs[j]; + boundary[i-1]+= pow(1.0*i/dim,j)*coeffs[j]; + //boundary[i-1]*=110/dim;*/ + double div = (double) dim; + double y,scale; + conv(scale,R2); + for (double x = 1; x<=dim; x+=1){ + y = x/div; + boundary[int(x)] = min( -276.919520419850*pow(y,8) \ + +1208.33321732860 *pow(y,7) \ + -2128.79627565000 *pow(y,6) \ + +1952.22801180000 *pow(y,5) \ + -1012.11476080000 *pow(y,4) \ + + 305.211610000000*pow(y,3) \ + - 51.347076000000*pow(y,2) \ + + 4.408932000000*pow(y,1) \ + + 0.000914465000, 1.0); + boundary[int(x)]*= scale; + } + + for(int i= 0; i< dim; i+=2) + boundary[i]= boundary[i+1]= floor(boundary[i+1]); + + for(int i= 1; i< dim-1; i+=2) + if(boundary[i]>boundary[i+1]) + for(int j= i; j >= 0; j--) + if(boundary[j] > boundary[i+1]) + boundary[j]= boundary[i+1]; + + + + } + + RR* act= new RR[dim]; + for(int i= 0; i< dim; i++) + conv(act[i],boundary[i]); + + RR p_succ_r; + RR t_enum; + if((t_node!=0)&&(t_reduc!=0)) + t_enum= t_extreme_RR(act, c, t_node, t_reduc, dim); + + + RR* mod_f= new RR[dim]; + for(int j= 0; j < dim; j++) { + conv(mod_f[j], act[j]); + mod_f[j]= sqrt(mod_f[j]); + } + p_succ_r= p_succ(mod_f, dim); + + cout << "# estimated enumeration time: " << t_enum << endl; + cout << "# success probability: " << p_succ_r << endl; + cout << "# boudary function: " << endl; + + + vec_RR out; + out.SetLength(dim); + for(int i= 0; i < dim; i++) + out[i]= boundary[i]; + cout << "# " << out << endl << endl; + + for(int i= 0; i < dim; i++) { + out[i].SetOutputPrecision(RR_PRECISION); + cout << i << " " << out[i] << endl; + } + cout << endl; + + return 0; +} diff --git a/app/genlattice.cpp b/app/genlattice.cpp index a50ff55..f25b56c 100644 --- a/app/genlattice.cpp +++ b/app/genlattice.cpp @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -28,7 +29,15 @@ using namespace std; -//TODO: refaktorálni a paraméterfeldolgozást: csinálni hozzá int és double változatot, hibaüzenetekkel és kivételkezeléssel +// Defined in boundary.cpp +extern RR ball_vol_RR(int k, RR r); +extern void init_factorials(int up_to); +extern RR RR_PI; +extern void enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& result, + unsigned long &termination, double &time); + + +void measure_epr(mat_ZZ& basis, int beta, unsigned long termination, double& t_node, double& t_reduc); void gen_randlat(mat_ZZ& basis, ZZ determinant, int dim) { basis.SetDims(dim, dim); @@ -62,16 +71,18 @@ int main(int argc, char** argv) { << "\t-m n\t\tGenerates a random lattice with entries of length at most n. It is ignored when -c is given." << endl << "\t-h \t\tPrint this help." << endl << "\t-s n\t\tUse n as the seed of the pseudorandom generator." << endl + << "\t-p filename\tPreprocess an existing lattice basis" << endl + << "\t-t \t\tMeasure and output enumeration timing information" << endl << "\t-k n\t\tReduces the generated basis with blocksize of n." << endl; return 0; } - if (!cmd_option_exists(argv, argv+argc, "-d")) { + if (!cmd_option_exists(argv, argv+argc, "-d") && !cmd_option_exists(argv, argv+argc, "-p")) { cout << "Lattice dimension is missing. Run again with -h for help." << endl; return 0; } - if (!cmd_option_exists(argv, argv+argc, "-m") && !cmd_option_exists(argv, argv+argc, "-c")) { + if (!cmd_option_exists(argv, argv+argc, "-m") && !cmd_option_exists(argv, argv+argc, "-c") && !cmd_option_exists(argv, argv+argc, "-p")) { cout << "ERROR: neither maximum size of entries nor density is provided. Aborting." << endl; return 0; } @@ -161,11 +172,100 @@ int main(int argc, char** argv) { GenPrime(determinant,maxsize); gen_randlat(m,determinant,dim); } + else if (cmd_option_exists(argv, argv+argc, "-p")) { + act_arg= get_cmd_option(argv, argv + argc, "-p"); + ifstream basis_file(act_arg); + if (basis_file.is_open()) + basis_file >> m; + else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } - if(beta > 1 && !(cmd_option_exists(argv, argv+argc, "-c"))) - BKZ_QP1(m, 0.99, beta); + double t_node, t_reduc; + if(beta > 1 && !(cmd_option_exists(argv, argv+argc, "-c"))) { + + if(cmd_option_exists(argv, argv+argc, "-t")) { + measure_epr(m, beta, 10000000, t_node, t_reduc); + }else{ + LLL_XD(m, 0.99); + BKZ_FP(m, 0.99, beta); + } + } - cout << m << endl << beta; + cout << m << endl << beta << endl; + if(cmd_option_exists(argv, argv+argc, "-t")) { + cout << t_node << endl; + cout << t_reduc << endl; + } return 0; } + +void measure_epr(mat_ZZ& basis, int beta, unsigned long termination, double& t_node, double& t_reduc) { + double enu_time= 0; + mat_RR mu1; + vec_RR c1; + clock_t begin, end; + vec_RR result; + unsigned long nodes; + + t_node= t_reduc= 0; + + int dimension= basis.NumRows(); + + double** mu= new double*[dimension]; + for(int i= 0; i < dimension; i++) + mu[i]= new double[dimension]; + + double* c= new double[dimension]; + + begin= clock(); + LLL_XD(basis, 0.99); + BKZ_FP(basis, 0.99, beta); + end= clock(); + + ComputeGS(basis,mu1,c1); + + for(int i= 0; i < dimension; i++) + for(int j= 0; j < dimension; j++) + conv(mu[i][j], mu1[i][j]); + + for(int i= 0; i < dimension; i++) + conv(c[i], c1[i]); + + + RR_PI.SetPrecision(RR_PRECISION); + RR_PI= ComputePi_RR(); + init_factorials(2*dimension+1); + RR one,gh,exp; + one.SetPrecision(RR_PRECISION); + gh.SetPrecision(RR_PRECISION); + exp.SetPrecision(RR_PRECISION); + gh= one= 1; + for(int i= 0; i < mu1.NumRows(); i++) { + gh*= sqrt(c1[i]); + } + exp= 1.0/dimension; + pow(gh, gh/ball_vol_RR(dimension, one), exp); + gh*= 1.05; + + //cout << "Using Darmstadt bound: " << gh << endl; + + double* Rvec= new double[dimension]; + for(int i= 0; i < dimension; i++) + conv(Rvec[i], gh*gh); + + t_reduc= (double)(end - begin) / CLOCKS_PER_SEC; + nodes= termination; + enumerate_epr(mu, c, Rvec, dimension, result, nodes, enu_time); + + /*if(enu_time < 1.0/CLOCKS_PER_SEC/termination) + cerr << "Warning! Zero enumeration time!" << endl; + else if (nodes!=0) + cerr << "Warning! Nodes traversed: " << (termination-nodes) << endl;*/ + t_node= enu_time; + +} + diff --git a/app/timing.cpp b/app/timing.cpp index 755f1d7..f123906 100644 --- a/app/timing.cpp +++ b/app/timing.cpp @@ -19,10 +19,12 @@ */ #include +#include #include #include #include #include +#include #include #include @@ -34,6 +36,13 @@ using namespace NTL; void measure_epr(int dimension, int beta, unsigned long samples, unsigned long termination, double& t_node, double& t_reduc, unsigned long& zeroes, unsigned long& bias); +void measure_epr(mat_ZZ basis, int beta, unsigned long termination, double& t_node, double& t_reduc); + +// Defined in boundary.cpp +extern RR ball_vol_RR(int k, RR r); +extern void init_factorials(int up_to); +extern RR RR_PI; + int main(int argc, char** argv) { int dimension= 0; int bkz_blocksize= 2; @@ -48,6 +57,7 @@ int main(int argc, char** argv) { if (argc==1 || cmd_option_exists(argv, argv+argc, "-h")) { cout << "This program uses cjloss lattices to measure the parameters t_node and t_reduc required for the computation of boundary functions. These are the running time of the enumeration and reduction algorithms on the current platform (in the case the cjloss lattices the dimension of the preprocessing is one higher than the enumeration). Program options:" << endl << "\t-h \t\tPrint this help." << endl + << "\t-l filename\tPerform tests on the given lattice. (no other switch is allowed just the -b and the -k)" << endl << "\t-d n\t\tMeasure running times in dimension n." << endl << "\t-s n\t\tStart the measurements in dimension n. It is ignored when -d is given." << endl << "\t-e n\t\tContinue measuring in all dimensions until dimension n with a step five. It is ignored when -d is given." << endl @@ -72,6 +82,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-d"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-l")){ + cerr << "ERROR: invalid switch. In the presence of the -l switch the only other switch allowed is the -b and the -k" << endl; + return 1; + } ss << act_arg; ss >> dimension; ss.clear(); @@ -83,6 +97,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-n"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-l")){ + cerr << "ERROR: invalid switch. In the presence of the -l switch the only other switch allowed is the -b and the -k" << endl; + return 1; + } ss << act_arg; ss >> samples; ss.clear(); @@ -105,6 +123,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-s"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-l")){ + cerr << "ERROR: invalid switch. In the presence of the -l switch the only other switch allowed is the -b and the -k" << endl; + return 1; + } ss << act_arg; ss >> start; ss.clear(); @@ -116,6 +138,10 @@ int main(int argc, char** argv) { act_arg= get_cmd_option(argv, argv + argc, "-e"); if (act_arg) { + if(cmd_option_exists(argv, argv+argc, "-l")){ + cerr << "ERROR: invalid switch. In the presence of the -l switch the only other switch allowed is the -b and the -k" << endl; + return 1; + } ss << act_arg; ss >> end; ss.clear(); @@ -125,6 +151,18 @@ int main(int argc, char** argv) { } } + mat_ZZ basis; + act_arg= get_cmd_option(argv, argv + argc, "-l"); + if (act_arg) { + ifstream basis_file(act_arg); + if (basis_file.is_open()) + basis_file >> basis; + else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } + cout << "cleanbkz " << CBKZ_VERSION << endl << "Copyright (C) 2014 Janos Follath" << endl << "This is free software with ABSOLUTELY NO WARRANTY." << endl << endl; @@ -145,8 +183,14 @@ int main(int argc, char** argv) { cout << "t_node= " << t_node << endl; cout << "t_reduc= " << t_reduc << endl; cout << "biased/zeroes: " << bias << "/" << zeroes << endl << endl; - } - else { + } else if(cmd_option_exists(argv, argv+argc, "-l")){ + cout << "Measuring timing for: " << get_cmd_option(argv, argv + argc, "-l") << endl; + + measure_epr(basis, bkz_blocksize, nodes, t_node, t_reduc); + + cout << "t_node= " << t_node << endl; + cout << "t_reduc= " << t_reduc << endl; + } else { if (cmd_option_exists(argv, argv+argc, "-t")) { unsigned long int total= 0; for(int i= start; i <= end; i+=5) { @@ -168,11 +212,11 @@ int main(int argc, char** argv) { cout << "t_reduc= " << t_reduc << endl; cout << "biased/zeroes: " << bias << "/" << zeroes << endl << endl; } - } - cout << "(Sometimes the enumeration doesn't have to inspect the prescribed number of nodes or even nodes enough " + cout << "(Sometimes the enumeration doesn't have to inspect the prescribed number of nodes or even nodes enough " << "to make the runing time measureable, the number of these cases are in the \"biased/zeroes\" line." << "The first number measures only the biased cases with nonzero running time.)" << endl << endl; + } return 0; } @@ -209,7 +253,8 @@ void measure_epr(int dimension, int beta, unsigned long samples, unsigned long t tmp= lattice->get_basis(0); begin= clock(); - BKZ_QP1(tmp, 0.99, beta); + LLL_XD(tmp, 0.99); + BKZ_FP(tmp, 0.99, beta); end= clock(); t_reduc+= (double)(end - begin) / CLOCKS_PER_SEC; @@ -243,3 +288,69 @@ void measure_epr(int dimension, int beta, unsigned long samples, unsigned long t t_reduc/= samples; } +void measure_epr(mat_ZZ basis, int beta, unsigned long termination, double& t_node, double& t_reduc) { + double enu_time= 0; + mat_RR mu1; + vec_RR c1; + clock_t begin, end; + vec_RR result; + unsigned long nodes; + + t_node= t_reduc= 0; + + int dimension= basis.NumRows(); + + double** mu= new double*[dimension]; + for(int i= 0; i < dimension; i++) + mu[i]= new double[dimension]; + + double* c= new double[dimension]; + + begin= clock(); + LLL_XD(basis, 0.99); + BKZ_FP(basis, 0.99, beta); + end= clock(); + + ComputeGS(basis,mu1,c1); + + for(int i= 0; i < dimension; i++) + for(int j= 0; j < dimension; j++) + conv(mu[i][j], mu1[i][j]); + + for(int i= 0; i < dimension; i++) + conv(c[i], c1[i]); + + + RR_PI.SetPrecision(RR_PRECISION); + RR_PI= ComputePi_RR(); + init_factorials(2*dimension+1); + RR one,gh,exp; + one.SetPrecision(RR_PRECISION); + gh.SetPrecision(RR_PRECISION); + exp.SetPrecision(RR_PRECISION); + gh= one= 1; + for(int i= 0; i < mu1.NumRows(); i++) { + gh*= sqrt(c1[i]); + } + exp= 1.0/dimension; + pow(gh, gh/ball_vol_RR(dimension, one), exp); + gh*= 1.05; + + cout << "Using Darmstadt bound: " << gh << endl; + + double* Rvec= new double[dimension]; + for(int i= 0; i < dimension; i++) + conv(Rvec[i], gh*gh); + + t_reduc= (double)(end - begin) / CLOCKS_PER_SEC; + nodes= termination; + enumerate_epr(mu, c, Rvec, dimension, result, nodes, enu_time); + + if(enu_time < 1.0/CLOCKS_PER_SEC/termination) + cerr << "Warning! Zero enumeration time!" << endl; + else if (nodes!=0) + cerr << "Warning! Nodes traversed: " << (termination-nodes) << endl; + t_node= enu_time; + +} + diff --git a/app/verify.cpp b/app/verify.cpp new file mode 100644 index 0000000..cf7cd2d --- /dev/null +++ b/app/verify.cpp @@ -0,0 +1,128 @@ +/* + Copyright (C) 2014 Janos Follath. + + This file is part of cleanbkz. + + cleanbkz is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cleanbkz is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cleanbkz. If not, see . + +*/ + +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +extern void init_factorials(int); + +extern void predict_nodes_RR(RR Rvec[], double b_star_norm[], int n); + +extern double ball_vol(int k, double r); + +extern void profile_enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& result); + +void gen_randlat(mat_ZZ& basis, ZZ determinant, int dim); + +int main(int argc, char** argv) { + int dim; + mat_ZZ basis; + vec_ZZ boundary; + char* act_arg; + + if (argc==1 || cmd_option_exists(argv, argv+argc, "-h")) { + cout << "This program verifies the node prediction." << endl + << "\t-h \t\tPrint this help." << endl + << "\t-l n\t\tThe name of the file containing the preprocessed lattice basis. (required)" << endl + << "\t-b n\t\tThe name of the file containing the boundary function. (required)" << endl; + return 0; + } + + act_arg= get_cmd_option(argv, argv + argc, "-b"); + if (act_arg) { + ifstream basis_file(act_arg); + if (basis_file.is_open()) { + basis_file >> boundary; + cout << "# Bounding function: " << endl << "# " << boundary << endl; + } else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } + + act_arg= get_cmd_option(argv, argv + argc, "-l"); + if (act_arg) { + ifstream basis_file(act_arg); + if (basis_file.is_open()){ + basis_file >> basis; + } else { + cerr << "ERROR: can't open input file: '" << act_arg << "'. Aborting." << endl; + return 1; + } + } + + dim= basis.NumRows(); + + mat_RR mu1; + vec_RR c1; + ComputeGS(basis,mu1,c1); + + double* c= new double[mu1.NumRows()]; + for(int i= 0; i < mu1.NumRows(); i++) + conv(c[i], c1[i]); + + + double** mu= new double*[mu1.NumRows()]; + for(int i= 0; i < mu1.NumRows(); i++) + mu[i]= new double[mu1.NumCols()]; + for(int i= 0; i < mu1.NumRows(); i++) + for(int j= 0; j < mu1.NumCols(); j++) + conv(mu[i][j], mu1[i][j]); + +// Gaussian heuristic + double gh= 1; + for(int i= 0; i < mu1.NumRows(); i++) + gh*= sqrt(c[i]); + gh= 1.05* pow(gh/ball_vol(dim, 1),1.0/dim); + cout << "# Darmstadt bound: " << gh << endl; + +// Enumeration + double* act= new double[dim]; + for(int i= 0; i data/svpchallengedim80seed0red20.lat +./bin/timing -l data/svpchallengedim80seed0.lat -k 20 +./bin/boundtool -f data/svpchallengedim80seed0red20.lat -n 8e-08 -r 9.74 -c 300 -d 100000 + + diff --git a/debug.sh b/debug.sh index 4ec444e..15d64dc 100755 --- a/debug.sh +++ b/debug.sh @@ -5,8 +5,8 @@ extension="${filename##*.}" filename="${filename%.*}" # gnuplot -p -e "set terminal pdf;set output '$filename.pdf';unset key;set yrange [0:*];plot '$1'" -gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [0:*]; plot '$1' i 0 u 1:2 w lines title columnheader(1), '$1' i 1 u 1:2 w lines title columnheader(1)" -#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [0:*]; plot '$1' i 0 u 1:2 w lines title columnheader(1), '$1' i 1 u 1:2 w lines title columnheader(1)" +gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" #gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" #gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:1.21e+24];set logscale y; set ytics(1.02e+03,1.05e+06,1.07e+09,1.1e+12,1.13e+15,1.15e+18,1.18e+21,1.21e+24);plot '$1' i 0 u 1:2 title columnheader(1)" #gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1), '$1' i 2 u 1:2 w dots title columnheader(1)" diff --git a/include/cleanbkz/boundary.hpp b/include/cleanbkz/boundary.hpp index 16153de..8bf46fe 100644 --- a/include/cleanbkz/boundary.hpp +++ b/include/cleanbkz/boundary.hpp @@ -55,11 +55,19 @@ void generate_boundary( int n, //!< The dimension of the lattice double Rvec[], //!< Container with enough space reserved for the result (n double values) NTL::ZZ R, //!< The square length of the vector the enumeration is looking for - double delta, //!< The step of the random modifications + ZZ delta, //!< The step of the random modifications unsigned long iterations, //!< The number of random modifications to test double& p_succ, //!< Container for the success probability of the resulting function double& t_enum, //!< Container for the estimated running time of the resulting function bool quiet //!< Set this false if you do not want this function to print on the standard output ); +/** Continues a previously started boundary function optimization for enumeration with extreme pruning. Uses numerical optimization with random changes as briefly explained in: Nicolas Gama, Phong Q. Nguyen and Oded Regev "Lattice Enumeration using Extreme Pruning", Advances in Cryptology – EUROCRYPT 2010 Lecture Notes in Computer Science Volume 6110, 2010, pp 257-278. */ +void continue_boundary_gen( + std::ifstream& infile, //!< Reference to the input file stream containing the information about the previous computation + unsigned long iterations, //!< The number of random modifications to test + double** Rvec, //!< This parameter will hold the result + int& dim //!< This parameter will hold the length of the result + ); + #endif diff --git a/newCPU.txt b/newCPU.txt new file mode 100644 index 0000000..023aa48 --- /dev/null +++ b/newCPU.txt @@ -0,0 +1,17 @@ +http://www.cpubenchmark.net/high_end_cpus.html +Intel Core i7-4790K @ 4.00GHz - 300USD (11,290) +Intel Core i7-5820K @ 3.30GHz - 375USD (12,952) +Intel Core i7-5930K @ 3.50GHz - 550USD (13,493) + +Intel Xeon E5-1650 v2 @ 3.20GHz - 560USD (12,495) + + +---------------------------------------------------------------------------- +Xeon vs i7 + +The current line of Xeons are based on the same architecture as the i7. The difference is usually that the Xeons are the cream of the crop. They run cooler and at lower voltages and are spec'd for 24/7 continuous usage. Otherwise, performance is usually identical. Xeons are able to be used in multi-socket motherboards, where i7s are not (which is why the Mac Pros use them). + +Xeons are also usually the first to be updated. There are 6-core Xeons, but not i7s yet, though they are still based on the same architecture. + +The additional reliability of the Xeons is very important in servers, especially rackmount and blade-enclosed servers where the lower heat dissipation and power consumption are essential. These benefits usually don't mean too much to all but the most extreme overclockers though, so people in the desktop segment usually ignore it due to the enormous difference in the price of both the CPU and the motherboards needed to support them. + diff --git a/plot_boundary.sh b/plot_boundary.sh new file mode 100755 index 0000000..cd35f8d --- /dev/null +++ b/plot_boundary.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +filename=$(basename "$1") +extension="${filename##*.}" +filename="${filename%.*}" + +gnuplot -p -e "set terminal pdf;set output '$filename.pdf';unset key;set yrange [0:*];plot '$1'" diff --git a/plot_nodes.sh b/plot_nodes.sh new file mode 100755 index 0000000..15d64dc --- /dev/null +++ b/plot_nodes.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +filename=$(basename "$1") +extension="${filename##*.}" +filename="${filename%.*}" + +# gnuplot -p -e "set terminal pdf;set output '$filename.pdf';unset key;set yrange [0:*];plot '$1'" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [0:*]; plot '$1' i 0 u 1:2 w lines title columnheader(1), '$1' i 1 u 1:2 w lines title columnheader(1)" +gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:1.21e+24];set logscale y; set ytics(1.02e+03,1.05e+06,1.07e+09,1.1e+12,1.13e+15,1.15e+18,1.18e+21,1.21e+24);plot '$1' i 0 u 1:2 title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1), '$1' i 2 u 1:2 w dots title columnheader(1)" diff --git a/plot_progress.sh b/plot_progress.sh new file mode 100755 index 0000000..4ec444e --- /dev/null +++ b/plot_progress.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +filename=$(basename "$1") +extension="${filename##*.}" +filename="${filename%.*}" + +# gnuplot -p -e "set terminal pdf;set output '$filename.pdf';unset key;set yrange [0:*];plot '$1'" +gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [0:*]; plot '$1' i 0 u 1:2 w lines title columnheader(1), '$1' i 1 u 1:2 w lines title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:1.21e+24];set logscale y; set ytics(1.02e+03,1.05e+06,1.07e+09,1.1e+12,1.13e+15,1.15e+18,1.18e+21,1.21e+24);plot '$1' i 0 u 1:2 title columnheader(1)" +#gnuplot -p -e "set terminal pdf;set output '$filename.pdf';set yrange [1:*];set logscale y; plot '$1' i 0 u 1:2 w dots title columnheader(1), '$1' i 1 u 1:2 w dots title columnheader(1), '$1' i 2 u 1:2 w dots title columnheader(1)" diff --git a/ratio.tmp b/ratio.tmp index 745bc2e..0f219c0 100644 --- a/ratio.tmp +++ b/ratio.tmp @@ -1 +1 @@ -2 13 69 339 1355 4788 14545 39469 95677 201819 412763 819609 1676146 3101275 4998689 7436042 10740473 13423824 15591263 17141409 17619306 16238926 14688734 12495592 10446876 8711786 6795375 4899701 3329245 2157371 1343679 742077 440010 256421 137334 66845 29540 12577 5305 1978 720 304 100 27 13 5 2 2 2 2 \ No newline at end of file +3 8 30 98 271 652 1702 3832 9545 19088 33302 53278 75818 103773 188586 269434 343133 404652 695414 945785 1088151 1106141 1421885 1506474 2250998 2514364 2403021 2154305 2633790 2476946 3421878 3800470 4588395 4574138 5128969 4479082 5593639 5394202 6790987 6764986 7350251 6177154 6524585 5578909 6842017 6552596 6709821 5502239 5892175 5036320 5197335 4252727 4689694 4222734 4219745 3322200 3194977 2318880 2210445 1768962 1458399 999343 751817 499596 392694 254070 179656 101933 57388 27289 13388 5374 2083 807 268 77 22 7 1 1 \ No newline at end of file diff --git a/src/boundary.cpp b/src/boundary.cpp index a1b9814..f7dd7f8 100644 --- a/src/boundary.cpp +++ b/src/boundary.cpp @@ -79,6 +79,8 @@ RR ball_vol_RR(int k, RR r) { exp.SetPrecision(RR_PRECISION); pipow.SetPrecision(RR_PRECISION); + //cout << "Ball vol: k= " << k << ", r= " << r << endl; + exp= k; pow(pwr, r, exp); @@ -179,7 +181,7 @@ RR integral_odd_RR(int h, int l, RR tvec[], RR vvec[]) { tmp= (2*h+1)/2.0; - /******** Debug *************** + //******** Debug *************** if(1-tvec[l-h]<0) { cout << "tvec[" << (l-h) << "]== " << tvec[l-h] << endl; @@ -310,7 +312,7 @@ RR ci_prob_RR(RR Rvec[], int k) { bounds[i]= Rvec[2*i]*Rvec[2*i]/(Rvec[k-1]*Rvec[k-1]); //bounds[i]= Rvec[2*i]*Rvec[2*i]/(Rvec[k-1]*Rvec[k-1]); - /******** Debug *************** + //******** Debug *************** if(bounds[i]>1) { cout << "k: " << k << "\ti: " << i << "\tl: " << l << endl; @@ -529,9 +531,8 @@ void predict_nodes_RR(RR Rvec[], double b_star_norm[], int n) { cout << "# Measured nodes: " << sum << endl; } - static -void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int n, ZZ* act, double delta, unsigned long iterations, RR& t_enum, int& changes) { +void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int n, ZZ* act, ZZ delta, unsigned long iterations, RR& t_enum, int& changes, RR* values_init, double* ratios_init, unsigned int oldits) { ZZ* mod= new ZZ[n]; RR* mod_f= new RR[n]; time_t currentTime; @@ -559,13 +560,6 @@ void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int cerr << "Estimated end of computation: " << asctime(localTime); } - if(i%10==0) { - values[stat_ctr]= t_enum; - ratios[stat_ctr]= ((float) (changes-oldchanges))/10; - stat_ctr++; - oldchanges= changes; - } - do { if(n%2==0) change= 2*(rand()%(n/2-1)); @@ -586,9 +580,13 @@ void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int /*if((change==0) && (mod[change]+sign*delta<=0)) flag= true;*/ - } while((mod[change]+sign < 1) || (mod[change]+sign > mod[n-1])); + } while( ((sign<0) && (mod[change] == 1)) || ((sign>0) && (mod[change] == mod[n-1])) ); - mod[change]= mod[change+1]+= sign; + mod[change]= mod[change+1]+= sign*delta; + if(mod[change]<1) + mod[change]= mod[change+1]= 1; + if(mod[change]>mod[n-1]) + mod[change]= mod[change+1]= mod[n-1]; // Ensuring monotonity //if((change < n-2) && mod[change] > mod[change+2]) @@ -603,7 +601,7 @@ void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int if(mod[j] < mod[change]) mod[j]= mod[change]; - if(t_enum == -1) { + if(i == 0) { for(int j= 0; j < n; j++) { conv(mod_f[j], act[j]); mod_f[j]= sqrt(mod_f[j]); @@ -632,27 +630,97 @@ void generate_boundary_step(RR b_star_norm[], double t_node, double t_reduc, int } else for(int j= 0; j < n; j++) mod[j]= act[j]; - + + if(i%10==0) { + values[stat_ctr]= t_enum; + ratios[stat_ctr]= ((float) (changes-oldchanges))/10; + stat_ctr++; + oldchanges= changes; + } + + } time( ¤tTime ); localTime = localtime( ¤tTime ); cerr << "Computation finished: " << asctime(localTime) << endl; - // Output statistics - + // Output dump data + ofstream stat_out; stat_out.open ("optistat.dat"); + // timing and delta + stat_out << "# " << t_node << " " << t_reduc << " " << delta << endl; + + // dimension + stat_out << "# " << n << endl; + + // GS vectors + stat_out << "# "; + for(int j= 0; j < n; j++) { + b_star_norm[j].SetOutputPrecision(RR_PRECISION); + stat_out << b_star_norm[j] << " "; + } + stat_out << endl; + + // last boundary + stat_out << "# "; + for(int j= 0; j < n; j++) + stat_out << act[j] << " "; + stat_out << endl; + + // statistics + int s1= 0; + unsigned int s2= 1; + /*unsigned int s2= 0; + if(oldits==0) + s2= 1;*/ + + stat_out << "# " << oldits + iterations/10-1 << endl << "# "; + for(unsigned int i= s1; i0) + scale= values_init[0]; + else if (iterations/10>0) + scale= values[0]; + else + scale= 1; + + stat_out << "\"Change ratios\"" << endl; - for(unsigned int i= 1; i> tmp; + infile >> t_node; + infile >> t_reduc; + infile >> delta; + + infile >> tmp; + infile >> n; + + b_star_norm= new RR[n]; + infile >> tmp; + for(int i= 0; i> b_star_norm[i]; + } + + act= new ZZ[n]; + infile >> tmp; + for(int i= 0; i> act[i]; + + infile >> tmp; + infile >> oldits; + + values_init= new RR[oldits]; + infile >> tmp; + for(unsigned int i= 0; i> values_init[i]; + } + + ratios_init= new double[oldits]; + infile >> tmp; + /*string line; + while ( getline (infile,line) ) { + cout << line << '\n'; + } + infile.close(); + exit(0);*/ + for(unsigned int i= 0; i> ratios_init[i]; + + + /* Debug/ellenőrzés + cout << n << " " << t_node << " " << t_reduc << endl; + for(int j= 0; j < n; j++) { + b_star_norm[j].SetOutputPrecision(RR_PRECISION); + cout << b_star_norm[j] << " "; + } + cout << endl; + cout << oldits << endl; + for(unsigned int i= 0; irvec[k+1]?rvec[k]:rvec[k+1]; for(int i= rvec[k+1]; i>k; i--) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2463388..f096d3a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ SET(TARGET_NAME1 unit_tests) SET(TARGET_NAME2 act_test) SET(TARGET_NAME3 performance_test) -#SET(TARGET_NAME4 detprofile) +SET(TARGET_NAME4 psucc_exp) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/include) LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) @@ -14,5 +14,5 @@ TARGET_LINK_LIBRARIES(${TARGET_NAME2} cleanbkz ntl) ADD_EXECUTABLE(${TARGET_NAME3} performance_test.cpp) TARGET_LINK_LIBRARIES(${TARGET_NAME3} cleanbkz ntl) -#ADD_EXECUTABLE(${TARGET_NAME4} detprofile.cpp) -#TARGET_LINK_LIBRARIES(${TARGET_NAME4} cleanbkz ntl) +ADD_EXECUTABLE(${TARGET_NAME4} psucc_exp.cpp) +TARGET_LINK_LIBRARIES(${TARGET_NAME4} cleanbkz ntl) diff --git a/test/act_test.cpp b/test/act_test.cpp index ba4d504..9a8343f 100644 --- a/test/act_test.cpp +++ b/test/act_test.cpp @@ -87,7 +87,7 @@ int main(int argc, char** argv) { gh*= c[i]; gsghs[i]= pow(gh/ball_vol(i+1, 1),1.0/(i+1)); } - gh= pow(gh/ball_vol(dim, 1),1.0/dim); + gh= 1.05* pow(gh/ball_vol(dim, 1),1.0/dim); if(l_cjloss) cout << "# Shortest vector length: " << sqrt(dim) << endl; cout << "# Gaussian heuristic: " << gh << endl; diff --git a/test/psucc_exp.cpp b/test/psucc_exp.cpp new file mode 100644 index 0000000..12b074e --- /dev/null +++ b/test/psucc_exp.cpp @@ -0,0 +1,262 @@ +/* + Copyright (C) 2014 Janos Follath. + + This file is part of cleanbkz. + + cleanbkz is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cleanbkz is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cleanbkz. If not, see . + +*/ + +#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +extern RR p_succ(RR Rvec[], int n); +extern void init_factorials(int); +extern RR RR_PI; +extern void enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& result, unsigned long &termination, double &time); + +extern void predict_nodes_RR(RR Rvec[], double b_star_norm[], int n); + +extern void predict_nodes(double Rvec[], double b_star_norm[], int n); +extern double ball_vol(int k, double r); +extern void profile_enumerate_epr(double** mu, double *b, double* Rvec, int n, vec_RR& result); + +void gen_randlat(mat_ZZ& basis, ZZ determinant, int dim); + +// The maximum of the coefficients of the random unimodular matrix +#define UNIMOD_SIZE 100 +mat_ZZ unimod(int dim){ + mat_ZZ L, U; + L.SetDims(dim, dim); + U.SetDims(dim, dim); + + for(int i= 0; i < dim; i++) + L[i][i]= U[i][i]= 1; + + for(int i= 0; i < dim; i++) + for(int j= i+1; j < dim; j++) { + U[i][j]= RandomBnd(UNIMOD_SIZE); + L[j][i]= RandomBnd(UNIMOD_SIZE); + } + + return L*U; +} + + +int main(int argc, char** argv) { + int dim, bsize= 2; + stringstream ss; + mat_ZZ basis; + int lattices, bases; + int* seeds; + int* lsucc; + int* psucc; + + // dimension + ss << argv[1]; + ss >> dim; + ss.clear(); + + // number of random lattices + ss << argv[2]; + ss >> lattices; + ss.clear(); + seeds= new int[lattices]; + lsucc= new int[lattices]; + psucc= new int[lattices]; + + // number of bases per lattice + ss << argv[3]; + ss >> bases; + ss.clear(); + + // reduction blocksize + if(argc>4) { + ss << argv[4]; + ss >> bsize; + ss.clear(); + } + + double* polybound= new double[dim]; + double* linbound= new double[dim]; + + // Schneider's polynomial approximation boundary function + double div = (double) dim; + double y,scale; + scale= dim; + for (double x = 1; x<=dim; x+=1){ + y = x/div; + polybound[int(x)] = min( -276.919520419850*pow(y,8) \ + +1208.33321732860 *pow(y,7) \ + -2128.79627565000 *pow(y,6) \ + +1952.22801180000 *pow(y,5) \ + -1012.11476080000 *pow(y,4) \ + + 305.211610000000*pow(y,3) \ + - 51.347076000000*pow(y,2) \ + + 4.408932000000*pow(y,1) \ + + 0.000914465000, 1.0); + polybound[int(x)]*= scale; + } + + for(int i= 0; i< dim; i+=2) + polybound[i]= polybound[i+1]= floor(polybound[i+1]); + + for(int i= 1; i< dim-1; i+=2) + if(polybound[i]>polybound[i+1]) + for(int j= i; j >= 0; j--) + if(polybound[j] > polybound[i+1]) + polybound[j]= polybound[i+1]; + + // linear boudary function + ZZ* act= new ZZ[dim]; + ZZ R2; + conv(R2, dim); + act[0]= act[1]= (2*R2)/dim; + for(int i= 2; i < dim; i+=2) { + act[i]= act[i+1]= act[i-1]+act[0]; + } + act[dim-1]= R2; + if(dim%2==0) + act[dim-2]= R2; + + for(int i= 0; i < dim; i++) + conv(linbound[i],act[i]); + + + // Computing success probabilities + RR_PI.SetPrecision(RR_PRECISION); + RR_PI= ComputePi_RR(); + init_factorials(2*dim+2); + RR* mod_f= new RR[dim]; + cout << "Linear boundary: " << endl; + for(int j= 0; j < dim; j++) { + cout << linbound[j] << " "; + conv(mod_f[j], linbound[j]); + mod_f[j]= sqrt(mod_f[j]); + } + cout << endl << "Linear success rate: " << p_succ(mod_f, dim) << endl; + + cout << "Polynomial boundary: " << endl; + for(int j= 0; j < dim; j++) { + cout << polybound[j] << " "; + conv(mod_f[j], polybound[j]); + mod_f[j]= sqrt(mod_f[j]); + } + cout << endl << "Polynomial success rate: " << p_succ(mod_f, dim) << endl; + + + // Performing randomization followed by enumeration + unsigned long termination= 0; + mat_RR mu1; + vec_RR c1; + vec_RR solution; + double* c= new double[dim]; + double** mu= new double*[dim]; + double t_enum; + + for(int i= 0; i>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +************************************************************************** +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +yanesca@peace:~/workspace/cleanbkz$ ./bin/boundtool -f data/svpchallengedim100seed0red20.lat -n 8e-08 -r 36.39 -c 300 -d 100000 +Starting time: Mon Nov 24 13:35:22 2014 +Estimated end of computation: Mon Nov 24 13:52:01 2014 + +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- +--------------------------------------------------------------------------- + +d80k20 -> 20 min +d100k20 -> 2 years (lehet, hogy nem volt rendesen optimalizálva sem) +d100k30 -> 24 days diff --git a/tmp b/tmp new file mode 100644 index 0000000..cfbc621 --- /dev/null +++ b/tmp @@ -0,0 +1,102 @@ +[[51 -384 278 -300 117 -151 717 5 202 -417 -161 139 -145 292 -42 115 520 296 -450 -27 -198 -147 301 193 -335 -267 127 248 -76 -636 -324 586 233 -745 -84 -227 -77 178 494 221 376 795 -256 -447 771 480 106 102 -500 915 28 400 -69 -439 447 409 -332 -2 -543 664 664 -337 513 52 -93 349 -313 43 301 166 -675 -26 10 -772 105 -216 -191 124 298 -76 -340 99 491 -395 226 16 573 -126 -376 293 32 17 -968 360 -663 -89 105 383 622 135] +[743 299 -366 148 222 -270 426 -408 -218 114 859 -58 -263 -313 -342 115 -237 -101 -423 -208 298 -180 105 -280 -662 497 22 381 132 382 -443 128 -316 409 650 248 403 396 61 160 -170 -758 295 150 -179 -221 36 215 -850 -899 -154 133 -238 373 127 -382 -369 203 280 -110 -290 220 76 384 371 -367 23 -633 320 -74 214 -136 438 142 -104 211 351 1007 197 692 -373 -211 50 284 -146 9 -518 -187 -123 -172 62 -473 921 -585 -275 -400 -44 838 -381 -74] +[-226 -885 -569 28 -300 56 -498 333 511 309 -266 -185 -57 629 69 87 -697 488 -586 351 412 -11 -359 350 -44 -41 -94 -448 2 679 -18 -594 -4 -744 113 -117 -444 -3 182 -134 636 367 -472 223 -275 -300 -229 118 346 327 414 111 -125 -295 -607 677 243 705 -101 427 129 142 141 225 -46 898 -6 -2 273 -383 -134 252 -451 304 -261 252 205 -965 -347 -271 130 -303 169 -665 45 -349 651 392 670 -284 361 -373 -278 655 636 507 162 -130 -19 -163] +[-264 282 225 -395 117 -158 619 302 721 -405 -1292 172 587 -71 -569 146 376 -469 92 -783 -341 141 57 -405 173 -498 399 362 -13 -1204 448 662 273 -234 -395 -637 -390 191 -386 281 169 439 504 338 344 -433 83 -576 386 519 -271 -698 -319 385 551 623 -85 -82 -781 -82 -179 -219 -309 -768 62 -18 532 99 -484 399 -56 407 294 312 311 -201 -117 117 265 -368 -333 471 521 79 138 -86 -184 -46 -352 885 -609 498 -225 139 -448 -221 -539 -199 695 252] +[99 -135 244 -250 -23 -9 -242 4 -467 -467 -452 322 -420 324 689 -550 194 407 -188 1046 210 -662 293 212 -373 152 -94 -111 -86 346 -309 394 -503 -615 -311 333 -429 534 4 42 -151 213 -600 -451 64 41 34 -250 -460 264 -46 150 487 -436 447 45 -439 497 -62 -127 196 -75 34 527 -223 109 -687 297 268 857 141 328 -337 -648 1 -73 -566 -293 167 -54 645 651 322 -615 79 -165 188 -65 110 -511 924 132 -575 118 554 -326 214 606 -677 163] +[-256 126 -25 251 -567 106 -325 -71 -165 838 -153 -365 430 358 -162 451 -585 625 -100 298 -87 336 -1125 170 726 103 -523 -182 221 505 107 -899 -281 145 -541 510 -342 -328 524 -266 539 107 -118 -120 -394 120 -29 120 -7 338 348 112 366 -194 -632 76 1087 -474 276 -422 45 492 -795 -243 -509 609 -102 -151 363 -381 218 -474 -349 -132 -632 452 -245 -114 -407 -963 217 -691 20 -177 242 8 638 69 455 -199 -30 -55 -772 311 199 666 864 -655 -516 -642] +[150 -418 -89 434 213 655 -178 -109 228 -385 598 53 -130 -714 -146 15 330 -200 -663 -50 -300 242 -83 -177 62 -567 25 81 -507 530 220 -335 922 345 576 -445 24 -605 106 -168 -203 -331 -323 155 -398 243 141 110 921 -362 360 109 -266 459 -219 358 -125 204 -401 339 289 -508 121 -268 -220 -243 -285 264 51 -869 -250 -141 -2 477 749 -3 224 -649 221 288 92 221 -645 992 307 -189 -219 -6 -463 535 167 260 234 -69 -413 331 190 -83 -128 -677] +[-455 363 83 753 -262 460 147 -710 -285 -452 420 484 -28 -111 -505 -603 251 29 187 13 -53 -171 129 -635 -237 -77 -96 -542 -89 591 -365 -305 189 721 -373 283 45 -280 -293 -561 -771 -243 -707 -181 -291 701 -409 -150 452 -557 -196 -75 776 343 -51 -352 -332 426 395 -104 97 -458 220 -315 18 -796 -536 -123 -326 -204 -31 -263 -355 -88 549 -689 357 -237 111 92 591 721 -321 382 -193 216 -652 88 64 -624 258 394 -647 -310 57 0 64 -480 423 -423] +[-84 -373 -687 -387 459 -264 501 130 564 -513 -504 496 -155 48 119 0 -485 -341 -107 -113 390 -495 816 -1112 -465 -144 20 -30 428 819 -440 -566 -47 174 111 -365 35 145 -354 -249 -582 -839 -272 622 -493 -756 -71 4 153 -1079 -286 -590 20 12 -104 468 -243 940 153 115 -273 213 -494 -369 1038 12 -604 140 -679 -205 602 631 -44 382 206 -204 409 53 162 999 -33 433 -67 4 64 -488 -713 -118 -103 -84 105 275 -149 -173 -25 -519 -480 318 -211 -176] +[300 260 458 734 -301 59 780 -576 -121 -293 568 9 -565 -503 138 153 132 -594 -182 -213 -370 -196 315 -968 -107 -308 -126 612 -406 516 70 -711 -29 330 390 -69 576 -524 148 -353 -383 -176 -468 -538 211 633 151 777 546 -147 81 992 12 -480 -152 -5 22 159 -75 222 530 16 456 -299 905 -489 -545 129 371 -1172 -445 -226 34 -301 562 -79 -252 705 139 526 -400 480 -202 -162 207 -82 -278 -277 -678 -682 -119 538 -639 -422 -535 -252 29 120 985 -261] +[-88 495 492 -497 -563 -6 248 -190 -369 -137 274 -211 -878 -30 109 -275 933 -95 31 302 24 -710 598 -483 -26 262 -319 -823 82 255 165 81 -711 -748 8 347 -662 330 -482 -107 400 725 -570 -526 142 939 -799 49 -55 404 219 282 278 -511 -290 -206 -426 -44 158 143 -114 -434 141 81 658 296 -970 -52 210 111 -262 389 -499 -590 228 -383 -138 198 61 -90 259 231 344 -820 75 250 -71 95 10 -1048 138 689 -1310 -360 334 -351 328 -117 517 -125] +[506 1015 478 888 -184 -246 -418 357 -852 516 -318 -253 409 265 304 -8 -234 -492 880 289 44 129 -1034 -449 -101 -189 -242 331 -421 102 -534 -81 -605 620 -638 418 101 353 -468 166 -220 196 354 -269 94 -756 415 254 -857 113 -582 80 289 160 162 -773 43 -227 804 -487 -256 249 -100 338 -66 -174 600 -210 -274 842 590 -352 73 -22 -47 139 -85 1154 -135 -323 658 402 -28 -111 -172 107 -503 -335 -305 -173 558 -680 804 -413 1011 -52 -403 374 -794 391] +[60 583 552 519 -97 267 -583 -241 -146 161 454 -743 73 -685 -488 68 756 -200 -377 221 -145 -140 -981 21 -767 20 174 -69 -188 1489 -313 -477 -245 450 214 -93 -340 -402 -636 -4 147 243 -7 80 -172 188 -366 239 -475 -331 354 366 241 245 14 -330 -249 302 -168 -246 426 -908 451 704 -238 -632 26 -400 365 -473 -378 -330 -556 676 269 48 270 569 -165 -23 331 135 -326 633 -81 13 -225 -286 -544 -287 399 79 -112 -563 562 73 56 320 -408 -514] +[664 265 96 -375 -402 -50 -226 359 -653 219 521 -94 -285 145 872 -177 94 311 -242 685 667 -162 -448 -290 112 243 -866 -221 -249 577 -178 143 -362 404 217 263 -45 306 433 651 646 122 36 -420 -409 268 599 513 -30 147 578 778 -183 30 -703 -392 -15 -798 84 271 -175 -145 -331 299 625 977 -360 -407 369 132 231 -248 -162 -161 -103 530 -111 281 -289 -113 777 -35 173 -64 423 -195 -303 -792 370 -412 840 -275 566 135 551 -240 610 800 -156 -463] +[126 235 -108 -314 -412 686 92 -742 -386 -69 -167 289 -375 -331 -58 23 -377 -186 -285 72 -481 -315 204 -395 487 14 -128 235 -440 -633 565 -409 -633 495 116 582 -82 463 427 -445 -685 -569 -521 -558 -297 682 -220 577 257 15 -330 146 -2 -628 322 -84 325 228 -262 198 281 603 -157 -696 286 -202 -1020 315 -289 -431 383 64 73 -281 458 -619 -603 318 198 291 -303 -66 -211 -162 139 -103 262 -275 393 -372 -266 1306 -658 -422 -592 -87 750 -260 -206 -317] +[-328 315 229 464 326 -159 577 484 -468 744 334 -514 429 83 -885 346 123 25 293 -752 -238 -206 -378 -1320 -184 -81 104 -294 498 213 -445 -886 46 127 97 85 -20 158 88 -182 104 -538 134 340 -316 -707 -668 -326 -579 -290 96 -53 106 281 -815 -234 141 551 690 -241 -744 226 -540 -5 -127 -98 187 -268 203 -20 154 247 1 -249 278 136 941 1035 -355 -284 4 -592 -396 329 -340 64 -639 417 -133 -46 67 -162 -709 -1010 266 327 -350 -520 -598 40] +[113 480 689 -944 729 -171 327 284 -183 558 343 -608 98 -166 152 -109 909 408 146 -33 -616 118 37 -62 -212 600 -227 -4 857 -238 -334 40 240 508 571 246 298 -459 691 70 621 -330 484 446 22 282 -138 496 -1470 -299 -25 603 -31 118 -274 -392 28 -698 -188 294 -73 11 -249 401 -339 -28 379 -92 613 230 -215 -300 -80 -42 -455 685 336 1062 -367 -113 -75 -364 -477 128 175 96 6 -238 -9 400 -208 293 163 -238 -12 -491 108 854 -1145 184] +[-428 -22 46 751 -363 -93 -40 -611 1053 10 -454 -72 12 224 -822 67 -313 -504 309 -1000 -80 35 132 521 -349 -127 435 77 43 -268 -21 -23 -22 -131 -556 -42 171 -115 -450 -108 -628 1012 -457 -409 194 -448 398 -358 340 406 -211 -98 68 -832 95 355 -56 -142 86 -694 409 -459 955 -269 348 -314 636 -297 87 -545 -180 -174 93 172 -334 -36 -270 -122 -161 -521 -762 -357 358 -665 -448 200 204 659 -434 -935 -443 -537 -559 224 -483 366 -622 -811 1447 439] +[-345 -189 -111 24 453 -110 770 639 368 -705 -146 -482 -310 54 -864 470 368 39 -216 -37 -182 -12 215 195 -566 287 432 356 -234 70 162 434 -375 -858 533 -714 -394 205 -605 254 503 78 389 333 881 212 -760 -357 -809 45 6 -649 95 542 763 547 -395 81 -448 -172 26 -632 77 39 -396 -397 -305 -107 -269 862 -405 289 7 356 563 -317 -36 860 326 562 -423 307 466 302 25 50 219 -528 -368 153 -690 -74 -275 -394 -547 -73 -143 426 -146 541] +[422 517 -26 -642 264 918 -644 -13 -721 -337 1006 -237 -697 -830 202 38 595 -111 658 154 426 94 -46 437 110 368 -409 -214 24 254 573 425 -359 933 536 58 -384 278 -332 332 -597 250 74 -743 -702 350 426 -42 98 -473 46 -393 76 388 -193 -608 -425 -1046 367 -460 -671 -849 -626 283 -265 -156 106 235 -368 310 477 -741 -460 519 243 13 -99 1040 -77 454 321 -202 -446 1271 -328 48 -161 -820 -100 117 520 -77 735 -297 -319 -524 438 242 -1020 -557] +[-321 -594 -14 -591 -28 -101 -11 832 257 -74 262 200 -441 544 1230 669 474 286 869 262 44 248 97 519 -166 -664 -220 145 -41 256 -383 -437 353 -341 -472 -431 9 -830 -243 -169 376 881 -8 -645 975 2 122 521 -606 351 -177 33 -24 -731 -224 -20 132 161 375 308 629 -814 -81 268 51 664 273 587 -323 -501 -954 -588 -704 -185 -573 786 -68 -183 -507 117 15 45 -276 -32 -62 1 729 -595 -422 491 -367 -666 -555 1153 99 -240 -33 19 500 287] +[118 205 66 104 -142 745 -699 -200 -553 -578 -75 602 -605 -19 354 -436 78 -348 99 473 -203 -199 -154 105 174 -11 -176 -416 -619 -195 636 480 -101 712 -2 92 -146 251 -400 -14 -1271 -748 -660 -783 -466 -492 213 -928 460 -47 145 -516 -47 -544 474 -661 -566 260 382 -842 -41 4 165 -263 -376 -1275 -11 680 -535 54 800 -107 134 468 1028 -68 -577 -546 -238 2 631 291 -714 746 -202 108 -82 196 1025 -538 280 293 537 164 156 8 382 19 -41 189] +[458 18 185 106 -633 -678 619 -117 -185 571 -168 -685 226 -98 -60 859 202 -84 -983 286 329 379 -255 157 106 531 -308 638 251 635 565 -48 -383 107 723 -480 448 -501 209 14 920 -868 884 346 356 159 114 -278 -232 -731 1343 438 -196 64 -387 182 300 -138 -480 -466 80 128 -492 32 481 -366 -482 -379 1210 -866 -478 -440 414 -47 -158 775 -361 112 -187 -252 -221 -634 255 418 605 23 46 -197 385 185 -457 -90 172 552 -606 125 445 675 679 -483] +[-828 -142 258 168 -522 389 -79 -423 158 -106 84 -24 -16 -40 -85 -10 155 217 969 -940 83 -31 541 1006 224 -113 434 -30 210 -1196 182 206 -225 337 -813 363 -41 -70 -585 -376 -331 283 143 -702 314 768 149 -453 -49 340 -290 -88 234 -302 185 12 316 -428 540 -321 -317 -798 -142 -108 36 269 403 -48 -62 -103 -548 -43 412 -422 -231 -344 -533 -403 -732 -204 -527 -435 -506 341 -470 -29 -202 13 392 -239 -732 5 -802 395 -900 343 -54 -957 527 762] +[16 -617 -249 -421 619 8 434 -98 815 -148 -275 39 445 115 -193 -135 -829 489 -571 -883 -340 92 34 -77 -786 -249 699 395 102 -421 -749 41 509 151 256 -222 397 241 646 357 -163 -836 -340 527 -627 -815 463 52 -359 503 184 63 -825 119 139 350 113 499 -391 644 103 1056 129 156 156 229 450 34 -413 272 595 563 1186 195 87 -314 386 -257 -217 329 -484 -1005 -815 304 340 -488 621 611 505 167 -55 33 124 -317 -1000 500 -3 400 397 -96] +[-111 162 -462 350 333 -612 680 -174 -166 -254 794 -668 -534 -147 -342 292 -607 -160 397 -725 60 118 900 -352 -910 610 904 74 429 254 151 399 -74 -321 585 -230 -151 -65 -937 153 -617 -425 -11 59 47 -290 -452 -482 642 -340 -41 -435 -364 249 -237 -401 -210 -30 71 -937 -985 273 176 725 47 -494 880 120 -299 95 71 120 491 439 342 -122 137 959 127 364 -817 -296 -67 -113 -779 -42 180 646 90 -1118 69 -822 444 -768 -341 -329 -421 -30 657 546] +[-143 674 -208 155 161 -539 -660 -42 132 -97 -125 -217 -224 -261 -100 -464 875 -734 417 -192 -120 -180 638 483 358 -114 -131 -390 323 -617 103 282 -162 -464 -494 399 -464 311 -571 -405 -381 696 552 -7 -22 -514 343 -526 255 -395 -401 -738 224 286 711 171 -220 -74 374 -245 -499 -121 -67 171 -139 -421 220 -31 -144 -140 85 -93 -113 -134 -629 92 -239 -404 65 351 -133 243 323 -252 -363 179 -486 166 -1265 435 307 -263 484 -57 432 200 -371 -307 -530 -132] +[700 492 -192 703 -185 -116 4 -565 -744 537 653 104 299 -279 -619 528 -180 -541 59 131 119 504 -74 -156 813 174 -182 168 349 -340 -526 299 386 506 -220 272 305 -272 100 -244 -335 257 295 -599 235 390 299 48 -563 -255 99 -721 262 -277 -165 -386 340 -1448 785 -416 55 28 -476 -106 -569 -572 -913 -156 250 455 457 -806 326 -701 154 -651 271 173 962 45 -245 82 310 333 293 797 -197 360 -735 170 281 -355 208 13 -647 -102 240 -332 -1020 60] +[-1021 -385 -306 -477 -445 820 241 104 535 -206 127 400 391 108 -758 -826 63 1172 -515 -337 -545 -586 269 -285 514 -239 -160 -246 -41 -880 -288 -328 735 -33 -251 263 218 333 861 -183 -170 312 -637 -478 -812 98 408 -244 276 348 63 139 266 -289 42 646 260 459 -492 111 593 -42 17 -709 -441 328 -1424 -12 180 -207 -125 498 -626 -250 -6 58 -4 -1119 -409 -539 -50 611 372 -194 373 -185 -226 -292 304 -345 -25 1287 -597 -405 -363 592 729 -474 -574 -196] +[612 146 548 -305 113 -79 130 -96 -260 161 -723 973 50 -350 600 -328 -41 -362 -50 59 623 227 478 62 -334 133 67 699 -333 -364 117 1305 94 533 -367 -371 503 195 233 226 -198 -613 213 676 -404 37 660 -167 -169 -673 -301 -11 -398 795 118 15 -176 -749 -517 -347 -54 242 -277 226 665 -265 -16 -407 79 1024 386 -277 1002 39 31 -18 -405 -358 799 32 267 -221 243 489 582 36 -320 308 15 56 317 -21 428 211 -326 -523 -194 537 -67 -187] +[45 -837 -1035 291 -375 510 -332 -361 905 -107 -839 333 -164 271 167 -725 -978 -77 -114 -80 134 129 184 184 -926 133 532 502 -1054 -40 -194 -811 -455 1249 664 46 -14 120 188 -88 -415 -863 -80 92 -317 1 294 233 359 -1010 -46 -20 -341 366 -330 474 -99 883 -146 174 -237 -653 142 -731 943 257 121 240 -135 166 161 148 232 710 346 -91 -95 -503 -8 225 236 438 -958 87 -253 -239 -433 -67 469 -938 28 -62 532 493 -610 212 -158 113 28 435] +[560 415 195 -50 55 251 -354 -575 -162 647 1291 -198 -586 -731 -34 344 -146 -216 92 -208 -392 139 -568 524 64 -36 225 -467 432 382 -479 629 186 -42 -136 -2 151 -221 -365 -357 394 207 147 163 -607 532 82 -91 -651 -101 -618 159 18 162 458 -678 -290 -355 1275 24 -516 341 103 284 -174 -179 971 127 108 -261 659 -346 -147 761 -715 226 71 532 192 -102 -966 -244 -60 209 -344 438 100 756 207 289 -730 -234 704 -72 -194 317 493 -167 -1136 69] +[345 -451 420 380 52 242 -865 80 258 523 465 -292 597 -745 -301 228 753 -152 140 -364 56 185 -1021 11 1175 -696 -304 56 -152 -78 766 -157 729 4 29 -231 481 -215 65 659 196 879 -194 264 -757 -247 161 -139 684 642 262 234 -633 -19 -299 -1 51 -203 394 499 139 -104 217 193 -375 248 794 49 90 -837 -281 51 -451 694 703 236 168 -589 -511 -539 208 -499 -141 509 338 -7 -156 467 -366 585 274 32 462 -541 428 409 -319 -175 -494 -471] +[-436 -666 145 -503 278 352 369 333 -75 -42 463 384 -777 499 -24 228 15 766 -8 -505 -344 -24 314 118 -1112 248 516 -331 103 367 -10 67 497 -141 -12 -875 -28 -663 1001 217 -2 -130 -443 -758 -18 -17 166 -601 -130 61 782 144 32 -413 -849 -31 -166 353 -336 -454 249 -232 360 312 -411 -71 88 530 390 -101 -450 -348 -467 11 -166 827 342 -168 524 -392 -390 -599 -117 756 -114 466 872 723 166 -177 -191 -651 -1157 537 -345 54 26 -536 965 328] +[758 82 117 -510 -250 -188 123 -354 54 344 -137 562 -446 -63 556 -159 258 -752 -560 50 -7 238 256 28 -444 -433 -292 395 -240 -440 183 238 256 -166 478 -320 -164 169 213 10 -396 736 -366 -417 406 -38 262 575 196 266 -152 832 -977 -616 -275 -159 -379 -447 -178 111 460 367 952 54 675 148 -350 502 -43 -747 -259 -350 281 -81 465 -508 -62 711 84 185 -378 4 -424 -235 -3 211 480 -47 -149 -749 248 41 -608 174 -701 -166 290 283 -103 -376] +[-197 -491 -356 -143 696 -975 -164 -19 115 58 891 -287 -439 -502 937 271 -257 299 532 197 511 -26 819 608 -161 1017 -13 -160 407 1109 105 320 -331 -681 422 40 322 -393 -115 367 80 -604 264 799 -194 421 -680 539 79 -442 -87 237 -195 -21 -244 -447 66 -383 499 -198 -50 126 164 950 254 -194 680 -732 -175 -719 -337 99 328 391 -760 473 -69 -249 -332 587 -199 -1048 49 -424 70 -724 329 425 -170 -364 -388 -288 320 -453 423 -313 -67 432 326 174] +[49 -413 357 301 1261 -495 179 241 76 -186 -351 -429 189 -736 -398 863 381 -750 -804 -626 -672 224 152 -40 -9 -829 -54 21 302 455 -672 813 742 -340 -163 -819 -173 -314 -282 16 393 -106 333 455 31 -390 -55 -191 -53 159 -211 -5 -660 218 241 492 -296 -1298 -12 -132 276 -634 -38 133 -284 -337 216 -292 -172 -545 139 -184 528 106 333 233 -413 361 -69 -265 -590 -982 168 736 166 -457 -287 60 -1048 1139 -1 -181 -813 -344 -801 537 180 300 -670 -302] +[-240 241 -485 -230 217 -191 -264 788 75 434 563 -58 662 -142 450 -110 -489 -12 203 700 -170 403 -762 148 -635 -83 604 419 -304 331 -462 -241 253 -19 1134 -601 187 233 -602 719 212 -7 451 417 509 -861 25 142 -553 -145 2 -125 -651 144 -456 -666 -69 672 -213 -466 467 -93 238 293 -142 -184 382 121 -608 217 -19 551 104 600 174 2 664 646 -105 -341 -20 543 -557 244 8 -90 -6 -229 -44 -173 -733 -295 1148 -662 423 253 -405 133 -680 813] +[11 216 40 -478 237 74 1200 261 -110 -128 304 643 348 -95 270 -136 241 -212 523 -1356 -520 -73 393 -963 277 -923 -187 631 -143 -749 9 288 834 446 -323 121 819 -96 228 -26 -976 -604 -339 32 -475 -286 333 57 132 550 -138 299 -305 -223 133 -50 -236 214 284 370 -317 745 358 -910 574 -221 464 58 -743 -695 -53 -88 593 -255 144 -68 73 147 -824 195 -1 -331 -298 -136 -99 -486 22 76 206 360 -775 796 -250 -534 -809 78 10 -114 1060 -350] +[162 73 -169 -822 235 397 -163 -427 52 67 -586 678 382 649 -195 -136 -361 -316 -587 230 226 228 -182 61 366 138 -145 -531 748 320 -207 558 227 -88 4 588 -464 168 348 -266 -90 262 -782 362 50 666 111 547 155 128 49 -233 559 -560 -426 379 -131 -103 -883 795 241 112 160 -564 -332 441 -172 -41 8 -703 330 -492 -281 -454 -717 -597 292 141 352 -401 -96 -30 891 -767 252 -216 484 -106 -149 608 -348 -349 -544 656 26 92 180 -447 -18 -577] +[829 843 307 -667 63 455 -428 -190 -59 -280 -326 -8 340 -1118 205 -152 152 -577 -366 392 301 10 -789 -175 -63 123 137 293 228 939 461 -107 -104 254 -297 944 -1056 -108 -786 544 11 721 124 -239 10 -182 146 292 658 678 -164 -6 15 217 16 360 134 -955 -685 -975 -77 -237 -307 -213 -47 383 140 -140 610 2 -103 139 -419 -55 -473 65 -258 127 251 -54 459 961 448 -110 -238 -181 -505 -396 -553 -293 747 837 -207 -132 555 -965 95 158 -438 -722] +[825 287 972 158 109 -363 -55 -145 -62 886 -148 -543 454 -84 450 -235 365 -574 632 348 -280 186 -544 535 137 793 -12 -455 -33 133 817 436 39 38 -82 430 160 -531 299 93 -395 507 214 31 74 -303 621 27 -347 218 -141 565 118 -409 -312 -692 268 -1152 308 -818 269 957 948 -42 -2 -642 309 84 1167 -457 -231 -938 229 -8 -713 121 -63 27 474 -740 -53 -121 96 -347 490 606 332 1182 -532 -429 -58 -6 553 -104 475 -78 149 -41 -191 -299] +[-60 292 624 492 370 -363 -104 -430 636 -107 -442 32 494 -330 -207 -64 36 134 -270 -399 -874 -159 -451 -251 893 -690 135 635 -165 -388 -243 -193 536 -14 -542 113 46 -279 412 -323 -247 -227 -125 335 -255 184 -230 592 61 868 29 52 -40 -427 832 645 183 57 -310 216 -219 -193 -436 -709 -1132 -13 513 -402 379 -142 -116 204 541 -123 3 34 -349 -369 -410 -126 -124 146 -697 -292 381 -747 204 -68 -1040 1004 -170 1032 -521 -467 -163 183 168 -323 -471 220] +[559 349 597 -113 -928 200 -279 82 75 874 1 -222 340 422 357 -163 781 -470 290 -266 509 81 -165 102 417 -61 -357 -497 578 108 383 -274 548 236 114 -92 114 -562 -172 330 632 1041 382 -6 -370 -173 701 -18 -100 373 1029 783 -209 -307 -1389 107 483 -1035 465 925 -1 -14 456 234 610 1149 -15 261 759 -238 -183 288 -80 -105 -341 104 820 -203 -62 -539 201 280 -282 -131 539 692 -538 411 -116 -115 -184 -338 137 630 -40 -18 -409 272 -312 -14] +[-32 2 476 -48 328 254 517 -961 -308 -161 175 522 86 212 -483 -406 525 947 -763 779 104 -20 377 487 -581 39 -489 166 542 -315 343 524 197 -465 67 110 -182 -20 529 -689 97 -271 -794 310 265 755 -863 -504 -359 -764 -455 282 256 669 -83 105 -635 558 -412 -361 264 -238 -301 547 -1144 -257 4 -278 1190 750 -303 -530 66 -959 712 -118 -234 -51 238 -380 345 -329 -62 182 -34 9 393 234 471 164 1405 -85 -964 -66 -76 -583 349 327 -834 -728] +[-168 243 -25 -98 -446 -299 27 -156 748 -411 642 152 -594 -387 221 -553 1082 737 505 86 -82 422 612 213 284 349 49 -550 104 -410 297 418 373 -849 -98 143 -221 -396 -278 53 451 1212 -233 -140 202 710 -423 -189 78 389 -368 -340 7 331 352 -6 -350 286 657 145 -232 38 -193 161 -218 -221 -731 581 -225 60 -703 548 -302 258 -264 -496 459 -1453 178 309 344 810 -821 77 314 91 -65 985 -64 -153 -309 579 -380 236 -109 3 43 -12 594 227] +[-215 -414 533 -260 112 778 628 821 -495 -690 912 47 -273 -94 817 325 1111 235 109 337 551 -23 264 89 260 -252 -545 192 -172 385 862 73 293 -1016 380 -498 18 -336 633 127 332 404 -564 -290 287 868 224 -292 -60 444 389 859 465 -32 -575 110 -181 85 194 90 502 -479 589 -76 319 335 -640 532 295 -539 -918 -252 -540 -657 825 -48 -231 -15 169 329 431 -205 185 930 22 -306 199 -35 217 281 319 337 -845 -29 -383 148 296 -286 299 -460] +[381 494 720 -790 299 143 -634 -11 233 389 -732 -1020 33 -796 113 110 303 -1060 -115 -386 -732 -390 426 -794 610 -458 230 -645 -336 -1450 1207 -282 215 288 217 -446 -498 9 -582 -98 -758 163 154 37 -488 -819 331 -22 1123 -467 124 -760 -457 -391 -256 -48 218 -179 -796 -177 -224 327 -257 -788 244 267 -529 655 142 191 911 759 216 500 883 -515 -172 -34 1051 -340 -512 235 -463 361 203 -85 -313 716 -417 634 620 947 1109 -372 395 2 -313 -812 -787 -335] +[-132 -432 -53 35 521 37 -1175 -228 673 -43 887 -61 -248 -980 -290 -813 778 -380 -949 386 -286 246 35 266 309 228 -498 -748 -226 275 -299 213 1003 -12 855 -56 143 -478 387 419 802 1087 -166 -394 348 565 -186 602 938 522 639 817 -143 -83 -588 235 -225 -1011 -103 809 698 -757 353 -43 -188 -59 -275 -344 348 -752 -280 118 -212 285 88 138 241 -1339 -887 15 398 368 -85 -419 428 -295 -144 55 -508 -153 327 133 881 44 342 162 310 130 204 -151] +[45 -795 -929 1342 -531 -347 127 -27 662 -152 -186 251 -138 506 -894 418 -305 128 -491 -337 296 -71 -326 -281 -147 -577 -358 394 -700 -87 -89 -892 -256 -865 215 305 -195 527 -9 -155 72 741 2 -337 939 -480 -1012 784 599 595 -886 38 -609 5 641 527 -670 905 109 360 248 -353 256 -301 115 374 63 -609 -285 -565 -906 309 -278 253 243 -107 523 387 -139 203 -204 573 234 -717 -496 -313 39 -651 -151 -148 -166 -536 -72 136 59 580 -270 21 1084 423] +[-416 -346 62 -709 546 -851 429 -174 676 186 851 689 -143 -549 -416 470 133 315 -103 -320 292 -595 455 -517 -135 107 719 73 249 213 119 -620 402 -280 406 -335 -203 -451 238 -390 -48 -544 698 996 296 509 -1051 178 646 -836 -335 62 -242 -70 370 -147 30 355 -38 -439 -110 -289 -3 -501 507 -115 50 -781 370 -765 -805 612 -345 181 -172 -516 849 195 681 773 -927 -286 104 -14 -717 -230 -302 -52 -485 -229 -431 407 -729 -366 -152 -247 -227 -1117 689 -185] +[210 -447 -501 381 424 139 -576 -266 -179 -874 1871 564 -172 73 39 -9 -742 564 -167 49 622 -132 -31 -317 -418 -216 -157 -288 -337 1423 -1058 -6 64 238 179 -297 126 -254 52 -69 15 -734 -384 -367 -502 329 -134 922 -15 -823 -89 -118 -170 349 -403 -690 -402 754 1197 516 -250 -378 66 467 -412 169 -122 -182 -374 -922 71 -334 -236 179 448 61 954 44 -546 698 390 -655 -834 1294 -175 -496 -685 -519 -197 604 581 -1211 307 -445 6 270 517 120 61 -502] +[471 -708 -993 738 -666 87 951 -19 307 50 357 685 -117 498 -370 731 -910 -57 171 -560 1244 150 -452 -303 -484 276 407 256 -452 456 -386 32 -257 562 -226 -736 260 -319 -363 344 -159 -44 278 -219 -386 799 -123 270 121 -292 464 -635 -323 716 -172 398 39 391 508 787 -385 -237 446 43 208 102 229 -537 -303 84 -448 -946 306 435 568 -651 972 223 693 839 -205 155 -4 393 51 -9 24 -122 510 -274 -139 -938 52 952 -522 -95 -125 466 567 52] +[-240 -379 -70 752 -137 -115 -532 358 -349 219 1065 -29 -535 87 -58 -789 -456 320 347 -879 761 54 -288 -35 -135 -97 -197 -349 -332 324 258 -648 -393 -146 40 229 -22 -36 139 -118 8 322 -683 -333 -43 -56 89 513 595 72 30 99 -339 291 -778 -271 -96 294 520 619 -368 588 731 594 450 60 505 -542 336 -338 -613 110 -91 1 -237 -180 795 -6 -272 436 200 -392 -334 160 -215 166 -460 339 36 -928 113 -1469 -219 75 752 842 -804 -699 1587 -153] +[-407 107 -63 -138 -404 229 52 526 -499 248 -538 -56 78 -3 104 492 -399 -252 191 -114 220 79 -716 -160 1130 469 24 40 -242 -202 864 -466 -463 347 341 -445 -139 491 306 186 311 -510 -5 -636 -104 -115 -433 -416 472 99 945 -701 169 -6 -1093 190 907 253 -39 -620 -918 -293 -1214 -899 -274 -184 570 -274 314 68 141 -279 73 125 -226 781 -291 -227 -320 -603 593 -85 180 51 308 -126 325 4 882 -63 -986 488 3 443 22 -206 201 -807 417 223] +[8 87 -391 -22 468 -13 467 -575 -42 -216 -175 466 -807 19 157 -331 -276 -613 188 332 -45 -272 1454 449 -577 332 51 -307 587 743 -319 105 -231 -80 365 -2 265 700 -626 -1231 -616 -377 -23 103 -514 -107 -70 -436 -349 -949 -356 -304 369 136 264 761 -949 535 676 20 -194 103 130 -109 814 -1006 -26 -398 -207 151 327 -304 352 -171 -144 -308 -36 -506 330 868 -675 -44 103 -633 -180 -10 -189 805 -73 -398 -214 776 -274 -415 -61 -97 -268 586 -168 237] +[181 -622 -526 615 -125 322 600 -100 -302 -479 746 167 104 226 -362 473 -385 -4 -402 -107 654 241 -608 -285 -495 74 -216 -369 -66 1423 -1209 192 555 532 316 -178 -60 -493 276 -170 84 -134 -313 -228 296 661 -95 746 -728 -291 473 835 540 25 -673 384 -13 -138 486 826 437 -1029 581 325 59 -6 -453 -237 180 -972 -487 -1081 -373 -76 -177 -179 420 248 -194 566 295 479 8 494 -128 -147 -35 -745 -268 380 409 -581 -703 424 -513 112 816 516 -458 -403] +[42 -14 334 932 -442 -1107 632 399 -707 383 -184 -648 360 813 753 985 372 -21 99 -200 437 -503 1 -155 -625 -172 -111 1238 535 334 -633 168 -244 418 -579 -324 330 65 695 364 -630 -56 381 -414 459 -503 1191 -41 -1239 457 708 540 181 -1277 -53 -338 -7 -513 193 -648 -237 -503 -191 770 781 13 532 -225 608 -274 -414 -536 646 -433 259 433 -621 1028 -545 -17 -316 -352 302 -259 -129 -413 131 -388 -323 -493 100 -448 -372 337 -351 -506 -201 900 336 1050] +[-722 -907 -615 969 -326 262 -754 344 -264 23 74 -443 -217 429 -131 172 -341 -44 250 -396 -121 -548 -14 33 -388 -691 443 277 -902 338 600 -815 -560 704 552 -15 222 -153 -197 -81 -725 -568 -628 224 -114 -236 56 -240 442 -463 254 179 -126 -361 -162 -13 171 1289 146 470 -288 -366 70 -149 834 229 -177 741 -21 -353 264 741 -167 397 359 -209 -424 33 -606 292 -128 -106 -766 -210 -674 -282 -6 -342 -3 -649 -452 -253 543 -419 -361 669 -322 -435 325 349] +[106 693 450 -1056 -358 274 -484 581 308 129 -489 -846 244 219 186 -13 668 77 446 39 -194 -19 -445 739 -229 494 -105 -360 6 -320 1272 -65 -458 175 343 134 -853 -291 473 -13 477 40 548 180 -21 -668 167 -272 -201 -270 671 54 -48 -40 -631 127 330 -93 -608 -118 -270 -310 -487 76 316 287 904 53 707 559 -11 44 -297 890 -592 1050 -5 150 -55 -1138 693 -385 -329 1 209 94 281 229 430 -110 -375 -8 94 679 412 -290 -106 241 327 -150] +[335 -306 310 -339 380 534 -315 -895 195 16 -411 1164 491 -512 702 198 -85 -162 357 -39 -759 761 462 199 973 -111 153 1014 -94 -777 -300 -354 746 731 -491 1208 376 -409 736 -181 -288 -427 -560 -504 41 324 235 508 224 337 -225 168 -355 -122 -263 381 1402 -1099 52 197 638 182 -615 -582 -514 543 -286 424 -47 -652 -249 -633 544 -773 -247 335 -907 -702 20 -601 136 -505 -452 133 328 237 470 112 -925 140 19 456 -908 -209 -1463 -327 465 -480 -774 -476] +[557 -96 230 -1184 623 138 -306 -127 942 -122 -748 49 -325 -243 398 -187 44 373 -158 565 -24 -343 134 160 -355 726 114 -369 -21 629 -540 175 -239 -337 532 258 -134 234 668 704 776 -188 191 812 -185 187 -68 923 -691 -380 39 -156 339 129 156 -40 140 -932 -138 999 142 -50 -514 131 362 1034 -334 -164 -208 853 878 848 -329 334 -1033 303 633 24 940 20 250 -22 324 -317 760 609 387 -76 -843 295 -412 127 -100 -220 -279 -273 -36 638 -514 -68] +[80 -470 -20 -1362 -57 233 131 79 -662 246 -177 187 -469 18 580 263 492 -151 -829 832 -607 -65 366 -337 485 -224 416 30 -39 381 158 -403 230 243 356 -270 -329 -624 -61 -403 632 -693 -69 -812 256 659 -414 -324 535 140 730 135 -655 -1410 29 -14 -21 247 -627 3 591 -370 -343 -921 -151 -233 -1530 766 505 4 -57 305 -536 -914 608 -215 -423 -813 473 -224 -38 -204 -430 -202 119 476 -257 -233 426 -15 481 1040 -823 74 -301 217 987 -187 392 102] +[-59 -280 242 -605 28 -370 994 -717 534 417 669 -673 142 -414 -390 826 375 102 -738 -439 138 -685 -219 -349 -335 -605 -348 59 1121 1089 -122 239 -152 377 -242 -614 -176 -457 -93 -33 297 572 -212 119 -719 481 324 315 -69 109 500 749 244 -701 -180 644 -242 -43 -159 363 209 -173 -336 -21 798 800 -27 -550 632 -973 -282 -61 -466 -94 233 17 135 533 -389 -108 -919 -595 285 -434 496 -561 -99 56 -51 417 307 409 -1319 -330 -301 24 244 690 603 -888] +[242 789 355 850 -263 163 -262 -648 -585 175 112 294 719 93 -477 -330 -1143 -221 -280 703 -419 -260 -454 -70 504 267 144 -591 313 399 -79 116 -250 -18 -183 403 290 308 -45 -415 9 -310 -194 -345 3 108 -121 -160 272 395 131 279 219 -505 -502 -312 236 183 330 -115 28 1017 206 -92 -549 -108 -808 -442 705 -81 583 736 -155 -483 -40 -544 190 -298 -124 -364 350 538 436 -605 244 -169 -428 224 242 -474 -95 118 -156 -495 750 -292 -120 -600 -527 409] +[84 -282 -734 553 -50 623 -253 -448 -453 671 -62 -342 117 -227 -478 -354 -563 -29 -946 218 -29 469 -354 -342 -270 396 114 390 512 837 470 -431 -59 32 1165 356 126 196 -206 -552 36 -360 -802 262 -123 -255 -548 -47 281 -1086 -78 246 274 -99 -1021 -98 -72 729 -207 -606 -43 371 351 459 -420 -387 -283 540 666 -462 449 75 -659 -235 628 176 -181 -18 -284 169 362 -144 264 -410 -544 254 -589 491 367 -1026 708 -676 414 -762 475 365 -523 112 -935 15] +[-651 -623 -161 50 -386 541 -619 131 163 -464 399 225 -550 91 -172 -110 96 157 518 342 672 74 432 -119 203 -37 -403 -269 326 888 377 -654 -88 -196 716 56 388 21 -1044 -62 -417 514 -895 -485 -58 -323 -487 -343 1251 -150 340 -329 557 -127 -799 253 -728 623 519 -1175 -307 -721 -461 161 24 -108 -1016 275 -106 -305 -206 651 -1250 -188 104 163 230 -612 -581 -72 195 484 -326 2 -660 49 108 -516 546 -615 507 104 -316 -349 520 478 -483 -467 622 -44] +[-100 -432 1243 113 913 77 -102 156 -366 -181 -156 143 421 -299 504 -448 105 345 173 283 -547 -6 15 405 205 -571 -245 -528 189 -170 -360 1146 869 -1056 -492 -558 -509 -543 -75 168 366 602 -279 100 345 323 202 161 257 840 -641 546 377 -36 270 -277 -30 -781 -134 -81 842 -117 668 215 -1398 157 87 605 130 267 -191 -211 -40 -259 149 -320 -164 130 320 -1295 20 182 564 176 145 312 183 551 -386 1202 419 -291 -731 -151 384 232 53 -633 -373 233] +[1083 522 -510 -891 -60 -206 -91 -459 454 384 -92 -215 377 -781 95 -366 153 533 -768 -138 590 -135 -506 -132 -706 607 -258 924 572 1378 44 -258 201 -133 637 10 -813 -136 -27 928 77 38 156 228 -1188 -674 578 81 29 -773 597 -581 -237 392 -398 170 -261 -459 -376 -568 -1026 -272 -629 89 -634 395 443 -585 666 210 481 -58 -117 1059 -981 637 821 750 470 -492 534 251 200 -44 100 -463 -16 326 -334 34 588 -408 743 -5 -117 -674 -79 911 -457 -731] +[611 412 -405 -255 -1009 -205 -749 -565 264 565 -50 -715 -455 502 -171 246 61 -698 -935 0 336 -363 -374 -209 -318 227 177 -508 110 -169 85 289 -282 -272 891 281 49 748 -457 -119 -129 70 -169 -89 412 -259 -432 460 -288 -494 -37 223 -616 -1296 52 -278 -730 1191 -113 485 -224 -426 611 550 458 -429 330 -260 658 -1175 367 -395 -90 632 -65 198 83 35 -561 609 -406 -104 -243 -547 -658 -119 -237 13 58 -733 117 -317 1206 -180 347 234 198 611 128 892] +[84 318 520 545 248 393 -476 47 -212 -608 27 -166 838 -432 114 163 -209 -55 -524 181 -306 581 -746 371 537 -382 628 385 -266 217 -451 424 568 -176 -317 -376 319 89 -98 921 -36 117 380 190 364 -247 405 77 -65 1275 234 -425 -211 189 861 -68 -268 -135 -463 617 783 408 170 339 -967 -580 362 404 -659 264 206 561 680 308 646 -335 434 -535 0 194 178 221 -251 1606 355 213 -138 -65 -316 1048 -657 -61 469 -15 -520 643 -76 354 287 422] +[-34 -404 276 214 134 -862 484 233 -24 746 826 -1021 0 370 110 147 -192 415 -469 -74 121 -284 42 -505 -530 332 148 443 -83 1097 -88 -803 -368 -1 704 -689 256 -523 203 332 518 174 575 87 73 410 -188 661 -888 15 652 1239 -177 -874 -1198 102 409 -540 -42 203 473 -77 375 780 397 521 -888 -526 1486 -410 -744 558 141 -520 21 -261 -23 603 327 113 -664 -854 -236 -199 649 -368 143 67 -385 -728 382 -309 -879 -599 -164 -79 160 757 -455 -185] +[-473 109 210 212 -18 294 -580 425 -1076 -349 -539 -198 43 466 1112 -761 337 -350 796 582 -233 14 200 184 658 112 138 -27 -888 -775 1364 440 -794 -170 216 343 -302 497 -635 275 6 628 299 -735 652 21 103 -18 1039 214 -242 362 2 48 233 41 1 -847 -355 362 93 -431 792 -62 0 125 -54 1207 -31 450 -32 -33 -256 -600 677 -431 -1290 414 151 -241 312 651 182 -674 -485 478 -217 -622 125 -43 565 -33 882 -207 260 388 18 -108 309 303] +[-158 210 -9 1587 -228 -248 -352 -270 -182 461 763 -166 7 586 -887 661 67 -477 -738 337 226 353 -524 -192 223 515 -767 101 225 1213 -257 -904 -194 5 618 129 290 -246 732 -291 2 -586 -811 333 309 129 -469 992 -780 -813 584 89 213 61 -342 271 349 -200 259 448 672 12 425 103 -439 -1044 -350 -771 733 -671 -202 -844 184 164 386 -249 630 1061 200 426 -282 181 -293 -327 164 -359 -14 -119 -419 -473 -238 -425 134 -383 -3 566 285 346 -368 -8] +[284 138 -85 -997 236 -500 -122 -118 -432 396 -401 110 215 -493 -245 -787 110 -182 97 -236 338 -490 -97 280 -421 695 466 109 368 -1110 54 943 -642 -337 175 -265 -105 1260 356 291 213 -278 1211 431 -380 -792 270 -723 -183 -320 640 -166 -433 615 495 -1 -339 -105 -550 -217 -784 404 -551 817 -17 -598 1056 -384 917 1250 431 -250 720 26 -584 67 -205 182 -332 395 -276 -183 604 99 -703 406 140 229 18 427 935 -67 729 -91 618 -570 -39 335 -326 -165] +[226 795 -595 764 -264 -265 630 -529 -698 -330 654 171 -319 -92 -590 -692 753 -71 603 -281 -519 324 -83 -106 -52 -328 -377 523 -137 -771 157 316 246 -924 -217 171 220 616 309 156 -529 867 -346 -930 449 217 -398 -683 -420 680 -323 366 414 659 491 -647 -13 539 1057 214 -14 663 673 337 -505 -527 258 -114 -502 297 -555 -283 -214 -847 -238 68 -148 863 -70 -718 496 527 428 -606 -365 976 365 56 -738 -60 -466 -262 -676 -1014 -235 -289 -329 390 587 -321] +[-93 -18 142 -311 -427 49 1028 432 353 151 151 -1111 -603 -621 -315 1077 -604 392 -371 -67 -172 -71 393 -178 -689 570 334 491 923 99 252 8 -271 -805 729 -130 -142 -46 -253 -131 803 -291 481 90 -31 -560 -129 598 -132 151 298 533 -103 90 -230 842 177 463 -948 -521 -512 478 -568 709 -141 650 201 233 763 -299 -756 274 117 239 -572 1259 -256 659 -719 139 -1034 11 34 -678 89 -767 663 -60 655 239 -353 744 -391 311 -37 -559 -139 791 -783 606] +[-91 107 471 28 334 310 -255 73 -757 -312 418 97 -422 192 123 342 -645 140 439 296 667 -40 68 204 -645 1022 96 -49 -483 695 253 -86 -729 759 573 -14 711 200 399 275 323 -120 -425 -548 396 -3 209 985 -755 -286 313 537 -2 -268 -180 -278 32 -10 -94 142 381 208 51 904 292 -999 -58 -119 -191 43 -54 -832 -188 201 -442 -71 142 1158 -451 678 -190 -710 -179 536 5 -177 661 -535 294 -871 119 -595 314 84 -106 -223 335 412 1115 -103] +[-170 201 -81 -601 85 -494 -128 286 796 589 -7 -49 726 -40 -293 -349 920 916 -859 -118 -350 420 -876 -234 371 40 -61 -585 507 775 -248 -212 497 298 -83 22 -876 -622 399 -199 1043 -545 518 1078 -394 544 -448 -333 125 -34 1132 -492 -442 285 -396 146 -34 154 -134 369 -628 -499 -1288 -642 -682 -36 252 -203 349 -489 115 97 264 726 -352 416 646 -170 -485 -674 67 -297 -651 534 1062 -155 -155 -92 -489 746 -1265 338 -214 245 -162 493 878 -165 -222 -236] +[367 -551 -170 24 575 -75 840 341 353 -144 -758 648 49 471 153 -127 190 544 -438 -261 -123 73 771 -325 -951 -635 -308 520 -80 -630 -166 267 599 422 386 -285 274 -139 422 -317 -199 -1113 77 574 -341 -624 410 -181 -254 -873 -202 -210 -874 563 53 615 6 480 -233 929 636 -31 -191 -78 434 700 196 -615 154 -833 -169 341 719 121 515 613 288 -4 1 -507 -59 -380 26 784 911 -380 -234 -45 227 674 197 -502 -33 834 -926 78 -107 1248 114 -470] +[-95 -110 -232 617 689 -68 442 236 93 -431 308 -447 -336 242 -807 307 -11 24 -812 -190 125 -542 -105 -184 -265 91 -495 -498 -177 743 297 -768 77 -670 -332 175 -879 445 373 131 -63 234 -923 156 -17 -373 82 68 272 -27 303 -400 445 532 -50 732 332 -773 -11 -116 -433 -7 -356 -440 -212 409 -500 -610 395 -37 318 -355 82 -127 -62 225 447 618 303 428 -443 -480 349 330 -331 302 148 -232 -731 -297 153 -421 -784 -609 -502 218 673 -203 -503 -1412] +[-123 -272 -151 1122 446 485 -175 820 -383 655 -408 -434 295 -440 -780 42 -1352 133 -85 -208 243 555 -1006 -355 -381 -198 217 422 -802 1383 222 -1118 -22 82 236 -411 130 131 472 -311 169 272 46 421 -544 -838 93 -137 618 -411 502 479 440 843 -696 1168 167 476 433 -424 -403 58 -632 -59 -316 -235 117 360 911 433 530 -579 -441 442 -563 341 431 481 -353 -791 82 -341 6 233 -537 138 -153 280 -452 -601 424 -308 -607 -799 -396 689 191 -770 -485 -800] +[710 317 624 -575 -592 -634 -106 -183 742 200 -460 41 -80 -306 351 394 -2 299 -1062 417 617 -1040 -396 1023 92 -272 -87 526 132 -44 306 -216 -210 -1553 -294 -95 -429 630 -336 174 896 346 208 -260 449 -1192 101 -574 15 82 266 -231 -375 -703 298 256 256 111 -149 -614 71 -311 -563 344 -173 502 -73 -429 1524 -185 -203 588 269 -182 -629 962 -792 -240 16 -417 -768 -82 795 -560 285 -240 307 73 -382 -228 128 213 -271 526 172 -551 217 9 -202 -175] +[-421 178 -642 537 396 -328 -197 45 -99 -757 -162 1198 179 570 -288 -4 -797 -168 -164 -346 632 -713 141 -350 -109 -526 -203 -584 -129 -163 -212 708 116 777 -208 -27 -489 843 73 75 -911 637 -446 154 -50 -827 386 79 559 -175 -936 -527 -528 557 147 297 -174 -179 -56 -368 -292 -774 -150 -52 486 325 210 -486 -656 496 567 -11 -193 178 299 -123 243 350 290 198 100 902 300 162 -591 -330 -622 -347 -345 -741 359 -687 205 274 258 -195 -462 -213 365 284] +[397 261 84 129 338 280 -1215 462 -1181 468 1261 723 79 351 638 -800 188 367 -11 345 381 -215 -639 106 252 -157 341 237 -116 48 -1078 14 294 813 -39 702 705 586 534 290 215 -307 225 -226 -506 -208 709 -121 -716 229 724 96 -371 270 88 -363 1 318 531 679 -311 -530 21 783 -351 304 432 -4 432 26 -128 -185 130 -802 -189 393 13 -97 -211 256 119 140 -293 748 -356 601 -662 -276 -230 634 459 -456 783 276 250 337 153 -133 -1071 715] +[456 -375 510 696 -203 -315 -582 -193 54 92 -566 -618 -609 -153 359 -68 393 -95 124 492 -363 191 372 236 613 295 -268 -416 -206 -272 1056 -142 -539 -1162 704 101 -149 341 -686 -97 302 113 308 641 -230 -315 -799 -700 1015 107 262 2 -166 468 69 123 -360 426 171 62 -1194 32 -310 249 -403 57 678 516 608 432 319 887 431 31 228 169 -807 -815 -419 -98 794 199 -773 -766 -603 -204 -288 787 641 333 777 86 648 297 941 -438 -497 519 -332 330] +[371 797 254 -1001 11 -145 -679 -111 -200 443 -946 419 -26 -220 276 -426 377 -169 -646 -325 -184 171 131 -574 -331 27 -106 442 133 -86 -88 901 -331 207 -531 235 -621 303 166 150 -43 62 -276 -58 -660 185 191 111 -822 -470 90 -452 -195 15 -241 271 -994 535 -417 -242 -342 -296 -28 -46 -15 -148 66 126 831 -72 27 12 136 468 -167 729 -131 -264 119 -379 38 185 -85 30 180 -535 -468 405 91 253 634 338 475 365 318 282 79 456 -674 380] +[-640 -288 -98 -107 -469 -78 717 -380 742 338 695 -56 203 301 -44 -168 -133 468 61 -113 -126 376 346 513 258 -477 159 -933 1034 -185 -1121 -166 533 -539 -702 110 -139 -556 -972 -1169 590 433 -312 775 191 547 -302 477 -101 413 -527 -376 234 632 -68 167 150 -104 110 205 -122 464 -490 111 28 953 -117 -327 -493 -328 -768 -233 224 -1078 -843 -692 232 -541 -21 -547 -461 -105 236 -711 35 92 626 338 372 719 -566 -450 -334 537 -111 756 294 -774 685 -415] +[449 -235 -410 98 -254 -644 424 213 19 145 -63 -568 1 -90 -126 422 861 -380 -303 -573 -606 15 618 -20 1009 -511 -427 305 -680 -1088 549 -184 166 116 196 -141 89 -62 -9 373 166 88 423 -585 556 60 -178 9 473 -37 404 -121 -549 -451 -462 748 340 -652 -832 309 -111 -621 138 -573 50 1050 -615 66 68 -105 -802 105 229 -370 628 404 -522 -132 439 -305 46 121 186 -397 754 35 -18 -81 -786 285 -338 -216 796 79 -526 424 -109 -348 -44 743] +[-142 310 -5 -218 -398 126 -243 -439 -835 365 454 966 371 -294 20 419 -413 594 85 620 1230 -620 -498 -622 431 698 -365 -376 1175 427 -90 -501 -268 330 -54 570 -37 156 754 -172 -67 -449 90 -313 -416 25 126 -114 228 -714 461 -119 728 -22 -754 -631 63 280 875 -947 -619 279 -1443 84 269 -77 -279 -302 805 -142 445 203 -771 -1192 -969 82 749 -10 324 325 714 -156 148 -358 -592 -283 -156 -72 1216 -591 525 -55 -343 565 317 -255 148 -870 252 -141] +[-1 -825 103 -300 -68 296 -188 -344 139 -629 -466 594 64 122 -166 -493 92 347 -593 440 751 -685 -134 775 306 4 -361 -275 -280 1131 399 477 -335 -300 -301 -483 115 -620 -496 -580 -284 378 -804 -291 -82 649 -943 -109 -99 -264 428 -123 158 -756 346 171 -698 827 79 487 915 -353 819 349 -741 -1094 -446 40 621 -135 -804 -256 -700 326 618 0 138 -1735 -43 -63 803 387 189 -194 511 314 72 433 633 -77 466 509 -690 695 1174 -177 -337 445 46 -388] +[-110 411 -148 638 98 558 -834 -33 -428 -99 118 130 133 -625 19 -811 467 -218 -124 125 -421 379 337 1065 641 -174 -199 -119 -331 -920 -188 95 371 352 459 997 -644 64 17 -116 -237 141 746 -580 358 513 290 70 -404 -59 3 -220 -270 244 164 -75 -82 -884 -502 496 231 -760 -215 240 -798 -760 -690 198 -374 500 -312 87 818 -732 538 -338 -113 -971 -59 -247 756 -252 -1072 266 -193 250 -197 -415 -767 63 -107 269 87 -436 -163 482 136 -68 -740 335] +[-76 531 282 -470 -25 180 -268 -314 -355 145 623 215 -472 -368 -323 -240 295 241 382 452 -290 -573 178 -46 839 858 -65 -665 -289 -774 428 452 -177 360 931 623 -40 372 8 135 -581 -805 380 150 -6 -233 -693 60 -803 -335 -156 -1092 -462 -756 192 -798 -361 -286 336 -361 -232 -445 -502 -239 -504 -697 -682 -448 516 396 493 1041 451 94 -290 -276 128 -274 522 -410 176 63 -523 -126 123 510 -55 384 192 353 -909 917 850 -329 225 -676 274 -85 -684 1013] +[-345 771 358 -787 339 -516 -115 302 76 -73 -337 121 154 -27 801 -362 668 -747 550 639 -422 425 29 -283 -146 -872 68 -384 317 1008 -554 -426 614 574 261 -239 -383 -1013 -767 -40 678 40 916 262 628 -613 161 297 655 -42 662 -99 -363 386 -471 -259 56 -284 -600 -11 -58 -180 -1306 237 553 265 85 722 -429 143 -48 -256 -456 -114 -366 40 555 -144 -187 420 113 806 -912 284 386 26 -198 -590 -1056 141 301 253 175 98 494 -426 63 -376 315 -580] +[213 121 530 -621 -244 -440 -611 805 -268 891 14 -561 357 -63 1657 374 285 -179 683 695 194 -59 -1057 -1047 373 68 291 -664 -133 121 -143 -686 -93 398 -92 133 698 -615 -259 97 235 -79 189 361 147 -39 -371 739 289 174 351 251 -766 -1082 -475 -670 608 319 467 223 214 -79 71 540 759 106 -32 724 -56 -784 268 -47 -615 346 147 51 -315 -380 -237 83 244 -34 -606 70 -230 36 43 -96 99 -619 713 616 -47 35 1492 -152 344 -504 -25 261] +[300 454 126 1092 -891 -342 -750 -158 -899 343 186 270 85 185 51 -388 -574 72 147 372 -15 54 -38 5 524 -626 -702 163 -819 -53 310 -475 148 423 -631 518 -164 -416 486 74 -321 282 -162 -531 -43 -121 208 692 1091 221 465 550 -405 55 -538 -121 658 -737 -454 -103 342 165 -225 343 -260 572 -559 85 122 93 31 -812 187 119 307 -393 -355 -254 62 -328 493 81 -237 144 242 43 493 -342 -616 -619 1308 158 -250 -339 453 -42 458 -584 92 -958] +[278 -156 526 747 -438 365 -596 383 386 -256 -402 -53 -382 450 586 -791 1092 -92 -338 558 -548 -30 187 742 121 -414 -561 -23 -822 540 214 55 221 -716 -41 -51 194 -361 -449 -450 37 326 -304 -480 -354 -595 249 -761 -161 176 182 529 -133 -571 304 16 -334 158 -212 -258 931 -383 945 833 -668 -302 -760 -72 809 -743 -285 107 -129 468 253 710 -1063 -1164 -725 -198 796 659 189 -179 489 -512 -277 -69 -69 -7 914 -398 316 482 949 264 -182 578 -876 -102] +[609 -308 -656 760 -735 -30 167 -547 339 611 251 -377 -282 -226 -978 468 -1302 -275 -13 -1183 892 391 -374 -218 -210 453 297 -157 -298 -123 -367 -588 -482 -173 -501 661 94 409 -328 -235 -211 380 -132 244 -331 -764 480 -219 -699 -498 -622 -314 93 417 -82 75 -19 632 854 -810 -529 599 -181 -41 323 -15 389 -971 397 -588 724 250 537 281 -1608 493 484 104 508 62 -885 -464 519 -157 -568 317 -572 598 -135 171 -576 -1120 567 339 77 323 -445 -271 714 -530] +[-299 204 -396 51 -785 -295 19 -804 -142 82 251 164 -236 -1074 184 240 183 -498 -108 -386 134 -54 131 -634 84 -606 127 -556 220 416 916 -435 459 422 128 -626 -558 -398 -916 -776 -244 -282 80 712 -419 653 -1016 185 597 -452 -189 496 -319 253 -156 14 15 305 -22 226 -56 -921 410 -282 488 315 93 -440 -804 -1320 -1170 327 -428 802 589 -385 222 -43 514 196 8 300 -706 1488 -103 -371 -417 262 -48 141 -309 509 -550 -247 -308 -18 -586 -302 182 -399] +[56 227 -977 -291 -427 -837 506 320 572 525 29 158 -284 752 -642 691 -918 659 -120 -564 543 -151 -100 -537 -340 127 -105 -284 682 1075 -846 -196 -819 -61 -657 -708 439 218 -198 -96 511 -403 527 340 -485 -864 -601 -181 -574 -683 263 -1227 -222 366 -425 -143 539 291 805 -666 -740 264 -721 37 106 -335 -552 -470 -6 495 1360 -190 -351 191 -1116 757 491 52 -162 837 -52 -895 774 3 293 518 -217 -336 -580 -156 -505 -914 262 -2 -203 -291 144 69 423 -449] +] +20 \ No newline at end of file