feat: add repunit theorem helpers#1892
feat: add repunit theorem helpers#1892nickzerjeski wants to merge 4 commits intoTheAlgorithms:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds repunit theorem–related utilities to the Maths module, enabling theorem-based divisibility checks and modular computations for repunits without constructing large integers.
Changes:
- Introduces
multiplicativeOrder10,repunitMod, andisRepunitDivisibleByPrimeinMaths/RepunitTheorem.js. - Adds Jest tests covering example orders, theorem-based divisibility cases, and repunit modulo computations.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| Maths/RepunitTheorem.js | Implements BigInt-based helpers for multiplicative order, repunit modulo, and a theorem-based divisibility check. |
| Maths/test/RepunitTheorem.test.js | Adds unit tests for the new repunit theorem helpers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const isRepunitDivisibleByPrime = (length, prime) => { | ||
| if (!Number.isInteger(length) || length < 1) { | ||
| throw new RangeError('length must be a positive integer') | ||
| } | ||
|
|
||
| const p = BigInt(prime) | ||
| if (p === 2n || p === 5n) return false | ||
| if (gcd(10n, p) !== 1n) return false | ||
|
|
||
| const order = multiplicativeOrder10(p) | ||
| return BigInt(length) % order === 0n |
There was a problem hiding this comment.
The stated divisibility criterion and current implementation fail for p = 3. Since gcd(9,3) != 1, “ord_p(10) divides n” is not equivalent to 3 | R_n (e.g., length=1 would incorrectly return true because ord_3(10)=1). Handle p===3n explicitly (R_n mod 3 == n mod 3) and/or update the theorem condition to require p not dividing 9 (i.e., exclude p=3).
| /** | ||
| * Repunit theorem helpers. | ||
| * | ||
| * A repunit of length n is: | ||
| * R_n = (10^n - 1) / 9 | ||
| * | ||
| * For a prime p (p != 2, 5), p divides R_n iff ord_p(10) divides n. | ||
| * Reference: https://en.wikipedia.org/wiki/Repunit | ||
| */ |
There was a problem hiding this comment.
The file header comment says the theorem holds for primes p != 2,5, but it also needs p != 3 (equivalently gcd(p,9)=1). As written, it documents an incorrect condition and matches the buggy behavior for p=3.
| // For prime p, ord_p(10) divides p-1. | ||
| const upper = p - 1n | ||
| for (let k = 1n; k <= upper; k++) { | ||
| if (upper % k === 0n && modPow(10n, k, p) === 1n) { | ||
| return k | ||
| } | ||
| } |
There was a problem hiding this comment.
multiplicativeOrder10 currently checks every k from 1..p-1 and runs modPow for each divisor check, which is O(p log p) and will be extremely slow for larger primes. Consider iterating only divisors of (p-1) (e.g., enumerate divisors up to sqrt(p-1) or factor p-1 and test candidate orders by reducing factors) to keep runtime practical.
| it('checks repunit divisibility using the theorem', () => { | ||
| // 111111 is divisible by 3, 7, 11, 13, 37 | ||
| expect(isRepunitDivisibleByPrime(6, 3n)).toBe(true) | ||
| expect(isRepunitDivisibleByPrime(6, 7n)).toBe(true) | ||
| expect(isRepunitDivisibleByPrime(6, 11n)).toBe(true) | ||
| expect(isRepunitDivisibleByPrime(6, 13n)).toBe(true) | ||
| expect(isRepunitDivisibleByPrime(6, 37n)).toBe(true) | ||
| }) | ||
|
|
||
| it('returns false when divisibility condition does not hold', () => { | ||
| expect(isRepunitDivisibleByPrime(6, 19n)).toBe(false) | ||
| expect(isRepunitDivisibleByPrime(9, 2n)).toBe(false) | ||
| expect(isRepunitDivisibleByPrime(9, 5n)).toBe(false) | ||
| }) |
There was a problem hiding this comment.
Add an explicit test case for p=3 (e.g., length=1 should be false and length=3 should be true). The current tests only cover a length (6) where 3 happens to divide the repunit, so they won’t catch the p=3 edge case where the theorem-based check is incorrect.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1892 +/- ##
==========================================
+ Coverage 85.91% 85.95% +0.04%
==========================================
Files 379 380 +1
Lines 19778 19857 +79
Branches 3016 3043 +27
==========================================
+ Hits 16993 17069 +76
- Misses 2785 2788 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Describe your change:
Added repunit theorem utilities in
Maths/RepunitTheorem.js:Checklist:
Fixes: #{$ISSUE_NO}.Tests
npm test -- RepunitTheorem