How about" Miller-Rabin primality test"?
when the number < 3.4X10^14 ,the result of test is correct.
static unsigned g_aPrimeList[] = { // 100素数表
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
};
unsigned Montgomery(INT64 n,unsigned p,unsigned m)
{ //快速计算(n^e)%m的值
unsigned k=1;
n%=m;
while(p!=1)
{
if(0!=(p&1))
k=(k*n)%m;
n=(n*n)%m;
p>>=1;
}
return(n*k)%m;
}
bool RabbinMillerTest( unsigned n )
{
if (n<2)
{ // 小于2的数即不是合数也不是素数
throw 0;
}
const unsigned nPrimeListSize=sizeof(g_aPrimeList)/sizeof(unsigned);//求素数表元素个数
for(int i=0;i<nPrimeListSize;++i)
{// 按照素数表中的数对当前素数进行判断
if (n/2+1<=g_aPrimeList[i])
{// 如果已经小于当前素数表的数,则一定是素数
return true;
}
if (0==n%g_aPrimeList[i])
{// 余数为0则说明一定不是素数
return false;
}
}
// 找到r和m,使得n = 2^r * m + 1;
int r = 0, m = n - 1; // ( n - 1 ) 一定是合数
while ( 0 == ( m & 1 ) )
{
m >>= 1; // 右移一位
r++; // 统计右移的次数
}
const unsigned nTestCnt = 7; // 表示进行测试的次数
for ( unsigned i = 0; i < nTestCnt; ++i )
{ // 利用随机数进行测试,
int a = g_aPrimeList[ i ];
if ( 1 != Montgomery( a, m, n ) )
{
int j = 0;
int e = 1;
for ( ; j < r; ++j )
{
if ( n - 1 == Montgomery( a, m * e, n ) )
{
break;
}
e <<= 1;
}
if (j == r)
{
return false;
}
}
}
return true;
}
RabbinMillerTest (2234223321);
return 0;
because this way used "_int64",so it's not applicable for LISP . but for a small number ,it's ok.
(defun paw_mod( bs power diver)
(cond
((zerop power)
1
)
((= power 1)
bs
)
((= (logand power 1) 0)
(paw_mod (rem (* bs bs) diver) (lsh power -1) diver)
)
(t
(rem (* (paw_mod (rem (* bs bs) diver) (/ power 2) diver) bs) diver)
)
)
)
(defun RabbinMiller (base num / D K N RET TT)
(setq n (1- num))
(setq d n)
(while (= (logand d 1) 0)
(setq d (lsh d -1))
)
(setq k (paw_mod base d num))
(if (or (= k 1) (= k n))
t
(progn
(setq tt (/ n 2))
(while (/= d tt)
(setq d (lsh d 1))
(if (= (paw_mod base d num) n)
(setq ret t
d tt
)
)
ret
)
)
)
)
(defun check(p)
(if (> p 13)
(cond
( (or (= (rem p 2) 0)
(= (rem p 3) 0)
(= (rem p 5) 0)
(= (rem p 7) 0)
(= (rem p 11) 0)
(= (rem p 13) 0)
)
nil
)
( (and (RabbinMiller 2 p)
(RabbinMiller 7 p)
(RabbinMiller 5 p)
)
T
)
(t nil)
)
(and (member p '(2 3 5 7 11 13)))
)
)
(check 23421);
nil;