modular_arithmetic.cc

Go to the documentation of this file.
00001 // modular arithmetic
00002 // this module written by Thorsten Reinecke, 2000-04-13
00003 // last change: 2000-04-14
00004 
00005 // Grundidee: a mod N = a - floor(a/N)*N
00006 // Trick: (teure) Division vermeiden durch Vorberechnung von (2^k)/N,
00007 //        denn: 1/N = ((2^k)/N) * (1/(2^k))
00008 //        und Division durch 2^k durch Shiften
00009 // Einzige Bedingung: a darf nicht zu groß werden (oder k muß vergrößert werden)
00010 
00017 class CN_Residue
00018 {
00019  private:
00020   mpz_t N; // Modulo
00021   mpz_t R; // reciprocal of N (=2^(2*ldN)/N)
00022   mpz_t h; // helper variable
00023   unsigned int k;
00024  public:
00025   inline CN_Residue() // constructor
00026     {
00027       cout << "Modular arithmetic using precomputed reciprocal activated." << endl;
00028       mpz_init(N); mpz_init(R); mpz_init(h);
00029       k=0; // initialize with a dummy value
00030     };
00031   inline void init(const mpz_t M) // Initialization
00032     {
00033       mpz_set(N,M); // NResidue --> mod N
00034       k=mpz_sizeinbase(N,2)+1;
00035       mpz_set_ui(h,1); mpz_mul_2exp(h,h,2*k);
00036       mpz_cdiv_q(R,h,N); //mpz_add_ui(R,R,1);
00037     };
00038   inline explicit CN_Residue(const mpz_t M) // constructor
00039     { 
00040       CN_Residue();
00041       init(M);
00042     };
00043   inline ~CN_Residue() // destructor
00044     {
00045       mpz_clear(N);
00046       mpz_clear(R);
00047       mpz_clear(h);
00048     };
00049   inline void mod(mpz_t res, const mpz_t a) // res = a mod N
00050     {
00051       mpz_fdiv_q_2exp(h,a,k-1); mpz_add_ui(h,h,1);
00052       mpz_mul(h,h,R); 
00053       mpz_fdiv_q_2exp(h,h,k+1);
00054       mpz_mul(h,h,N); mpz_sub(res,a,h);
00055       if (mpz_sizeinbase(res,2)>k+1) 
00056        { mpz_mod(res,res,N); cerr << endl << "moderror!" << endl; }
00057     }
00058 };

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