Lucas primality test
This Lucas primality test checker turns a compact mathematical certificate into a reproducible primality result.
Run — free
Supply an odd integer n, a proposed Lucas witness, and the complete prime factorization of n minus one. The calculator validates the factorization itself, evaluates the required modular powers and greatest common divisors, and certifies n only when every condition of Lucas's theorem succeeds. Decimal strings preserve exact integers throughout, including values beyond JavaScript's ordinary safe-number range.
Prepare a complete certificate
Start with the odd integer you want to certify and factor n minus one completely. Enter n and every prime factor as a canonical decimal string, because strings preserve exact values all the way to the 64-bit limit. Each factor appears once with its positive exponent. For example, n = 29 has n minus one = 28 = 2 squared times 7, so the factor list contains 2 with exponent 2 and 7 with exponent 1. You must also provide a base a satisfying 1 < a < n. This base is the proposed Lucas witness. The checker deliberately requires the witness instead of searching for one: a certificate verification is fast, bounded, and repeatable, while a search can have an input-dependent running time. If you do not yet have a witness, try small bases with a separate primitive-root tool, then submit the resulting certificate here. Whitespace, signs, leading zeroes, floating-point notation, duplicate primes, composite factors, and missing factors are rejected rather than silently normalized, making the certificate suitable for audit logs and automated pipelines.
Understand the two Lucas conditions
The first calculation checks that a raised to n minus one is congruent to 1 modulo n. This is the familiar Fermat condition, but it cannot establish primality by itself because pseudoprimes can pass it. The decisive second stage uses every distinct prime q dividing n minus one. For each q, the checker computes a raised to (n minus one) divided by q modulo n, subtracts one, and verifies that the result has greatest common divisor 1 with n. Passing all these checks proves that the multiplicative order of a modulo n is exactly n minus one. An element modulo n cannot have that order unless n is prime, which is the core of Lucas's theorem. The returned check records expose the modular residue and gcd for each distinct q, while the exponent remains visible as part of the validated factorization. Modular exponentiation uses repeated squaring with exact BigInt arithmetic, so the calculation never depends on floating-point rounding, random bases, a network service, or probabilistic confidence.
Interpret failures and successful output
A successful response is a primality certificate result, not merely a probable-prime label. It repeats n, identifies the accepted witness, reports the Fermat residue, and lists one successful gcd check for each distinct factor of n minus one. Store the original input alongside this response when another system needs to reproduce the proof. Failures are intentionally specific. If the powered factors do not multiply to n minus one exactly, the factorization is incomplete or otherwise incorrect. If a listed factor is composite, or the same prime appears twice, the factorization is malformed even when its raw product happens to match. A failure of either modular condition means the supplied base is not a Lucas witness; it does not by itself distinguish a composite n from a prime paired with an unsuitable base. Try a mathematically justified alternative witness if primality is still expected. Inputs are limited to odd integers from 3 through 2^64 minus 1, allowing deterministic validation of the listed prime factors before the Lucas certificate is evaluated. The API price is $0.002 per request.
What you can do with it
Verify a generated prime
Check a candidate and its construction-time factorization before using the prime in another exact computation.
Reproduce a certificate
Validate a Lucas witness from a paper, classroom exercise, or archived computation with explicit intermediate residues.
Gate number-theory data
Reject incomplete factorizations and invalid witnesses before admitting claimed primes into a trusted dataset.
FAQ
Does a successful result prove primality?
Yes. When the complete factorization is valid and every Lucas condition passes, the result is a deterministic primality proof for the supplied n.
Why must I supply a base?
The base is the witness carried by the certificate. Requiring it keeps verification bounded and reproducible instead of performing an open-ended primitive-root search.
What if a base fails?
That base is not a valid witness. The candidate may be composite, or it may be prime with a different suitable witness; the failure alone does not decide which.
Why are integers entered as strings?
Decimal strings avoid precision loss for integers larger than JavaScript's safe numeric range. Outputs use strings for the same reason.
How is the factorization checked?
Every listed factor is deterministically tested for primality, duplicates are rejected, and the product of all prime powers must equal n minus one exactly.
What does it cost?
Each API request costs $0.002. The browser implementation uses the same pure calculation.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/numth/lucas-primality-test \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"n":"29","base":"2","factors":[{"prime":"2","exponent":2},{"prime":"7","exponent":1}]}'const res = await fetch("https://api.kit.forhosting.com/numth/lucas-primality-test", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"n": "29",
"base": "2",
"factors": [
{
"prime": "2",
"exponent": 2
},
{
"prime": "7",
"exponent": 1
}
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/numth/lucas-primality-test",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"n": "29",
"base": "2",
"factors": [
{
"prime": "2",
"exponent": 2
},
{
"prime": "7",
"exponent": 1
}
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/numth/lucas-primality-test", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"n":"29","base":"2","factors":[{"prime":"2","exponent":2},{"prime":"7","exponent":1}]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"n":"29","base":"2","factors":[{"prime":"2","exponent":2},{"prime":"7","exponent":1}]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/numth/lucas-primality-test", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"n": "29",
"base": "2",
"factors": [
{
"prime": "2",
"exponent": 2
},
{
"prime": "7",
"exponent": 1
}
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "numth.lucas_primality_test",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_bits | 64 |
max_factors | 64 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |