00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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()
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;
00041 };
00042 inline void init(const mpz_t M)
00043 {
00044 mpz_set(N,M);
00045
00046
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)
00052 {
00053 CN_Residue();
00054 init(M);
00055 };
00056 inline ~CN_Residue()
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
00065 mpz_tdiv_r_2exp(m,T,k);
00066 mpz_mul(m,m,Ns);
00067
00068 mpz_tdiv_r_2exp(m,m,k);
00069 mpz_mul(t,m,N); mpz_add(t,t,T);
00070
00071 mpz_tdiv_q_2exp(res,t,k);
00072 if (mpz_cmp(res,N)>=0)
00073 {
00074 mpz_sub(res,res,N);
00075 if (mpz_cmp(res,N)>=0)
00076 {
00077
00078
00079 mpz_mod(res,res,N);
00080 }
00081 }
00082 };
00083 inline void convert(mpz_t x) const
00084 {
00085
00086 mpz_mul_2exp(x,x,k);
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 };