www.pudn.com > CiperLib_release_by_csk.rar > ZModn.cpp
/*
Multiple-precision modular arithmetic
BY CSK(³ÂÊ¿¿)
CSK@live.com
www.csksoft.net
*/
#include "CiperLib.h"
#include "inner_support.h"
//ZModn::genPrimeArr will generate all primes <= MAX_PRIME_NUM to quickly test
//whether an Integer is a prime, implemented by ZModn::quickPrimeDec
#define MAX_PRIME_NUM 1000
//ZModn::isPrime() func will trying R_M_TRYING_TIME times to safely make a decision
#define R_M_TRYING_TIME 100
bool ZModn::is_prime_arr_inited = false;
unsigned int ZModn::prime_array[MAX_PRIME_NUM];
void ZModn::genPrimeArr(){
char *tmp_buff;
int pix,i,k,prime;
int max_prime;
max_prime=(MAX_PRIME_NUM+1)/2;
tmp_buff=new char[max_prime];
memset(tmp_buff,1,max_prime);
pix=1;
for (i=0;i tmp_k
w8 -> tmp2
w2 -> tmp3
w9 -> tmp4
*/
/* Miller-Rabin */
static Integer tmp_k,tmp2,tmp3,tmp4;
tmp_k = src - 1;
k=0;
while (Integer::raw_div_int(tmp_k,2,tmp_k)==0)
{
k++;
tmp2 = tmp_k;
}
times=R_M_TRYING_TIME;
d=IntHelper::logb2(src); /* for larger primes, reduce NTRYs */
if (d>220) times=2+((10*times)/(d-210));
ZModn tmpZm;
tmpZm.m_mod_value = src;
tmp_k = tmp2;
tmpZm.toMod(tmp_k);
for (n=1;n<=times;n++)
{
j=0;
do
{
r=(int)IntHelper::MZ_rand()%MR_TOOBIG;
if (src.m_acutual_len==1 && src.m_p_data_arr[0]0 || tmp4.m_acutual_len!=1 || tmp4.m_p_data_arr[0]!=1)
&& tmp4!=tmp3)
{
j++;
if ((j>1 && (tmp4.m_acutual_len==1 && tmp4.m_p_data_arr[0]==1)) || j==k)
{
return false;
}
/*
x = y = z = r = w9 = tmp4
w = q = src
*/
tmp4 *= tmp4;
tmp4 %=src;
}
}
return true;
}
Integer & ZModn::toMod(Integer& src) //src = src mod m_mod_value
{
if (!m_mod_value.isZero())
src %= m_mod_value;
return src;
}
//
Integer & ZModn::mod_add(Integer&src, Integer& dest)
{
dest+=src;
if (!m_mod_value.isZero())
if (dest>=m_mod_value) dest-=m_mod_value;
return dest;
}
Integer & ZModn::mod_mul(Integer&src, Integer& dest)
{
//TODO not the efficient way
//Using Montgomery's REDC after mul would be better
dest *= src;
if (!m_mod_value.isZero())
dest %= m_mod_value;
return dest;
}
Integer & ZModn::mod_pow(Integer&src, Integer& N)
{
// "Analysis of Sliding Window Techniques for Exponentiation",
// C.K. Koc, Computers. Math. & Applic. Vol. 30 pp17-24 1995.
int i,j,k,t,nb,nbw,nzs,n;
Integer *int_tb[16];
if (src.isZero() ){
if (N.isZero()) src.zero();
return src;
}
Integer tmp = N, tmpAns;
Integer tmp1;
if (tmp.isZero())
{
src = 1;
return src;
}
tmpAns = 1;
// prepare for further chgs..
toMod(tmpAns);
static Integer i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12;
i1 = src;
int_tb[0]=&i1;
int_tb[1]=&i2;
int_tb[2]=&i3;
int_tb[3]=&i4;
int_tb[4]=NULL;
int_tb[5]=&i5;
int_tb[6]=&i6;
int_tb[7]=&i7;
int_tb[8]=NULL;
int_tb[9]=NULL;
int_tb[10]=&i8;
int_tb[11]=&i9;
int_tb[12]=NULL;
int_tb[13]=&i10;
int_tb[14]=&i11;
int_tb[15]=&i12;
tmp1 = *int_tb[0];
mod_mul(tmp1,tmp1); //x^2
n=15;
j=0;
do
{ // pre-calc
t=1; k=j+1;
while (int_tb[k]==NULL) {k++; t++;}
*int_tb[k] = *int_tb[j];
for (i=0;i1) for (i=nb-2;i>=0;)
{ /* Left to Right method */
n=IntHelper::sliding_window(tmp,i,&nbw,&nzs,5);
for (j=0;j0) mod_mul(*int_tb[n/2],tmpAns);
i-=nbw;
if (nzs)
{
for (j=0;j