00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00020 #include "modulo.H"
00021
00022 namespace numtheory
00023 {
00024
00025 class Clucas_capsule
00026 {
00027 private:
00028 static const int lucas_cache_size = 128;
00029 unsigned int lucas_p, lucas_q, lucas_p_inv;
00030 int lucas_cache_index;
00031 unsigned int lucas_cache [lucas_cache_size][2];
00032 unsigned int lucasv(const unsigned int Primenumber, const unsigned int m);
00033 public:
00034 inline Clucas_capsule(void) : lucas_cache_index(0) { }
00035 unsigned int lucas(const unsigned int Radikant, const unsigned int Primenumber);
00036 };
00037
00038
00039 unsigned int Clucas_capsule::lucasv(const unsigned int Primenumber, const unsigned int m)
00040 {
00041 using std::cerr;
00042 using std::endl;
00043 if (m==0) return 2;
00044 if (m==1) return lucas_p;
00045
00046
00047 for (int i=lucas_cache_index-1; i>=0; --i)
00048 {
00049 if (lucas_cache[i][0]==m) return lucas_cache[i][1];
00050 }
00051
00052 unsigned int wert;
00053
00054
00055 if (m&1)
00056 {
00057 const unsigned int h1=lucasv(Primenumber,m+1);
00058 const unsigned int h2=lucasv(Primenumber,m-1);
00059 register unsigned int xx;
00060 xx=mulmod(h2,lucas_q,Primenumber)+h1;
00061 wert=mulmod(xx%Primenumber,lucas_p_inv,Primenumber);
00062 }
00063 else
00064 {
00065 const unsigned int h1=lucasv(Primenumber,m>>1);
00066 unsigned int xx;
00067 xx=(powmod(lucas_q,m>>1,Primenumber)<<1)%Primenumber;
00068 wert=(squaremod(h1,Primenumber)+Primenumber-xx)%Primenumber;
00069
00070
00071 if (lucas_cache_index<lucas_cache_size)
00072 {
00073 lucas_cache[lucas_cache_index][0]=m;
00074 lucas_cache[lucas_cache_index++][1]=wert;
00075 } else cerr << "Lucas-Cache should be increased!" << endl;
00076 }
00077 return wert;
00078 }
00079
00080
00081 unsigned int Clucas_capsule::lucas(const unsigned int Radikant, const unsigned int Primenumber)
00082 {
00083 using std::cerr;
00084 using std::endl;
00085 if ((Primenumber&3)!=1)
00086 {
00087 cerr << "Error in Lucassequence Primenumber%4<>1!: " << Primenumber%4 << endl;
00088 exit(1);
00089 }
00090
00091
00092 lucas_q=Radikant;
00093 lucas_p=1;
00094
00095 {
00096 int h1,h2;
00097 do
00098 {
00099 lucas_p++;
00100 h1=squaremod(lucas_p,Primenumber);
00101 h2=mulmod(4,lucas_q,Primenumber);
00102 if (h1>=h2) h1-=h2; else h1=Primenumber-(h2-h1);
00103 } while (legendre(h1,Primenumber)!=-1);
00104 }
00105
00106
00107 lucas_p_inv=fastinvmod(lucas_p,Primenumber);
00108
00109
00110 lucas_cache_index=0;
00111
00112
00113 unsigned int v=lucasv(Primenumber,(Primenumber+1)>>1);
00114
00115 if (v&1) v+=Primenumber;
00116 return v>>1;
00117 }
00118
00119
00133 unsigned int sqrtmod(const unsigned int Radikant, const unsigned int Primenumber)
00134 {
00135
00136
00137 if ((Primenumber&3)==3)
00138 {
00139
00140
00141 return powmod(Radikant,(Primenumber+1)>>2,Primenumber);
00142 }
00143 else
00144 if ((Primenumber&7)==5)
00145 {
00146
00147
00148 unsigned int y = powmod(Radikant,(Primenumber+3)>>3,Primenumber);
00149 if (squaremod(y,Primenumber)==Radikant) return y;
00150 else
00151 {
00152 unsigned int w=powmod(2,Primenumber>>2,Primenumber);
00153 return mulmod(y,w,Primenumber);
00154 }
00155 }
00156 else
00157 {
00158 if (Radikant<=1) return Radikant;
00159
00160
00161 Clucas_capsule lucas_capsule;
00162 return lucas_capsule.lucas(Radikant,Primenumber);
00163 }
00164 }
00165
00166 }