elliptic_curve.H

Go to the documentation of this file.
00001 #ifndef ECM_HEADER_
00002 #define ECM_HEADER_
00003 
00004 // Declaration of elliptic curves method (ecm) V1.35
00005 // written by Thorsten Reinecke
00006 // last change: 2007-05-21
00007 
00013 #include <iosfwd>
00014 #include <gmp.h>
00015 #include "utils.H"
00016 #include "mpz_wrapper.H"
00017 using namespace my_mpz_wrapper;
00018 
00019 using std::ostream;
00020 using std::istream;
00021 
00022 using std::cout;
00023 using std::cerr;
00024 using std::flush;
00025 
00026 extern mpz_t n;
00027 
00028 
00029 //#define DEBUG_ECM /* funktioniert nur im SLOW_WEIERSTRASS-Modus ohne NRESIDUE! */
00030 //#define SLOW_WEIERSTRASS /* in allen Phasen in der Form (x:y:1) rechnen */
00031 
00032 
00033 // you may choose one (or none) of the following defines:
00034 /* 
00035    Hint: up to 300 digits you should disable both,
00036          above 300 digits MODULAR_ARITHMETIC should be enabled
00037          (on 32 bit processors).
00038 */
00039          
00040 
00041 //#define NRESIDUE /* use "modular_mult.cc" instead of mpz_mod */
00042 /* Sollte in der aktuellen Implementierung asymptotisch schneller sein als
00043    mod mit Trialdivision. Da aber das Restklassensystem ein anderes ist,
00044    gibt es bei einigen Operationen Kompatibilitätsprobleme.
00045    Wenn man die Operation "redc" durch eine (ggf.) asymptotisch schlechtere,
00046    aber besser (maschinennähere) Implementierung ersetzt, dürfte dies
00047    für kleine Zahlen die schnellste Variante sein und (bei asymptotisch guter
00048    Implementierung) für größere Zahlen ähnlich schnell wie
00049    "MODULAR_ARITHMETIC" ablaufen.
00050 */
00051    
00052 
00053 //#define MODULAR_ARITHMETIC /* use modular_arithmetic.cc instead of mpz_mod (if possible) */
00054 /* Verwendung von reciprocal, d.h. "mpz_mod(a,b,n)" wird durch
00055    a=b-floor(b*(2^k/n)/2^k) ersetzt, wobei 2^k/n konstant bleibt,
00056    und 1/2^k durch Shiften realisiert wird.
00057    -> 2 Multiplikationen ersetzen 1 Division.
00058    Dies ist (bei Verwendung von Karatsuba oder noch schnelleren
00059    Multiplikationen) asymptotisch schneller als die in gmp-2.0.2 verwendete
00060    trialdivision. Scheint sich ab ca. 300 Dezimalstellen zu rentieren.
00061 */
00062   
00063 
00064 #if defined(NRESIDUE) && defined (MODULAR_ARITHMETIC)
00065  #error "You must not define both: NRESIDUE and MODULAR_ARITHMETIC"
00066 #endif
00067 
00068 #if ! ( defined(NRESIDUE) || defined(MODULAR_ARITHMETIC) )
00069  // we use mpz_mod
00070  #define mpz_mulmod(res,a,b,n) { mpz_mul(res,a,b); mpz_mod(res,res,n); }
00071  #define modulo(res,T,n) mpz_mod(res,T,n)
00072 #endif 
00073 
00074 #ifdef NRESIDUE
00075  #include "modular_mult.cc"
00076  /* WICHTIG: 
00077      A) Alle Werte, mit denen gerechnet wird, vorher nach NRESIDUE konvertieren!
00078      B) Das Resultat einer Multiplikation muß durch ein "redc" wieder normiert
00079         werden, bevor es verwendet werden kann!
00080      C) redc niemals (ohne genaue Analyse) ohne vorherige Multiplikation verwenden!
00081      -> daher: für MULTIPLIKATION am besten immer das MAKRO mpz_mulmod benutzen!
00082  */ 
00083  #define mpz_mulmod(res,a,b,n) { mpz_mul(res,a,b); NResidue.redc(res,res); }
00084  #define modulo(res,T,n) NResidue.redc(res,T)
00085 #endif
00086 
00087 #ifdef MODULAR_ARITHMETIC
00088  #include "modular_arithmetic.cc"
00089  #define mpz_mulmod(res,a,b,n) { mpz_mul(res,a,b); NResidue.mod(res,res); }
00090  #define modulo(res,T,n) NResidue.mod(res,T)
00091 #endif 
00092 
00093 
00094 #if (CONTINUATION_METHOD > 0)
00095  #include "polynomial.H"
00096 #endif
00097 
00098 #if defined(DEBUG_ECM) && (!defined(SLOW_WEIERSTRASS) || defined(NRESIDUE))
00099  #error "DEBUG_ECM works only in SLOW_WEIERSTRASS-Mode without NRESIDUE!"
00100 #endif
00101 
00102 
00104 class TmpzPoint : private ForbidAssignment
00105 {
00106  public:
00107   mpz_t x,z;
00108   inline TmpzPoint() { mpz_init(x); mpz_init(z); } // Konstruktor
00109   inline ~TmpzPoint() { mpz_clear(z); mpz_clear(x); } // Destruktor
00110 };
00111 typedef TmpzPoint* PmpzPoint;
00112 typedef const TmpzPoint* PconstmpzPoint;
00113 
00114 
00116 class elliptic_curves : private ForbidAssignment
00117 {
00118  public:
00119   typedef long long int NATNUM;
00120  private:
00121   mpz_t a,b; // außer in go nur lesend verwendbar!
00122   mpz_t h,k,m; // allgemein verwendbar (zwischen Aufrufen veränderbar)!
00123   mpz_t x3,y3; // nur in add, mul2 verwendbar!
00124   mpz_t xh_mul, yh_mul; // nur in mul verwendbar!
00125   PmpzPoint A,B,C,T1,T2; // für den PRAC-Algorithmus in XZ_multiply
00126   int sigma; // über sigma wird die Kurve ausgewählt/definiert
00127   int phase; // für statistische Zwecke: in welcher Phase befinden wir uns?
00128 #ifdef NRESIDUE
00129   CN_Residue NResidue;
00130 #endif
00131 #ifdef MODULAR_ARITHMETIC
00132   CN_Residue NResidue;
00133 #endif
00134  public:
00135   inline elliptic_curves() /* Konstruktor */
00136    : A(new TmpzPoint), B(new TmpzPoint), C(new TmpzPoint),
00137      T1(new TmpzPoint), T2(new TmpzPoint), sigma(-1), phase(-1) 
00138 #ifdef NRESIDUE
00139   , NResidue()
00140  /* Konstruktor aufrufen,
00141     NResidue wird später mit n initialisiert.
00142     n ist DIE globale Variable (die faktorisiert werden soll)
00143     zugegeben: es wäre besser, n trotzdem als Parameter allen Klassen
00144     zu übergeben, aber ich will's jetzt nicht mehr ändern, da
00145     dann auch die Rückgabe der Faktoren und die Division n/FAKTOR
00146     durchgeführt werden müssen... 
00147  */
00148 #endif   
00149 #ifdef MODULAR_ARITHMETIC
00150   , NResidue()
00151  /* Konstruktor aufrufen,
00152     NResidue wird später mit n initialisiert.
00153     n ist DIE globale Variable (die faktorisiert werden soll)
00154     zugegeben: es wäre besser, n trotzdem als Parameter allen Klassen
00155     zu übergeben, aber ich will's jetzt nicht mehr ändern, da
00156     dann auch die Rückgabe der Faktoren und die Division n/FAKTOR
00157     durchgeführt werden müssen... 
00158  */
00159 #endif   
00160     {
00161       mpz_init(a); mpz_init(b);
00162       mpz_init(h); mpz_init(k); mpz_init(m);
00163       mpz_init(x3); mpz_init(y3);
00164       mpz_init(xh_mul); mpz_init(yh_mul);
00165 #ifdef NRESIDUE
00166       NResidue.init(n);
00167 #endif
00168 #ifdef MODULAR_ARITHMETIC
00169       NResidue.init(n);
00170 #endif
00171     }
00172   inline ~elliptic_curves() /* Destruktor */
00173     {
00174       mpz_clear(a); mpz_clear(b);
00175       mpz_clear(h); mpz_clear(k); mpz_clear(m);
00176       mpz_clear(x3); mpz_clear(y3); 
00177       mpz_clear(xh_mul); mpz_clear(yh_mul);
00178       delete A; delete B; delete C; delete T1; delete T2;
00179     }
00180  private:
00181   void check_curve(const mpz_t x, const mpz_t y) const;
00182   void factor_found(mpz_t k) const;
00183 
00184   bool sub(mpz_t xr, mpz_t yr,
00185            const mpz_t x1, const mpz_t y1,
00186            const mpz_t x2, const mpz_t y2); // for single point
00187   bool add(mpz_t xr, mpz_t yr,
00188            const mpz_t x1, const mpz_t y1,
00189            const mpz_t x2, const mpz_t y2); // for single point
00190   bool mul2(mpz_t xr, mpz_t yr, const mpz_t x1, const mpz_t y1);
00191   bool mul(mpz_t xr, mpz_t yr,
00192            const mpz_t x1, const mpz_t y1,
00193            NATNUM K);
00194   bool add(mpz_t xr, mpz_t yr,
00195            const mpz_t x1, const mpz_t y1,
00196            const mpz_t x2, const mpz_t y2,
00197            mpz_t k);
00198   bool init_arithmetic_progression(mpz_t* const x, mpz_t* const y,
00199            const mpz_t startx, const mpz_t starty, const NATNUM startpos,
00200            const unsigned int delta, const unsigned int grad);
00201   bool arithmetic_progression(mpz_t* const x, mpz_t* const y, const int anz);
00202 
00203   void XZ_mul2(mpz_t xr, mpz_t zr,
00204                const mpz_t x1, const mpz_t z1);
00205   inline void XZ_mul2(const PmpzPoint R, const PconstmpzPoint A)
00206     { XZ_mul2(R->x,R->z,A->x,A->z); }
00207   void XZ_mul2plus1(mpz_t xr, mpz_t zr,
00208                     const mpz_t Xp0, const mpz_t Zp0,
00209                     const mpz_t Xp1, const mpz_t Zp1,
00210                     const mpz_t x1, const mpz_t z1);
00211   inline void XZ_mul2plus1(const PmpzPoint R, const PconstmpzPoint A, const PconstmpzPoint B, const PconstmpzPoint C)
00212     { XZ_mul2plus1(R->x,R->z,A->x,A->z,B->x,B->z,C->x,C->z); }
00213 
00214   static unsigned int cost_of_evaluating_lucas_chain(const NATNUM K, const double alpha);
00215   void XZ_multiply(mpz_t xr, mpz_t zr, const mpz_t x1, const mpz_t z1, NATNUM K);
00216 
00217  public:
00218   void go(const int ecm_sigma, NATNUM phase1, const NATNUM phase2);
00219   inline void go(const int ecm_sigma, const int phase1, const int phase2)
00220    {
00221      go(ecm_sigma,static_cast<NATNUM>(phase1),static_cast<NATNUM>(phase2));
00222    }
00223   inline void go(const int ecm_sigma, const double phase1, const double phase2)
00224    {
00225      go(ecm_sigma,static_cast<NATNUM>(phase1),static_cast<NATNUM>(phase2));
00226    }
00227 
00228 };
00229 
00230 #endif /* ECM_HEADER_ */

Generated on Wed Nov 7 23:29:25 2007 for Qsieve by  doxygen 1.5.4