- 注册时间
- 2017-12-7
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 3243
- 在线时间
- 小时
|
发表于 2020-11-30 02:54:34
|
显示全部楼层
本帖最后由 .·.·. 于 2020-11-30 04:20 编辑
试图Miller-Rabin还是不如直接Fermat快。
现在fermat部分应该已经优化到头了。虽然都是调包侠,但明显Rust比Julia调包更快一些
睡了睡了~
- use rug::{Assign, Integer};
- fn main() {
- let now=std::time::Instant::now();
- let mut a=Integer::from(10000000000000000000000000001u128);
- let mut am1=Integer::from(10000000000000000000000000000u128);
- let mut b=Integer::from(2);
- let mut prime=0u64;
- for _i in 0..5000000{
- prime+={b.assign(2u8);let _=b.pow_mod_mut(&am1,&a);b==1u8} as u64;
- a+=2;
- am1+=2;
- }
- println!("{},{},{:?}",a,prime,now.elapsed());
- }
复制代码 (加上isprobableprime的除非改并行否则打死不改版(改并行时候需要注意结果循环外的变量不能被共享))
- /*use num_bigint::BigUint;
- fn main() {
- let now=std::time::Instant::now();
- let mut a=BigUint::from(100000000000000u64);
- a=&a*&a+BigUint::from(1u8);
- let b:BigUint=BigUint::from(2u8);
- //let mut c:BigUint=BigUint::from(0u8);
- let mut prime=0u64;
- for _i in 0..500000{
- if b.modpow(&(&a-BigUint::from(1u8)),&a)==BigUint::from(1u8){prime+=1}
- a+=&b;
- }
- println!("{},{},{:?}",a,prime,now.elapsed());
- }*/
- /*
- use bigint::U256;
- fn fermat(module:U256)->bool{//module should be larger than 1<<64 and less than 1<<128
- let [mut a,b,_,_]=module.0;
- a-=1;
- let mut res=U256([1,0,0,0]);
- let mut pow=U256([2,0,0,0]);
- for _ in 0..64{
- if a&1==1{
- res=(res*pow)%module;
- pow=(pow*pow)%module;
- }else{
- pow=(pow*pow)%module;
- }
- a>>=1
- }
- a=b;
- while a>1{
- if a&1==1{
- res=(res*pow)%module;
- pow=(pow*pow)%module;
- }else{
- pow=(pow*pow)%module;
- }
- a>>=1
- }
- (res*pow)%module==U256([1,0,0,0])
- }
- fn main() {
- let now=std::time::Instant::now();
- let mut a=U256::exp10(28)+U256::from(1);
- let mut prime=0u32;
- for _ in 0..50000{
- if fermat(a){
- prime+=1;
- }
- (a.0)[0]+=2;
- if (a.0)[0]<2{(a.0)[1]+=1}
- }
- println!("{},{},{:?}",a,prime,now.elapsed());
- }*/
- /*use ramp::Int;
- fn main() {
- let now=std::time::Instant::now();
- let mut a=Int::from(10000000000000000000000000001u128);
- let b=Int::from(2u8);
- let mut c=Int::from(0u8);
- for _i in 0..500000{
- c+=b.pow_mod(&(&a-1),&a);
- a=a+2;
- }
- println!("{},{},{:?}",a,c,now.elapsed());
- }*/
- /*
- use gmp::mpz::Mpz;
- fn main() {
- let now=std::time::Instant::now();
- let mut a=Mpz::from_str_radix("10000000000000000000000000001",10).unwrap();
- let b=Mpz::from_str_radix("2",10).unwrap();
- let mut prime=0u64;
- for _i in 0..5000000{
- prime+=(b.powm(&(&a-1),&a)-1).is_zero() as u64;
- a=a+2;
- }
- println!("{},{},{:?}",a,prime,now.elapsed());
- }*/
- /*Pure Miller-Rabin
- use rug::{Assign, Integer};
- fn main() {
- let now=std::time::Instant::now();
- let mut a=Integer::from(10000000000000000000000000001u128);
- let mut am1=Integer::from(10000000000000000000000000000u128);
- let mut b=Integer::from(2);
- let mut buffer=Integer::from(0);
- let mut am1d=Integer::from(0);
- let mut prime=0u64;
- let mut psp=0u64;
- for _i in 0..5000000{
- prime+={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==1{break}else if b==am1{f=true;break}
- }
- f
- }
- } as u64;
- a+=2;
- am1+=2;
- }
- println!("{},{},{:?}",a,prime-psp,now.elapsed());
- }
- */
- use rug::{Assign, Integer};
- 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 mut a=Integer::from(10000000000000000000000000001u128);
- let mut am1=Integer::from(10000000000000000000000000000u128);
- let mut b=Integer::from(2);
- let mut am1d=Integer::from(0);
- let mut prime=0u64;
- let mut psp=0u64;
- for _i in 0..50000000{
- let aa=am1.find_one(0).unwrap().min(6);
- am1d.assign(&am1>>aa);
- if {b.assign(CONSTARR[aa as usize]);let _=b.pow_mod_mut(&am1d,&a);b==1u8}{//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,prime-psp,now.elapsed());
- }
复制代码 不知道为什么,Rust快到没朋友
(我这几个小时一直在Rust慢得怀疑人生和Rust快得没朋友之间徘徊)
另,这是Rust比Julia快的地方,只要你的Julia版本高于0.6,请务必执行
- chmod 644 ~/.julia/packages/Primes/eRBAQ/src/Primes.jl
- sed -i 's/(Any, Cint)/(Ref{BigInt}, Cint)/g' ~/.julia/packages/Primes/eRBAQ/src/Primes.jl
- chmod 444 ~/.julia/packages/Primes/eRBAQ/src/Primes.jl
复制代码 我也不知道为什么能从30s直接变成11s
或许这就是人生吧
最终测速结果:
11.642703 seconds (63.51 M allocations: 1.428 GiB, 5.59% gc time)
(只算Fermat 9.297450 seconds (59.88 M allocations: 1.007 GiB, 7.64% gc time))
Rust
10000000000000000000100000001.1552676,0,82.901862532s
(搜了前10^8个数字一个PSP都没有真的没问题吗?)
|
|