00001 #include "polphi_template.H"
00002
00009 class Tfibpair
00010 {
00011 private:
00012 mpz_t x1,x2;
00013 mpz_t h1,h2,h3;
00014
00015 inline const Tfibpair& operator= (const Tfibpair&) const { MARK; exit(9); return *this; }
00016
00017
00018 public:
00019 Tfibpair()
00020 {
00021
00022 mpz_init_set_ui(x1,0);
00023 mpz_init_set_ui(x2,1);
00024 mpz_init(h1); mpz_init(h2); mpz_init(h3);
00025 }
00026 Tfibpair(const unsigned int f1, const unsigned int f0)
00027 {
00028
00029
00030 mpz_init_set_ui(x1,f1);
00031 mpz_init_set_ui(x2,f0);
00032 mpz_init(h1); mpz_init(h2); mpz_init(h3);
00033 }
00034 Tfibpair(const Tfibpair &X)
00035 {
00036 mpz_init_set(x1,X.x1);
00037 mpz_init_set(x2,X.x2);
00038 mpz_init(h1); mpz_init(h2); mpz_init(h3);
00039 }
00040 ~Tfibpair()
00041 {
00042 mpz_clear(h3); mpz_clear(h2); mpz_clear(h1);
00043 mpz_clear(x2); mpz_clear(x1);
00044 }
00045
00046 inline void set(const unsigned int f1, const unsigned int f0)
00047 {
00048 mpz_set_ui(x1,f1);
00049 mpz_set_ui(x2,f0);
00050 }
00051 inline void set(const signed int f1, const signed int f0)
00052 {
00053 mpz_set_si(x1,f1);
00054 mpz_set_si(x2,f0);
00055 }
00056 inline void set(const Tfibpair &X)
00057 {
00058 mpz_set(x1,X.x1);
00059 mpz_set(x2,X.x2);
00060
00061 }
00062
00063
00064 inline const mpz_t& fn(void) const { return x1; }
00065 inline const mpz_t& fnm1(void) const { return x2; }
00066 inline const mpz_t& Ln(void) { mpz_add(h1,x2,x2); mpz_add(h1,h1,x1); return h1; }
00067
00068 inline void mod(const mpz_t m)
00069 {
00070 mpz_mod(x1,x1,m);
00071 mpz_mod(x2,x2,m);
00072 }
00073 inline void mul(const Tfibpair &Q)
00074 {
00075 mpz_add(h1,x1,x2); mpz_add(h2,Q.x1,Q.x2); mpz_mul(h1,h1,h2);
00076 mpz_mul(h2,x1,Q.x1);
00077 mpz_mul(h3,x2,Q.x2);
00078 mpz_sub(x1,h1,h3); mpz_add(x2,h2,h3);
00079 }
00080 inline void square()
00081 {
00082 mpz_add(h1,x1,x2); mpz_mul(h1,h1,h1);
00083 mpz_mul(h2,x1,x1);
00084 mpz_mul(h3,x2,x2);
00085 mpz_sub(x1,h1,h3); mpz_add(x2,h2,h3);
00086 }
00087 inline void fastsquare()
00088 {
00089
00090 #ifdef DEBUG
00091 const bool flag = (mpz_cmp_ui(x1,1)==0 && mpz_cmp_ui(x2,0)==0);
00092 if (flag) cout << "error, error!" << endl;
00093 #endif
00094 mpz_mul(h1,x1,x1); mpz_mul(h2,x2,x2);
00095 mpz_add(x2,h1,h2);
00096 mpz_mul_2exp(h1,h1,2); mpz_sub(h1,h1,h2); mpz_add_ui(h1,h1,2);
00097 mpz_sub(x1,h1,x2);
00098 }
00099 inline void pow(const unsigned int n)
00100 {
00101
00102 Tfibpair Q(*this);
00103 if ((n&1)==0) set(0,1);
00104 for (unsigned int i=2; i<=n; i<<=1)
00105 {
00106 Q.square();
00107 if (n&i) mul(Q);
00108 }
00109 }
00110 inline void powmod(const unsigned int n, const mpz_t m)
00111 {
00112
00113
00114 Tfibpair Q(*this);
00115 if ((n&1)==0) set(0,1);
00116 for (unsigned int i=2; i<=n; i<<=1)
00117 {
00118 Q.square(); Q.mod(m);
00119 if (n&i) { mul(Q); mod(m); }
00120 }
00121 }
00122
00123 #if 0
00124 inline void fastpowmod(const unsigned int n, const mpz_t m)
00125 {
00126
00127
00128
00129
00130
00131
00132
00133
00134 const Tfibpair saved(*this);
00135 signed int b = 8*sizeof(b)-1;
00136 while ( (n&(1<<b))==0 ) --b;
00137 while (--b>=0)
00138 {
00139 fastsquare(); mod(m);
00140 if (n&(1<<b)) { mul(saved); mod(m); }
00141 }
00142 }
00143 #else
00144 inline void fastpowmod(const unsigned int n, const mpz_t m)
00145 {
00146
00147
00148
00149
00150
00151
00152
00153
00154 mpz_t dx1, dx2;
00155 mpz_init_set(dx1,x1); mpz_init_set(dx2,x2); mpz_add(h3,x1,x2);
00156 signed int b = 8*sizeof(b)-1;
00157 while ( (n&(1<<b))==0 ) --b;
00158 while (--b>=0)
00159 {
00160
00161 mpz_mul(h1,x1,x1); mpz_mul(h2,x2,x2);
00162 mpz_add(x2,h1,h2);
00163 mpz_mul_2exp(h1,h1,2); mpz_sub(h1,h1,h2); mpz_add_ui(h1,h1,2);
00164 mpz_sub(x1,h1,x2);
00165 mod(m);
00166 if (n&(1<<b))
00167 {
00168
00169
00170
00171 mpz_mul(h1,h1,h3);
00172 mpz_mul(h2,x2,dx2);
00173 mpz_mul(x2,x1,dx1);
00174 mpz_sub(x1,h1,h2); mpz_add(x2,x2,h2);
00175 mod(m);
00176 }
00177 }
00178 mpz_clear(dx2); mpz_clear(dx1);
00179 }
00180 #endif
00181
00182 #if 1
00183
00184
00185 inline void set_Fibonacci(const signed int n)
00186 {
00187 if (n==0) { set(0,1); return; }
00188 if (n<0) { set(1,-1); pow(-n); } else { set(1,0); pow(n); }
00189 }
00190
00191 inline void step_forward(unsigned int d)
00192 {
00193
00194
00195
00196
00197 if (d<100)
00198 {
00199 while(d--) { mpz_swap(x1,x2); mpz_add(x1,x1,x2); }
00200 }
00201 else
00202 {
00203 Tfibpair temp(1,0);
00204 temp.pow(d);
00205 mul(temp);
00206 }
00207 }
00208 inline void step_backward(unsigned int d)
00209 {
00210
00211
00212
00213
00214 if (d<100)
00215 {
00216 while(d--) { mpz_sub(x1,x1,x2); mpz_swap(x1,x2); }
00217 }
00218 else
00219 {
00220 Tfibpair temp;
00221 temp.set_Fibonacci(-1);
00222 temp.pow(d);
00223 mul(temp);
00224 }
00225 }
00226 #endif
00227
00228 };
00229
00230
00231 class CRingFib
00232 {
00233 private:
00234 Tfibpair a;
00235
00236 inline const CRingFib& operator= (const CRingFib&) const { MARK; exit(9); return *this; }
00237
00238
00239 public:
00240 static const std::string name;
00241 static const int SieveIntervalSize=2*3*5*7*11*13*17;
00242 CRingFib() : a() { }
00243 CRingFib(const CRingFib &x) : a(x.a) { }
00244 ~CRingFib() { }
00245 bool set_startvalue(const unsigned int seed=1)
00246 {
00247 a.set(1,0);
00248 return seed==1;
00249 }
00250 void set(const CRingFib &x) { a.set(x.a); }
00251 void pow_mod(const unsigned int i, const mpz_t M) { a.powmod(i,M); }
00252 void fast_pow_mod(const unsigned int i, const mpz_t M) { a.fastpowmod(i,M); }
00253 void test_gcd(mpz_t x, const mpz_t M) { mpz_gcd(x,a.fn(),M); }
00254 friend class CRingFibPhase2;
00255 };
00256 const std::string CRingFib::name = "fib";
00257
00258
00259 class CRingFibPhase2 : private ForbidAssignment
00260 {
00261 private:
00262 Tfibpair F, stepF, mulF;
00263 mpz_t Fii, Lii, Liip, FD, LD, temp1, temp2;
00264 public:
00265 explicit CRingFibPhase2(const CRingFib &_F) : F(_F.a), stepF(), mulF()
00266 {
00267 F.powmod(2,n);
00268 stepF.set(F), mulF.set(F);
00269 mpz_init(Fii); mpz_init(Lii); mpz_init(Liip);
00270 mpz_init(FD); mpz_init(LD); mpz_init(temp1); mpz_init(temp2);
00271 }
00272 ~CRingFibPhase2()
00273 {
00274 mpz_clear(Fii); mpz_clear(Lii); mpz_clear(Liip);
00275 mpz_clear(FD); mpz_clear(LD); mpz_clear(temp1); mpz_clear(temp2);
00276 }
00277
00278 void get_polynomdef_point(mpz_t x)
00279 {
00280 mpz_set(x,stepF.fn()); mpz_mul(x,x,x); mpz_mod(x,x,n);
00281 }
00282 void calc_polynomdef_next_point()
00283 {
00284 stepF.mul(mulF); stepF.mod(n);
00285 }
00286
00287 void calc_EvalStartingPoint(const int D, const double ii)
00288 {
00289 Tfibpair h(F);
00290 h.powmod(D,n);
00291 mpz_set(FD,h.fn());
00292 mpz_set(LD,h.Ln());
00293
00294 Tfibpair hp(h);
00295 int pow = static_cast<int>(ii/D);
00296 h.powmod(pow,n);
00297 mpz_set(Fii,h.fn());
00298 mpz_set(Lii,h.Ln());
00299
00300 if (--pow<0) pow=-pow;
00301 hp.powmod(pow,n);
00302 mpz_set(Liip,hp.Ln());
00303 }
00304
00305 void get_point_and_calc_next_point(mpz_t x)
00306 {
00307 mpz_mul(x,Fii,Fii); mpz_mod(x,x,n);
00308
00309
00310
00311
00312
00313
00314 mpz_mul(temp1,Fii,LD); mpz_mul(temp2,Lii,FD);
00315 mpz_add(Fii,temp1,temp2); mpz_mod(Fii,Fii,n);
00316 if (mpz_odd_p(Fii)) mpz_add(Fii,Fii,n);
00317 mpz_tdiv_q_2exp(Fii,Fii,1);
00318
00319 mpz_mul(temp1,Lii,LD); mpz_sub(temp1,temp1,Liip); mpz_mod(Liip,temp1,n);
00320 mpz_swap(Liip,Lii);
00321 }
00322
00323 };
00324
00325
00326
00327
00328 template void polphi_template<CRingFib,CRingFibPhase2>(const int phase1, const double phase2);
00329
00330 #define fibonacci_ppm1(phase1,phase2) polphi_template<CRingFib,CRingFibPhase2>(phase1,phase2)