- 注册时间
- 2017-12-7
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 3243
- 在线时间
- 小时
|
发表于 2020-11-30 17:06:46
|
显示全部楼层
离成功优化powermod大概只差一步了- fn pow_mod(mut base:u128,mut exp:u128,module:u128)->u128{
- // assert!(module < 1<<94 && module&1==1 && exp>0)
- let mut acc = 1;
- //let m64=(module>>64) as u64;
- let m126=(1<<126)%module;
- let m157=(m126<<31)%module;
- let mulmod=|mut x,mut y|{
- let [lx,ly,mut hx,hy]=[x&9223372036854775807,y&9223372036854775807,x>>63,y>>63];
- x=lx*hy+ly*hx;
- y=lx*ly+((x&9223372036854775807)<<63);x>>=63;//y=low_mid, x=high_mid<<126
- //lx*ly+y+x<<126+hx*hy<<126
- x+=hx*hy;
- //lx*ly+y+x<<126
- hx=x&2147483647;
- x>>=31;
- //(y+hx*m126+x*m157)%module
- y+=hx*m126+x*m157;
- //y-(((y>>64)as u64)/m64) as u128*module
- y%module
- //lx.max(ly) < 1<<63 ==> lx*ly < 1<<126
- // y < 9223372036854775807<<63 < 1<<126
- //hx <2147483647*module< 1<<31+94 = 1<<126
- // x <(module*module>>(63*2+31))*module < 1<<(94*2-63*2-31+94)=1<<125
- //Thus, lx*ly+y+hx*m126+x*m157 < 1<<128, safe to add them together and executing % ops.
- };
- while exp > 1 {
- if (exp & 1) == 1 {
- acc = mulmod(acc,base);
- base = mulmod(base,base);
- }else{
- base = mulmod(base,base);
- }
- exp >>= 1;
- }
- mulmod(acc,base)
- }
- fn main(){
- const CONSTARR:[u128;7]=[1u128<<1,1u128<<2,1u128<<4,1u128<<8,1u128<<16,1u128<<32,1u128<<64];
- let now=std::time::Instant::now();
- let arguments: Vec<String> = std::env::args().collect();
- let begin=arguments.get(2).and_then(|x|Some(x.parse::<u128>().unwrap_or(0))).unwrap_or(0);
- let len=arguments.get(1).and_then(|x|Some(x.parse::<u128>().unwrap_or(10000000))).unwrap_or(10000000);
- let mut am1=10000000000000000000000000000u128+begin*len;
- let mut a=10000000000000000000000000001u128+begin*len;
- println!("from={},len={}",a,len);
- let mut b=2;
- let mut am1d=0;
- let mut prime=0u64;
- let mut psp=0u64;
- for _i in 0..len>>1{
- let aa=am1.trailing_zeros().min(6);
- am1d=&am1>>aa;
- if {b=CONSTARR[aa as usize]; pow_mod(b,am1d,a)==1u128}{//Fermat
- psp+=1;/*
- if {b.assign(2u8);//Miller-Rabin
- let aa=a.find_one(0).unwrap();
- am1d.assign(&am1>>aa);
- let _=b.pow_mod_mut(&am1d,&a);
- (b==1 || b==am1 )||{
- let mut f=false;
- for _ in 0..aa{
- let _=b.pow_mod_mut(&Integer::from(2),&a);
- if b==am1{f=true;break}
- }
- f
- }
- }{
- if a.is_probably_prime(25)==rug::integer::IsPrime::No{
- println!("{} is SPSP(2)",a)
- }else{prime+=1}
- }else{println!("{} is PSP(2)",a)}*/
- }
- a+=2;
- am1+=2;
- }
- println!("{}.{},{},{:?}",a,prime,psp-prime,now.elapsed());
- }
复制代码 这个程序是gmp的1/2,但如果拿掉取模步,速度是gmp的两倍多。
另外,或许应该直接写C调GMP,GMP写了Miller-Rabin测试,不知速度如何,但小改一下应该比Fermat快。
毕竟Miller-Rabin可以少算好几次乘法。 |
|