profiling2026

Word-size primality test and factoring (Fredrik)

Pari used to be much better than FLINT for primality testing and factoring word-size integers at least in some input ranges. After some recent optimizations I’ve made to FLINT, I expect that this should no longer be the case, and I’ve done some quick benchmarking to verify this. Average time in seconds for 100000 random inputs of each bit size:

          isprime                     factorint

bits    pari    flint    ratio      pari     flint   ratio
-----------------------------------------------------------
  2  1.27e-08  4.40e-09  2.89x    2.46e-08  5.42e-09  4.53x
  3  1.33e-08  4.37e-09  3.04x    3.58e-08  6.71e-09  5.33x
  4  1.43e-08  4.38e-09  3.26x    4.45e-08  8.45e-09  5.26x
  5  1.43e-08  4.37e-09  3.28x    4.98e-08  9.16e-09  5.44x
  6  1.51e-08  4.37e-09  3.47x    5.47e-08  1.04e-08  5.26x
  7  1.60e-08  4.38e-09  3.66x    5.94e-08  1.22e-08  4.87x
  8  1.68e-08  4.36e-09  3.84x    6.36e-08  1.37e-08  4.65x
  9  1.72e-08  4.39e-09  3.92x    6.82e-08  1.47e-08  4.64x
 10  1.87e-08  4.39e-09  4.25x    7.27e-08  1.58e-08  4.60x
 11  1.93e-08  4.37e-09  4.41x    7.88e-08  1.68e-08  4.69x
 12  2.03e-08  4.38e-09  4.63x    8.45e-08  1.79e-08  4.72x
 13  2.14e-08  4.39e-09  4.89x    9.06e-08  1.88e-08  4.82x
 14  2.29e-08  4.39e-09  5.22x    9.62e-08  1.96e-08  4.91x
 15  2.48e-08  4.39e-09  5.65x    1.05e-07  2.05e-08  5.10x
 16  2.90e-08  5.65e-09  5.13x    1.14e-07  2.30e-08  4.94x
 17  2.62e-08  5.65e-09  4.64x    1.27e-07  2.65e-08  4.81x
 18  2.39e-08  5.69e-09  4.19x    1.38e-07  2.83e-08  4.89x
 19  2.51e-08  5.67e-09  4.43x    1.57e-07  3.04e-08  5.17x
 20  2.72e-08  5.65e-09  4.81x    1.77e-07  3.29e-08  5.38x
 21  2.80e-08  1.46e-08  1.91x    1.99e-07  4.09e-08  4.87x
 22  2.88e-08  1.51e-08  1.91x    2.18e-07  4.79e-08  4.56x
 23  2.93e-08  1.54e-08  1.90x    2.38e-07  5.52e-08  4.31x
 24  3.05e-08  1.59e-08  1.92x    2.59e-07  6.31e-08  4.10x
 25  3.07e-08  1.63e-08  1.88x    2.97e-07  7.18e-08  4.13x
 26  3.15e-08  1.68e-08  1.87x    3.35e-07  8.13e-08  4.12x
 27  3.22e-08  1.73e-08  1.86x    3.75e-07  9.15e-08  4.10x
 28  3.26e-08  1.76e-08  1.85x    4.26e-07  1.03e-07  4.14x
 29  3.34e-08  1.82e-08  1.84x    4.89e-07  1.17e-07  4.18x
 30  3.41e-08  1.85e-08  1.84x    5.64e-07  1.31e-07  4.31x
 31  3.80e-08  1.89e-08  2.01x    6.61e-07  1.48e-07  4.46x
 32  4.02e-08  1.97e-08  2.04x    7.71e-07  1.69e-07  4.56x
 33  5.11e-08  2.42e-08  2.11x    9.08e-07  1.99e-07  4.56x
 34  5.78e-08  2.44e-08  2.37x    1.08e-06  2.37e-07  4.55x
 35  6.19e-08  2.45e-08  2.53x    1.25e-06  2.75e-07  4.56x
 36  6.34e-08  2.49e-08  2.55x    1.51e-06  3.32e-07  4.56x
 37  6.45e-08  2.52e-08  2.56x    1.72e-06  3.92e-07  4.39x
 38  6.62e-08  2.55e-08  2.60x    2.04e-06  4.62e-07  4.41x
 39  6.48e-08  2.57e-08  2.52x    2.39e-06  5.47e-07  4.37x
 40  6.37e-08  2.59e-08  2.46x    2.88e-06  6.38e-07  4.51x
 41  6.42e-08  2.64e-08  2.43x    3.37e-06  7.53e-07  4.47x
 42  6.43e-08  2.71e-08  2.37x    4.02e-06  8.73e-07  4.61x
 43  6.44e-08  2.69e-08  2.39x    4.78e-06  1.03e-06  4.64x
 44  6.48e-08  2.74e-08  2.37x    5.77e-06  1.20e-06  4.81x
 45  6.63e-08  2.76e-08  2.40x    6.77e-06  1.35e-06  5.02x
 46  6.73e-08  2.82e-08  2.39x    8.09e-06  1.54e-06  5.25x
 47  6.76e-08  2.80e-08  2.41x    9.27e-06  1.74e-06  5.33x
 48  6.98e-08  2.83e-08  2.47x    1.02e-05  1.94e-06  5.25x
 49  7.00e-08  2.87e-08  2.44x    1.14e-05  2.17e-06  5.23x
 50  7.09e-08  2.89e-08  2.45x    1.26e-05  2.45e-06  5.14x
 51  7.22e-08  2.92e-08  2.47x    1.38e-05  2.72e-06  5.07x
 52  7.26e-08  2.99e-08  2.43x    1.51e-05  3.05e-06  4.96x
 53  7.30e-08  3.02e-08  2.42x    1.66e-05  3.40e-06  4.89x
 54  7.48e-08  3.05e-08  2.45x    1.83e-05  3.78e-06  4.83x
 55  7.59e-08  3.08e-08  2.46x    1.98e-05  4.22e-06  4.69x
 56  7.66e-08  3.11e-08  2.46x    2.15e-05  4.70e-06  4.58x
 57  7.75e-08  3.14e-08  2.47x    2.36e-05  5.19e-06  4.55x
 58  7.86e-08  3.15e-08  2.50x    2.56e-05  5.83e-06  4.38x
 59  8.04e-08  3.13e-08  2.57x    2.79e-05  6.52e-06  4.28x
 60  8.00e-08  3.26e-08  2.45x    3.00e-05  7.36e-06  4.08x
 61  8.11e-08  3.25e-08  2.49x    3.29e-05  8.28e-06  3.97x
 62  8.25e-08  3.28e-08  2.51x    3.51e-05  9.25e-06  3.80x
 63  8.50e-08  3.69e-08  2.30x    3.78e-05  1.07e-05  3.54x
 64  8.54e-08  3.75e-08  2.28x    4.11e-05  1.23e-05  3.34x

Here are the main tricks currently used in FLINT, some of which would make sense to implement in Pari too where they are not already used.

Primality testing:

  • Static bitmap mod 2 up to 15 bits, mod 30 up to 20 bits
  • Trial division by a handful of small fixed primes
  • Between 21 and 32 bits, use a single base-2 test and catch all passing composites with a hash table
  • Modular arithmetic up to 32 bits uses Shoup modular reduction
  • Between 33 and 64 bits, use a base-2 test, then a single extra base strong probable prime test with a base chosen from a hash table to guarantee catching all remaining composites
  • Modular arithmetic up to 64 bits uses Montgomery reduction

Factoring:

  • Trial division uses exactly the 16-bit primes. Divisibility testing is done by multiplying by precomputed inverses mod 2^64
  • A primality test is done at a strategically chosen point in the middle of trial division
  • Between 33 and 38 bits, try Hart’s one line factor algorithm with SQUFOF as a fallback (in practice SQUFOF is never needed)
  • Between 39 and 64 bits, try one run of Pollard-Brent (succeeds in 99.9% of cases), then one line factor, then SQUFOF as a fallback
  • Pollard-Brent uses Montgomery arithmetic
  • Primality testing (of the input as well as partial factors) skips trial division