Skip to content

Instantly share code, notes, and snippets.

@user140242
Last active September 2, 2022 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save user140242/092c8422d854fff41f15f8a67c4f62c5 to your computer and use it in GitHub Desktop.
Save user140242/092c8422d854fff41f15f8a67c4f62c5 to your computer and use it in GitHub Desktop.
Lucas-Lehmer Primality Test
// Lucas-Lehmer Primality Test
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <stdint.h>
const int modulus=30; // example modulus=6,12,18,30
bool ll_test(uint64_t P)
{
// ll test for P>2*modulus return true if 2^P-1 is prime
uint64_t bW=(uint64_t)modulus;
int nR;
std::vector<int> RW; //vectors of the remainders associated with possible classes using (modulo bW)
int i_P=0;
if (P>2*bW)
{
int pt=2;
int pmax;
int d=1;
std::vector<char> Remainder_t(modulus,true);
while (pt*pt<=modulus)
{
if (modulus%pt==0 && Remainder_t[pt]==true)
{
pmax=pt;
for (int j=pt*pt;j< modulus;j+=pt)
Remainder_t[j]=false;
}
pt+=d;
d=2;
}
RW.push_back(1);
for (int j=pmax+1;j< modulus;j++)
if (Remainder_t[j]==true)
RW.push_back(j);
nR=RW.size();
while(P%bW!=RW[i_P] && i_P<nR)
i_P++;
}
else
std::cout<<std::endl<<"Enter P> "<< 2*bW<<std::endl;
if (P>2*bW && i_P<nR)
{
uint64_t bW_mod=(1<<modulus);
std::vector<uint64_t> mod_f(nR,0);
std::vector<uint64_t> coef_f(nR,0);
for (int i=0;i<nR;i++)
{
mod_f[i]=1<<RW[i];
coef_f[i]=1<<RW[nR-1-i];
}
uint64_t dim_v=(P+(uint64_t)RW[nR-1-i_P])/bW;
std::vector<uint64_t> prod_t(dim_v,0);
std::vector<uint64_t> esp_L_i_m2(dim_v+1,0);
std::vector<uint64_t> coef_L_i_m2(dim_v,0);
uint64_t l_m2=1;
esp_L_i_m2[0]=0;
coef_L_i_m2[0]=2; //L_1=S_0-2=2
uint64_t coef_sum,coef_t,esp_t,c_t,i1,j1;
for (uint64_t step=2;step<P;step++)
{
//begin multiplication and partial operation (modulo 2^P-1) - L_i+1 =L_i *L_i +4 *L_i
for (i1=0;i1<l_m2 && 2*esp_L_i_m2[i1]<dim_v;i1++)
{
prod_t[esp_L_i_m2[i1]]+=4*coef_L_i_m2[i1];
c_t=1;
for (j1=i1;j1<l_m2 && (esp_L_i_m2[i1]+esp_L_i_m2[j1])<dim_v-1;j1++)
{
esp_t=esp_L_i_m2[i1]+esp_L_i_m2[j1];
coef_t=(c_t*coef_L_i_m2[i1]*coef_L_i_m2[j1]);
prod_t[esp_t]+=coef_t%bW_mod;
prod_t[esp_t+1]+=coef_t/bW_mod;
c_t=2;
}
if (j1<l_m2 && (esp_L_i_m2[i1]+esp_L_i_m2[j1])==dim_v-1)
{
coef_t=(c_t*coef_L_i_m2[i1]*coef_L_i_m2[j1]);
prod_t[0]+=coef_t/mod_f[i_P];
prod_t[dim_v-1]+= coef_t%mod_f[i_P];
c_t=2;
j1++;
}
for (;j1<l_m2;j1++)
{
esp_t=esp_L_i_m2[i1]+esp_L_i_m2[j1]-dim_v;
coef_t=(c_t*coef_L_i_m2[i1]*coef_L_i_m2[j1]);
prod_t[esp_t]+=(coef_f[i_P]*(coef_t%bW_mod))%bW_mod;
prod_t[esp_t+1]+=coef_f[i_P]*(coef_t/bW_mod)+(coef_f[i_P]*(coef_t%bW_mod))/bW_mod;
c_t=2;
}
}
for (;i1<l_m2;i1++)
{
prod_t[esp_L_i_m2[i1]]+=4*coef_L_i_m2[i1];
c_t=1;
for (j1=i1;j1<l_m2;j1++)
{
esp_t=esp_L_i_m2[i1]+esp_L_i_m2[j1]-dim_v;
coef_t=(c_t*coef_L_i_m2[i1]*coef_L_i_m2[j1]);
prod_t[esp_t]+=(coef_f[i_P]*(coef_t%bW_mod))%bW_mod;
prod_t[esp_t+1]+=coef_f[i_P]*(coef_t/bW_mod)+(coef_f[i_P]*(coef_t%bW_mod))/bW_mod;
c_t=2;
}
}
//end multiplication and partial operation (modulo 2^P-1)
//begin completion of the (modulo 2^P-1) operation
do
{
l_m2=0;
coef_sum=0;
prod_t[0]+=prod_t[dim_v-1]/mod_f[i_P];
prod_t[dim_v-1]%= mod_f[i_P];
for (uint64_t i=1;i<dim_v;i++)
{
prod_t[i]+=prod_t[i-1]/bW_mod;
prod_t[i-1]%=bW_mod;
if (prod_t[i-1]>0)
{
esp_L_i_m2[l_m2]=(i-1);
coef_L_i_m2[l_m2]=prod_t[i-1];
coef_sum+=prod_t[i-1];
l_m2++;
}
}
if (prod_t[dim_v-1]>0 && prod_t[dim_v-1]<mod_f[i_P])
{
esp_L_i_m2[l_m2]=dim_v-1;
coef_L_i_m2[l_m2]=prod_t[dim_v-1];
l_m2++;
}
}
while (prod_t[dim_v-1]>=mod_f[i_P]);
//end completion of the (modulo 2^P-1) operation
std::fill(prod_t.begin(), prod_t.end(), 0);
}
if (l_m2==dim_v)
{
if ( coef_sum==((bW_mod-1)*dim_v-bW_mod-1) && coef_L_i_m2[0]==bW_mod-3 && coef_L_i_m2[dim_v-1]==mod_f[i_P]-1)
return true;
}
}
return false;
}
int main()
{
// ll_test(P) -- ll test for P>2*modulus
std::cout <<"ll test (1 prime, 0 composite): "<< ll_test(607)<< std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment