modular_mult.cc

Go to the documentation of this file.
00001 // Modular Multiplication Without Trial Division
00002 /* reference:
00003    Peter L. Montgomery: "Modular Multiplication Without Trial Division",
00004    Mathematics Of Computation, Vol. 44 (170), April 1985, p. 519-521
00005 */
00006 
00007 // this module written by Thorsten Reinecke, 1999-11-16
00008 // last change: 2004-08-01
00009 
00010 // not efficient enough (-> should use mpn instead of mpz)
00011 
00026 class CN_Residue
00027 {
00028  private:
00029   mpz_t N;
00030   mpz_t R,Ri,Ns;
00031   mpz_t m,t;
00032   unsigned int k;
00033  public:
00034   inline CN_Residue() /* Konstruktor */
00035     {
00036       cout << "Modular Multiplication Without Trial Division activated." << endl;
00037       mpz_init(N);
00038       mpz_init(R); mpz_init(Ri); mpz_init(Ns);
00039       mpz_init(m); mpz_init(t);
00040       k=0; // Dummywert-Initialisierung
00041     };
00042   inline void init(const mpz_t M) // Initialization
00043     {
00044       mpz_set(N,M); // NResidue --> mod N
00045       // select R=2^k, such that x div/mod R can be computed fast
00046       // compute Ri:=R^(-1) mod N; Ns:=(R*Ri-1)/N;
00047       k=mpz_sizeinbase(N,2)+1; mpz_set_ui(R,1); mpz_mul_2exp(R,R,k);
00048       mpz_invert(Ri,R,N); mpz_mod(Ri,Ri,N);
00049       mpz_mul(Ns,R,Ri); mpz_sub_ui(Ns,Ns,1); mpz_div(Ns,Ns,N);
00050     };
00051   inline explicit CN_Residue(const mpz_t M) // constructor
00052     { 
00053       CN_Residue();
00054       init(M);
00055     };
00056   inline ~CN_Residue() // destructor
00057     {
00058       mpz_clear(N);
00059       mpz_clear(R); mpz_clear(Ri); mpz_clear(Ns);
00060       mpz_clear(m); mpz_clear(t);
00061     };
00062   inline void redc(mpz_t res, const mpz_t T) 
00063     {
00064       //mpz_mod(m,T,R); // isn't efficient!
00065       mpz_tdiv_r_2exp(m,T,k); // this should be better...
00066       mpz_mul(m,m,Ns);
00067       //mpz_mod(m,m,R); // isn't efficient!
00068       mpz_tdiv_r_2exp(m,m,k); // this should be better...
00069       mpz_mul(t,m,N); mpz_add(t,t,T);
00070       //mpz_div(t,t,R); // isn't efficient!
00071       mpz_tdiv_q_2exp(res,t,k); // this should be better...
00072       if (mpz_cmp(res,N)>=0)
00073        {
00074          mpz_sub(res,res,N);
00075          if (mpz_cmp(res,N)>=0)
00076           {
00077             // overflow! arguments are not normalized!
00078             //MARK;
00079             mpz_mod(res,res,N); // fallback: standard mod
00080           }
00081        }
00082     };
00083   inline void convert(mpz_t x) const 
00084    {
00085      //mpz_mul(x,x,R); // isn't efficient!
00086      mpz_mul_2exp(x,x,k); // this should be better...
00087      mpz_mod(x,x,N);
00088    };
00089   inline void convert_back(mpz_t x) const 
00090    {
00091      mpz_mul(x,x,Ri); mpz_mod(x,x,N);
00092    };
00093   inline int invert(mpz_t res, const mpz_t T) const 
00094    {
00095      mpz_set(res,T);
00096      convert_back(res);
00097      int i=mpz_invert(res,res,N);
00098      convert(res);
00099      return i;
00100    };
00101 };

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