Lucas Primality Test (original) (raw)

Last Updated : 29 Jul, 2022

A number p greater than one is prime if and only if the only divisors of p are 1 and p. First few prime numbers are 2, 3, 5, 7, 11, 13, ...
The Lucas test is a primality test for a natural number n, it can test primality of any kind of number.
It follows from Fermat’s Little Theorem: If p is prime and a is an integer, then a^p is congruent to a (mod p )

Lucas’ Test : A positive number n
is prime if there exists an integer a (1 < a < n) such that :

a^{{n-1}}\ \equiv \ 1{\pmod n}

And for every prime factor q of (n-1),

a^{{({n-1})/q}}\ \not \equiv \ 1{\pmod n}

Examples :

Input : n = 7 Output : 7 is Prime Explanation : let's take a = 3, then 3^6 % 7 = 729 % 7 = 1 (1st condition satisfied). Prime factors of 6 are 2 and 3, 3^(6/2) % 7 = 3^3 % 7 = 27 % 7 = 6 3^(6/3) % 7 = 3^2 % 7 = 9 % 7 = 2 Hence, 7 is Prime

Input : n = 9 Output : 9 is composite Explanation : Let's take a = 2, then 2^8 % 9 = 256 % 9 = 4 Hence 9 is composite

lucasTest(n): If n is even return composite Else Find all prime factors of n-1 for i=2 to n-1 pick 'a' randomly in range [2, n-1] if a^(n-1) % n not equal 1: return composite else // for all q, prime factors of (n-1) if a^(n-1)/q % n not equal 1 return prime Return probably prime

Problems Associated with Lucas's test are :

// C++ Program for Lucas Primality Test #include <bits/stdc++.h> using namespace std;

// function to generate prime factors of n void primeFactors(int n, vector& factors) { // if 2 is a factor if (n % 2 == 0) factors.push_back(2); while (n % 2 == 0) n = n / 2;

// if prime > 2 is factor 
for (int i = 3; i <= sqrt(n); i += 2) { 
    if (n % i == 0) 
        factors.push_back(i); 
    while (n % i == 0) 
        n = n / i; 
} 
if (n > 2) 
factors.push_back(n); 

}

// this function produces power modulo // some number. It can be optimized to // using int power(int n, int r, int q) { int total = n; for (int i = 1; i < r; i++) total = (total * n) % q; return total; }

string lucasTest(int n) { // Base cases if (n == 1) return "neither prime nor composite"; if (n == 2) return "prime"; if (n % 2 == 0) return "composite1";

// Generating and storing factors 
// of n-1 
vector<int> factors; 
primeFactors(n - 1, factors); 

// Array for random generator. This array 
// is to ensure one number is generated 
// only once 
int random[n - 3]; 
for (int i = 0; i < n - 2; i++) 
    random[i] = i + 2; 
    
// shuffle random array to produce randomness 
shuffle(random, random + n - 3, 
        default_random_engine(time(0))); 

// Now one by one perform Lucas Primality 
// Test on random numbers generated. 
for (int i = 0; i < n - 2; i++) { 
    int a = random[i]; 
    if (power(a, n - 1, n) != 1) 
        return "composite"; 

    // this is to check if every factor 
    // of n-1 satisfy the condition 
    bool flag = true; 
    for (int k = 0; k < factors.size(); k++) { 
        // if a^((n-1)/q) equal 1 
        if (power(a, (n - 1) / factors[k], n) == 1) { 
            flag = false; 
            break; 
        } 
    } 

    // if all condition satisfy 
    if (flag) 
        return "prime"; 
} 
return "probably composite"; 

}

// Driver code int main() { cout << 7 << " is " << lucasTest(7) << endl; cout << 9 << " is " << lucasTest(9) << endl; cout << 37 << " is " << lucasTest(37) << endl; return 0; }

Java

// Java Program for Lucas Primality Test import java.util.*;

class GFG { static ArrayList factors = new ArrayList();

// function to generate prime factors of n
static ArrayList<Integer> primeFactors(int n)
{
    // if 2 is a factor
    if (n % 2 == 0)
        factors.add(2);
    while (n % 2 == 0)
        n = n / 2;

    // if prime > 2 is factor
    for (int i = 3; i <= Math.sqrt(n); i += 2) {
        if (n % i == 0)
            factors.add(i);
        while (n % i == 0)
            n = n / i;
    }
    if (n > 2)
        factors.add(n);
    return factors;
}

// this function produces power modulo
// some number. It can be optimized to
// using
static int power(int n, int r, int q)
{
    int total = n;
    for (int i = 1; i < r; i++)
        total = (total * n) % q;
    return total;
}

static String lucasTest(int n)
{
    // Base cases
    if (n == 1)
        return "neither prime nor composite";
    if (n == 2)
        return "prime";
    if (n % 2 == 0)
        return "composite1";

    // Generating and storing factors
    // of n-1
    primeFactors(n - 1);

    // Array for random generator. This array
    // is to ensure one number is generated
    // only once
    int[] random = new int[n - 2];
    for (int i = 0; i < n - 2; i++)
        random[i] = i + 2;

    // shuffle random array to produce randomness
    Collections.shuffle(Arrays.asList(random));

    // Now one by one perform Lucas Primality
    // Test on random numbers generated.
    for (int i = 0; i < n - 2; i++) {
        int a = random[i];
        if (power(a, n - 1, n) != 1)
            return "composite";

        // this is to check if every factor
        // of n-1 satisfy the condition
        boolean flag = true;
        for (i = 0; i < factors.size(); i++) {
            // if a^((n-1)/q) equal 1
            if (power(a, (n - 1) / factors.get(i), n) == 1) {
                flag = false;
                break;
            }
        }

        // if all condition satisfy
        if (flag)
            return "prime";
    }
    return "probably composite";
}

// Driver code
public static void main(String[] args)
{
    System.out.println(7 + " is " + lucasTest(7));
    System.out.println(9 + " is " + lucasTest(9));
    System.out.println(37 + " is " + lucasTest(37));
}

}

// This code is contributed by phasing17

Python3

Python3 program for Lucas Primality Test

import random import math

Function to generate prime factors of n

def primeFactors(n, factors):

# If 2 is a factor
if (n % 2 == 0):
    factors.append(2)
    
while (n % 2 == 0):
    n = n // 2
    
# If prime > 2 is factor
for i in range(3, int(math.sqrt(n)) + 1, 2):
    if (n % i == 0):
        factors.append(i)
        
    while (n % i == 0):
        n = n // i
        
if (n > 2):
    factors.append(n)
    
return factors

This function produces power modulo

some number. It can be optimized to

using

def power(n, r, q):

total = n

for i in range(1, r):
    total = (total * n) % q
    
return total

def lucasTest(n):

# Base cases 
if (n == 1):
    return "neither prime nor composite"
if (n == 2):
    return "prime"
if (n % 2 == 0):
    return "composite1"
     
# Generating and storing factors 
# of n-1
factors = []

factors = primeFactors(n - 1, factors)

# Array for random generator. This array 
# is to ensure one number is generated 
# only once
rand = [i + 2 for i in range(n - 3)]
     
# Shuffle random array to produce randomness
random.shuffle(rand)

# Now one by one perform Lucas Primality
# Test on random numbers generated.
for i in range(n - 2):
    a = rand[i] 
    
    if (power(a, n - 1, n) != 1):
        return "composite"

    # This is to check if every factor 
    # of n-1 satisfy the condition
    flag = True
    
    for k in range(len(factors)):
        
        # If a^((n-1)/q) equal 1
        if (power(a, (n - 1) // factors[k], n) == 1):
            flag = False
            break

    # If all condition satisfy
    if (flag):
        return "prime"

return "probably composite"

Driver code

if name=="main":

print(str(7) + " is " + lucasTest(7))
print(str(9) + " is " + lucasTest(9))
print(str(37) + " is " + lucasTest(37))

This code is contributed by rutvik_56

C#

// C# Program for Lucas Primality Test

using System; using System.Linq; using System.Collections.Generic;

class GFG { static List factors = new List(); // function to generate prime factors of n static List primeFactors(int n) { // if 2 is a factor if (n % 2 == 0) factors.Add(2); while (n % 2 == 0) n = n / 2;

    // if prime > 2 is factor 
    for (int i = 3; i <= Math.Sqrt(n); i += 2) { 
        if (n % i == 0) 
            factors.Add(i); 
        while (n % i == 0) 
            n = n / i; 
    } 
    if (n > 2) 
    factors.Add(n);
    return factors;
} 

// this function produces power modulo 
// some number. It can be optimized to 
// using 
static int power(int n, int r, int q) 
{ 
    int total = n; 
    for (int i = 1; i < r; i++) 
        total = (total * n) % q; 
    return total; 
} 

static string lucasTest(int n) 
{ 
    // Base cases 
    if (n == 1) 
        return "neither prime nor composite"; 
    if (n == 2) 
        return "prime"; 
    if (n % 2 == 0) 
        return "composite1"; 
        
        
    // Generating and storing factors 
    // of n-1 
    primeFactors(n - 1);

    // Array for random generator. This array 
    // is to ensure one number is generated 
    // only once 
    int[] random = new int[n - 2]; 
    for (int i = 0; i < n - 2; i++) 
        random[i] = i + 2; 
        
    // shuffle random array to produce randomness
    Random rand = new Random();
    random = random.OrderBy(x => rand.Next()).ToArray();

    // Now one by one perform Lucas Primality 
    // Test on random numbers generated. 
    for (int i = 0; i < n - 2; i++) { 
        int a = random[i]; 
        if (power(a, n - 1, n) != 1) 
            return "composite"; 

        // this is to check if every factor 
        // of n-1 satisfy the condition 
        bool flag = true; 
        foreach (var factor in factors) { 
            // if a^((n-1)/q) equal 1 
            if (power(a, (n - 1) / factor, n) == 1) { 
                flag = false; 
                break; 
            } 
        } 

        // if all condition satisfy 
        if (flag) 
            return "prime"; 
    } 
    return "probably composite"; 
} 

// Driver code 
public static void Main(string[] args) 
{ 
    Console.WriteLine(7 + " is " + lucasTest(7));
    Console.WriteLine(9 + " is " + lucasTest(9));
    Console.WriteLine(37 + " is " + lucasTest(37));
} 

}

// This code is contributed by phasing17

JavaScript

// JavaScript Program for Lucas Primality Test

// A function to shuffle the array. function shuffle(arr){ for(let i = arr.length-1; i>0;i--){ // have a random index from [0, arr.length-1] let j = Math.floor(Math.random() * (i+1));

    // swap the original and random index element
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}
return arr;

}

// function to generate prime factors of n function primeFactors(n, factors) { // if 2 is a factor if (n % 2 == 0){ factors.push(2); }

while (n % 2 == 0){
    n = n / 2; 
}
            
// if prime > 2 is factor 
for (let i = 3; i <= Math.sqrt(n); i += 2) { 
    if (n % i == 0){
        factors.push(i); 
    }
        
    while (n % i == 0){
        n = n / i; 
    }         
} 
if (n > 2){
    factors.push(n); 
}  

}

// this function produces power modulo // some number. It can be optimized to // using function power(n, r, q) { let total = n; for (let i = 1; i < r; i++){ total = (total * n) % q; }
return total; }

function lucasTest(n) {

// Base cases 
if (n == 1){
    return "neither prime nor composite"; 
}      
if (n == 2){
   return "prime";  
}      
if (n % 2 == 0){
    return "composite1"; 
}
           
// Generating and storing factors 
// of n-1 
const factors = [];
primeFactors(n - 1, factors); 

// Array for random generator. This array 
// is to ensure one number is generated 
// only once 
const random = [];
for (let i = 0; i < n - 2; i++){
    // random[i] = i + 2; 
    random.push(i+2);
}
    
// shuffle random array to produce randomness 
shuffle(random); 

// Now one by one perform Lucas Primality 
// Test on random numbers generated. 
for (let i = 0; i < n - 2; i++) { 
    let a = random[i]; 
    if (power(a, n - 1, n) != 1){
        return "composite";       
    }
        
    // this is to check if every factor 
    // of n-1 satisfy the condition 
    let flag = true; 
    for (let k = 0; k < factors.length; k++) { 
        // if a^((n-1)/q) equal 1 
        if (power(a, (n - 1) / factors[k], n) == 1) { 
            flag = false; 
            break; 
        } 
    } 

    // if all condition satisfy 
    if (flag){
        return "prime"; 
    }
        
} 
return "probably composite"; 

}

// Driver code { console.log( 7 + " is " + lucasTest(7)); console.log( 9 + " is " + lucasTest(9)); console.log( 37 + " is " + lucasTest(37)); return 0; }

// The code is contributed by Gautam goel (gautamgoel962) JavaScript

`

Output:

7 is prime 9 is composite 37 is prime

Time Complexity: O(nlogn)

Auxiliary Space: O(n)

This method is quite complicated and inefficient as compared to other primality tests. And the main problems are factors of ‘n-1’ and choosing appropriate ‘a’.

Other Primality tests: