Here are some short term objectives:

  - Check tifa_cofactor() on real cofactors from a number field sieve (dumps
    from CADO-NFS, for example). So far it has only been measured on
    synthetic cofactors: integers without small factors, of the sizes a
    sieve leaves.

  - Machine-specific parameters. The defaults of SIQS from 160 to 220 bits
    were retuned on an Apple M5 Pro and on GitHub's x86-64 runners (0.4.3);
    sweeping the factor base, the sieve width and the threshold on both, in
    November 2026, found them within 2% of the best everywhere, the machines
    disagreeing on the rest (a larger factor base at 190 bits on x86-64, a
    smaller one at 210). Tuning files (tifa-tune) can take that last 2% to
    3% on each machine. From 232 bits the defaults come from a fit on rows
    tuned on the M5 at 272 and 288 bits, their sieve half widths halved from
    248 to 280 bits for the M5 and the newer x86-64 cores; an EPYC 7763
    (Zen 3) was up to 9% faster with twice as wide ones from 264 bits, for a
    reason not known (its 512 KB L2 cache?). tifa-tune --search descent
    --fit tunes these sizes on a machine.

  - SIQS above 288 bits: the factor base stops at 65536 primes (16-bit
    indices, in the bucket entries too), reached at 288 bits, and its
    parameters are fitted, not tuned, above 288. Block Lanczos (November
    2026) took away the dense matrix of the elimination (530 MB at 65536
    primes), the other limit. Above 320 bits, tifa_factor() searches with
    ECM alone, up to factors of ecm_max_bits bits (85 by default, about 12
    minutes at 520 bits and 30 at 1024 when it finds nothing, 100 at most),
    then gives FACTORS_TOO_LARGE. Larger factors need a faster stage 2 (the
    FFT continuation of GMP-ECM) more than larger bounds.

  - ECM on one to four limbs (mont_ecm.c), measured on 30 October 2026:
      - The setup of a curve takes 0.3 us (Z/2 x Z/8) to 0.6 us (Suyama),
        3% to 6% of a curve with B1 = 50 on two limbs, 1% with B1 = 800;
        its inversion is half of that. ecm() keeps the plans of its levels
        from one call to the next (0.4.2), where building them took 1 to 2
        us each for B1 up to 200 (about 3% at 100 bits).
      - The baby and giant steps of stage 2 are chains of dependent xadd,
        13% of ecm() at 100 bits. As two chains each (steps of 4.P and of
        2.d.P), their xadd in interleaved pairs, ecm() took 0.955 to 0.98
        of its time from 70 to 128 bits on the M5, but 1.04 to 1.23 on
        x86-64 with GCC (Zen 3 and Zen 5): the pairs spill there. Not kept.
        GCC's inlining of add and sub in these kernels also shifts with the
        size of mont_ecm.c: forcing it slowed x86 by 13% to 15% on three
        and four limbs.
      - Not faster: a dedicated Montgomery squaring in the ladder step
        (0.97 to 1.00 of stage 1); two curves interleaved in one step (0.68
        on one limb, whose numbers go to factor_u64 instead, 0.87 to 0.92
        on two, 0.95 to 1.00 on three and four).
      - The levels of ecm_schedule.c (tifa_cofactor, tifa_factor's ECM
        search) were tuned for Suyama's curves; they run the Z/2 x Z/8 ones
        first since November 2026 (1% to 2.4% less work on sets of
        cofactors). Retuned for them (November 2026: mean curves to find a
        factor of exactly fbits bits, starting from curve 0, times the time
        of a curve on two limbs), every level from 25 to 60 bits is
        fastest at half to a third of its B1, 10% to 33% less expected time
        per level. Neither that table nor one keeping each level's time
        with the lower B1 (more curves) helped: on 20000 and 12000
        cofactors, 0.997 to 1.017 of the instructions exactly, and the
        first 1.08 to 1.26 when giving up (it spends more of the budget and
        gives up less); tifa_factor 0.86 to 1.03 over three seeds, within
        the spread of the curves' luck. Failures, bounded by the budget,
        and SIQS dominate these runs, not the levels' expected times.

  - SIQS, in shares of a run (November 2026, after 0.4.4): the sieve's fill
    55% to 75% from 160 to 220 bits, at about one cycle per hit on the M5;
    the bucket fill 15% at 220 bits on the M5, 19% to 20% on x86-64; at 180
    bits, the candidate pre-check and the candidates' values 6%, the batch
    smoothness test 7% to 9% and the trial division of the relations 3% to
    4%; the linear algebra 2% at 220 bits (FILTERED_GAUSS_ELIM).
      - The bucket fill with AVX-512 (0.4.6) compresses each vector of
        hits once per bin: from 225 bits, with 14 chunks per side or more,
        looping over the bins its lanes hit might keep more of its gain.
        Without AVX-512 the fill stays scalar. Bins of their own for the
        second roots, faster in a microbenchmark whose bins stayed in
        cache, were 1% to 3% slower in SIQS: measure such kernels with the
        caches flushed between runs.
      - The candidates the pre-check drops have their values u = a.x + b
        computed for nothing, and the trial division of the relations could
        start from the small primes the pre-check found: 1% to 2% at 180
        bits, perhaps.
      - The code of fill_sieve_chunk is sensitive to its layout on the M5:
        three instructions before its loops moved them and cost 3% at 150
        bits. Time 150 to 160 bits on the M5 after changing it.
      - Not faster: groups of medium primes with AVX2 (no better than SSE2)
        or NEON (slower on the M5); 128 KiB sieve chunks on the M5; testing
        128 bytes at a time in the scan; three-limb lanes in the batch test;
        trial division of every candidate instead of the batch test (1.06 of
        the time at 110 bits, 1.28 at 200), or testing them against the
        roots of their polynomial, four primes per NEON vector (not enough
        to pay for an x86 path); a retune of the parameters (see above);
        with the AVX-512 fill, buckets from 8192 to 32768 rather than 1.5
        chunks (49152), whose profile made them look cheaper per hit than
        the SSE2 groups: 1.00 to 1.03 of the time from 180 to 220 bits on
        two EPYC 9V74, 0.97 to 0.99 at 200 to 220 on an EPYC 9V45 (within
        2% of the noise there).
      - Double large primes (November 2026, a prototype counting the
        relations with two large primes and the cycles they would close, by
        union-find, on single numbers): none come through as SIQS stands,
        since the pre-check drops cofactors above log2(pmax) + 8 bits, and
        two primes above pmax need about twice that. Letting cofactors of up
        to 40 to 50 bits through, with large primes up to 15e6, 2^26 or 2^28,
        the cycles would have ended the run at 0.68 to 0.89 of the time of
        that run, but those runs took 1.5 to 2 times as long (the batch test
        on many more candidates, the splitting), so that the best of them
        would have taken 1.46 times the time of SIQS as it is at 200 bits,
        1.25 at 240, 1.18 at 264. Free candidates, the cycles would cut 25%
        to 32% of the sieving at 240 and 264 bits: double large primes need
        a much cheaper way to the cofactor of a candidate than the batch
        test (resieving, as msieve and yafu do), or larger numbers than
        SIQS takes here. A large prime bound of 2^26 rather than 15e6 alone
        gains 3% at 240 bits, within the noise.
      - For resieving, the bucket entries would carry the prime: position
        << 16 | index in the factor base (both fit in 16 bits) rather than
        position << 8 | log. Looking the log up by index when emptying the
        buckets cost 4% at 220 and 240 bits; a constant log per run of
        primes of the same log (msieve's slices, their ends kept per bin)
        retires fewer instructions than now (0.98 to 1.00), and with the
        loops of siqs_sieve.c aligned on 64 bytes in both builds took 1.00
        to 1.01 of the time from 180 to 240 bits. Unaligned, its place in
        the code made it 1.004 to 1.042; aligning those loops makes the
        current code 1.006 to 1.020 slower, so it is no fix by itself. Not
        done on the AVX-512 fill.
      - Resieving instead of the batch test does not pay either. The batch
        test costs 0.44, 0.67, 1.66 and 2.32 us per candidate at 180, 200,
        220 and 240 bits (3% to 6% of SIQS). Resieving would test some 4600
        primes (those sieved without buckets, from the 40th) against the
        roots of each candidate: 0.23 to 0.28 ns per prime, vectorized by
        clang on the M5, so 1.1 to 1.3 us per candidate, plus the scan of
        the buckets: about a third cheaper than the batch test from 220
        bits only, 1% of SIQS at 240 bits, what the prime index in the
        buckets costs. For double large primes, a third off the cost of
        their candidates would leave them slower than SIQS as it is (about
        7.1 s against 6.5 at 240 bits).
      - Block Lanczos below 12000 primes (November 2026, 10 numbers per
        size from 204 to 228 bits, with the filtered elimination): its
        linear algebra and the trial division of the relations cost 1 to
        3.5 ms more up to 212 bits, then 1 ms less at 216 bits, 6 at 220,
        15 at 224 and 21 at 228 (0.1% to 0.8% of a run), the peak memory 16
        to 22 MB rather than 81 to 166. The runs moved more than that, for
        another reason: with the same instructions retired, the sieving took
        0.983 of the time at 220 bits and 1.013 at 224, for each of the ten
        numbers. SIQS_BLOCK_LANCZOS_MIN_BASE stays at 12000. The arrays of
        the sieve start on a page (16 KiB) whatever was allocated before
        them, so that their offsets in a page never change; at 224 bits,
        the sieve's chunk allocated apart (aligned on 4 MiB, at any distance
        from the factor base) took the 1.1% back, but at 200 and 220 bits it
        changed nothing (1.000 to 1.004), nor does block Lanczos slow the
        sieving from 240 to 280 bits (0.994 to 1.002): no placement to fix.
        Measure such effects in alternation: the M5 slows by about 3% over a
        few minutes of load, which a sweep in order takes for an effect.
      - Threads (November 2026): at 240 bits in 6 threads the collection
        takes 1.23 s, near a sixth of 6.79 s, but the trial division of the
        relations (0.08 s) and the linear algebra (0.10 s) stay in one
        thread, 13% of the run. The batch test under the lock costs little:
        the threads wait for it 2% of the time.
      - From seven primes in 'a', the approximer sorts up to 18424 triples
        of primes per run (0.5 ms, 0.5% at 170 bits): pairs, which fixed six
        primes, gave slower 'a' there, but finding the best triple without
        the table would keep the same 'a'.
