diff options
| author | Paul Duncan <pabs@pablotron.org> | 2026-01-02 18:08:01 -0500 |
|---|---|---|
| committer | Paul Duncan <pabs@pablotron.org> | 2026-01-02 18:08:01 -0500 |
| commit | 512a56da63a22839bd5828964d0fc4ba7af77832 (patch) | |
| tree | 7daa7f7be78ea0d237c0565113078bfcf78b2dcc | |
| parent | 2b7b25f9b3deea10f44136764da00e65f491eed7 (diff) | |
| download | pablotron.org-512a56da63a22839bd5828964d0fc4ba7af77832.tar.xz pablotron.org-512a56da63a22839bd5828964d0fc4ba7af77832.zip | |
content/posts: add drafts
| -rw-r--r-- | content/posts/2025-11-30-faster-ml-kem-barrett-reduction.md | 47 | ||||
| -rw-r--r-- | content/posts/2026-01-02-new-years-primality-testing-by-hand.md | 99 |
2 files changed, 146 insertions, 0 deletions
diff --git a/content/posts/2025-11-30-faster-ml-kem-barrett-reduction.md b/content/posts/2025-11-30-faster-ml-kem-barrett-reduction.md new file mode 100644 index 0000000..c9a50c6 --- /dev/null +++ b/content/posts/2025-11-30-faster-ml-kem-barrett-reduction.md @@ -0,0 +1,47 @@ +--- +slug: faster-ml-kem-barrett-reduction +title: "Faster ML-KEM Barrett Reduction" +date: "2025-11-30T09:35:07-05:00" +draft: true +--- + +changes: + +1. `b` is a constant `1` (common trick) +2. change `(a*((2^k)/n))>>k` to `((a>>12)*((1<<k)/n))>>(k-12)` so + numerator product fits in `u32` +3. change mul by 3329 to three shifts and 3 adds (proth prime) + +```ruby +# good: +# numerator product fits in u32 +(((3000*3329)>>12)*((1<<31)/3329))>>19 +=> 2999 + +# constant fits in u20 +>> Math.log((1<<31)/3329, 2).ceil +=> 20 + +# better: +# numerator operands both fit in u16; product fits in u32 +>> (((3000*3329)>>12)*((1<<27)/3329))>>15 +=> 2999 + +# constant fits in u16 +>> Math.log((1<<27)/3329, 2).ceil +=> 16 + +>> (((1000*3329)>>11)*((1<<27)/3329))>>16 +=> 999 +>> Math.log((1<<27)/3329, 2) +=> 15.299100671012633 +>> Math.log((1<<28)/3329, 2) +=> 16.299118562796433 + +# check subset of +>> (0...3329).each.map { |x| t = (x*3329+x) - 3329*((((x*3329)>>11)*((1<<27)/3329))>>16); { x: x, y: t - (t<3329 ? 0 : 3329), z: (x*3329+x) % 3329 } }.select { |row| row[:y] != row[:z] } +=> [] + +ct_mod5_,,, from pt-mldsa + +``` diff --git a/content/posts/2026-01-02-new-years-primality-testing-by-hand.md b/content/posts/2026-01-02-new-years-primality-testing-by-hand.md new file mode 100644 index 0000000..00c13da --- /dev/null +++ b/content/posts/2026-01-02-new-years-primality-testing-by-hand.md @@ -0,0 +1,99 @@ +--- +slug: new-years-primality-testing-by-hand +title: "New Year's Primality Testing by Hand" +date: "2026-01-02T09:37:22-05:00" +draft: true +--- + +Happy New Year! + +The number 2026 has two factors: 2 and 1013. I wondered "is 1013 +prime?" and "for fun, can I solve this in my head?" (e.g. no calculator, +computer, or pen and paper). + +If 1013 is *not* prime, then it is composite and must have at least one +odd prime factor ≤ ⌊√1013⌋. + +(We know the factor -- if it exists -- is odd because the factors of odd +composite numbers are always odd, and we know the factor is prime +because of the [fundamental theorem of arithmetic][]). + +So our approach will be to check the odd primes from 3 to √1013 to +see if any are a factor of 1013. + +Unfortunately we don't know √1013, so we can't calculate the range +upper bound. Fortunately 1013 is close to 1024. 1024 is a handy power +of 2, so lets use that instead: + +2. √1024 = √(2{{<sup 10>}}) = 2{{<sup 5>}} = 32 +3. 1013 < 1024, so √1013 < √1024 +4. Therefore, √1013 < 32 + +So we need to test the odd primes in the range \[3,31\] to see if any +are a factor of 1013. + +Before that, though, we narrow the list with the [divisibility rules][]: + +1. Remove 3 because the sum of the digits of 1013 isn't divisible by 3: + `1+1+3=5` and 3∤5 +2. Remove 5 because the last digit of 1013 isn't 0 or 5. +3. Remove 7 because 5 times the last digit (3) plus the rest (101) is + not a multiple of 7: `5*3+101=116, 5*6+11=41`, and 7∤41. +4. ...and so on for [11][], [13][], [17][], [19][], [23][], and [29][]. + +(Full disclosure: I don't have the [divisibility rules][] for primes in +the range \[11,29\] memorized; instead I checked to see if they were +factors of 1013). + +The only remaining possibility is 31. To check it, we can use the +[Euclidean algorithm][] to check if `gcd(31, 1013) != 1` or do some +brief arithmetic. I chose the latter: + +1. 31 = (30 + 1) +2. (30 + 1) * 33 = 990 + 33 = 1023 +3. The closest multiples of 31 are 992 and 1023, so 31∤1013. + +1013 does not have any odd prime factors in the range \[3,√1013\], +so it must be prime. + +Let's check our work: + +```python +>>> import sympy +>>> sympy.ntheory.primetest.isprime(1013) +True +``` +... + +Success! + +Further reading: + +- [Integer factorization][] +- [Primality test][] +- [Sieve of Eratosthenes][] + +[fundamental theorem of arithmetic]: https://en.wikipedia.org/wiki/Fundamental_theorem_of_arithmetic + "Fundamental Theorem of Arithmetic" +[divisibility rules]: https://en.wikipedia.org/wiki/Divisibility_rule + "shorthand rules for determining if a number is factor of another number without performing division" +[11]: https://en.wikipedia.org/wiki/Divisibility_rule#11 + "divisibility rules for 11" +[13]: https://en.wikipedia.org/wiki/Divisibility_rule#13 + "divisibility rules for 13" +[17]: https://en.wikipedia.org/wiki/Divisibility_rule#17 + "divisibility rules for 17" +[19]: https://en.wikipedia.org/wiki/Divisibility_rule#19 + "divisibility rules for 19" +[23]: https://en.wikipedia.org/wiki/Divisibility_rule#23 + "divisibility rules for 23" +[29]: https://en.wikipedia.org/wiki/Divisibility_rule#29 + "divisibility rules for 29" +[euclidean algorithm]: https://en.wikipedia.org/wiki/Euclidean_algorithm + "Euclidean Algorithm" +[integer factorization]: https://en.wikipedia.org/wiki/Integer_factorization + "Integer factorization" +[primality test]: https://en.wikipedia.org/wiki/Primality_test + "Primality test" +[sieve of eratosthenes]: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes + "Sieve of Eratosthenes" |
