Big numbers.
Small factors.
Beautiful math.
The self-initializing quadratic sieve, in C# & .NET 10.
Turn an intimidating integer into a pair of primes. Then follow the trail from smooth numbers to sparse matrices, and see exactly how the split happens.
Find matching squares. Reveal a hidden factor.
gcd(16 − 9, 77) = 7
Same sieve. A new pace.
Incremental improvements, measured across 80 sizes. Explore the original results alongside a fresh set of cold runs. Every gain. Every regression. Nothing smoothed away.
11–90 DIGITS
One fresh balanced semiprime per digit count, one new process per input, no warm-up. Timed from process launch to exit, including startup and artifact I/O. “Cold” refers to the process; OS disk caches are not flushed. Fresh inputs vary in difficulty, so these are observations, not a controlled speedup estimate.
Download the data ↓All 80 comparisons & methodology
Before is preserved exactly from the original chart. Now follows the published method on the same CPU model and RAM capacity. The original inputs, exact runtime build and timing harness were not recorded in this showcase, so exact reproduction is unavailable. Run details, inputs & provenance ↗
| Composite | Before | Now | Observed change |
|---|---|---|---|
| C11 | 0.2 s | 0.284 s | 42.1% more time |
| C12 | 0.2 s | 0.281 s | 40.4% more time |
| C13 | 0.4 s | 0.599 s | 49.8% more time |
| C14 | 0.4 s | 0.646 s | 61.4% more time |
| C15 | 0.4 s | 0.642 s | 60.5% more time |
| C16 | 0.4 s | 0.683 s | 70.7% more time |
| C17 | 0.4 s | 0.741 s | 85.2% more time |
| C18 | 0.5 s | 0.684 s | 36.8% more time |
| C19 | 0.4 s | 0.598 s | 49.6% more time |
| C20 | 0.4 s | 0.717 s | 79.3% more time |
| C21 | 0.4 s | 0.823 s | 105.8% more time |
| C22 | 0.4 s | 0.880 s | 119.9% more time |
| C23 | 0.4 s | 0.669 s | 67.3% more time |
| C24 | 0.4 s | 0.628 s | 57.0% more time |
| C25 | 0.4 s | 0.856 s | 114.0% more time |
| C26 | 0.4 s | 0.798 s | 99.5% more time |
| C27 | 0.4 s | 0.833 s | 108.3% more time |
| C28 | 0.5 s | 0.919 s | 83.7% more time |
| C29 | 0.5 s | 0.693 s | 38.5% more time |
| C30 | 0.5 s | 0.708 s | 41.7% more time |
| C31 | 0.5 s | 0.968 s | 93.5% more time |
| C32 | 0.5 s | 0.904 s | 80.7% more time |
| C33 | 0.5 s | 0.756 s | 51.2% more time |
| C34 | 0.5 s | 0.728 s | 45.5% more time |
| C35 | 0.5 s | 0.747 s | 49.4% more time |
| C36 | 0.5 s | 0.762 s | 52.3% more time |
| C37 | 0.5 s | 0.787 s | 57.5% more time |
| C38 | 0.6 s | 0.763 s | 27.1% more time |
| C39 | 0.6 s | 0.802 s | 33.7% more time |
| C40 | 0.6 s | 0.808 s | 34.6% more time |
| C41 | 0.6 s | 0.874 s | 45.7% more time |
| C42 | 0.7 s | 1.001 s | 43.0% more time |
| C43 | 0.8 s | 1.193 s | 49.2% more time |
| C44 | 1.2 s | 1.170 s | 2.5% less time |
| C45 | 1.0 s | 1.566 s | 56.6% more time |
| C46 | 1.6 s | 1.980 s | 23.7% more time |
| C47 | 2.8 s | 2.356 s | 15.8% less time |
| C48 | 1.7 s | 1.881 s | 10.6% more time |
| C49 | 1.7 s | 1.851 s | 8.9% more time |
| C50 | 1.7 s | 1.948 s | 14.6% more time |
| C51 | 1.8 s | 2.041 s | 13.4% more time |
| C52 | 1.9 s | 2.380 s | 25.3% more time |
| C53 | 1.8 s | 2.414 s | 34.1% more time |
| C54 | 2.0 s | 2.222 s | 11.1% more time |
| C55 | 2.1 s | 2.359 s | 12.3% more time |
| C56 | 2.1 s | 2.451 s | 16.7% more time |
| C57 | 2.3 s | 2.805 s | 21.9% more time |
| C58 | 2.4 s | 2.907 s | 21.1% more time |
| C59 | 3.1 s | 3.384 s | 9.2% more time |
| C60 | 3.2 s | 3.756 s | 17.4% more time |
| C61 | 3.5 s | 4.114 s | 17.5% more time |
| C62 | 3.3 s | 4.581 s | 38.8% more time |
| C63 | 4.0 s | 4.454 s | 11.3% more time |
| C64 | 5.0 s | 4.808 s | 3.8% less time |
| C65 | 5.2 s | 5.373 s | 3.3% more time |
| C66 | 6.5 s | 5.390 s | 17.1% less time |
| C67 | 7.2 s | 5.998 s | 16.7% less time |
| C68 | 7.5 s | 5.825 s | 22.3% less time |
| C69 | 8.4 s | 7.505 s | 10.7% less time |
| C70 | 9.6 s | 9.117 s | 5.0% less time |
| C71 | 11.0 s | 9.421 s | 14.4% less time |
| C72 | 12.2 s | 9.219 s | 24.4% less time |
| C73 | 13.4 s | 11.779 s | 12.1% less time |
| C74 | 15.2 s | 13.062 s | 14.1% less time |
| C75 | 19.9 s | 16.281 s | 18.2% less time |
| C76 | 23.9 s | 15.307 s | 36.0% less time |
| C77 | 27.5 s | 19.077 s | 30.6% less time |
| C78 | 29.2 s | 20.887 s | 28.5% less time |
| C79 | 33.8 s | 22.909 s | 32.2% less time |
| C80 | 39.6 s | 31.173 s | 21.3% less time |
| C81 | 44.1 s | 34.179 s | 22.5% less time |
| C82 | 82.7 s | 33.576 s | 59.4% less time |
| C83 | 62.5 s | 39.128 s | 37.4% less time |
| C84 | 81.4 s | 54.855 s | 32.6% less time |
| C85 | 72.0 s | 70.433 s | 2.2% less time |
| C86 | 119.0 s | 79.666 s | 33.1% less time |
| C87 | 186.8 s | 111.942 s | 40.1% less time |
| C88 | 161.6 s | 126.331 s | 21.8% less time |
| C89 | 203.4 s | 128.634 s | 36.8% less time |
| C90 | 331.6 s | 162.302 s | 51.1% less time |
I just want to factor something.
Install the SDK, build once, and point the qs binary at a
number. Sensible defaults are chosen from its digit count — no tuning required.
Install the .NET 10 SDK, then clone and build.
git clone https://github.com/JesHansen/siqs.net.git
cd siqs.net
dotnet build -c Release SIQS.slnx
The build produces a qs binary. Point it straight at the number you want factored — no need to dotnet run the project again.
.\QS\bin\Release\net10.0\qs.exe 150478035830330483870744795468187571781390056303346096534807
On Linux or macOS, run ./QS/bin/Release/net10.0/qs (drop the .exe).
A live terminal view tracks every phase — factor base, sieving, filtering, linear algebra, square root — with a progress bar, elapsed time, and an estimate of the time left.
When it finishes, each phase collapses to a one-line summary above the factorization.
Want the raw numbers? --debug restores the full per-phase counter dump, and --quiet prints only the factor product to stdout so you can pipe qs into a script.
Prefer buttons over terminals? Start the web workbench and open http://localhost:5078.
dotnet run -c Release --project SIQS.UI/SIQS.UI.csproj --urls "http://localhost:5078"
That's the whole workflow. A prime input exits cleanly with “no non-trivial
factor”; Ctrl+C cancels a run and leaves its artifacts resumable with
--resume. Curious what's happening under the hood?
Read the deep dive.
Fifteen machines.
Seven hundred twenty cores.
One split.
A balanced 115-digit semiprime, factored end to end by SIQS.NET with default parameters. Fifteen 48-core DigitalOcean droplets sieved in parallel; one coordinator verified 6.66 million relations, built the matrix, solved it, and recovered the factors.
1634609642529461351426322818336738394876177998696139518394622790139101259986895310200063458405600316582957220469623
=
1237988317263640195375154562113020204374599620934815747079
×
1320375660848306094500628943570772166023517472818828376337
Pure SIQS, all the way through. The sieve streamed 5.10 GB in 1,638
durable chunks with no failed chunks. Filtering produced a 1,433,382 × 1,428,982
sparse matrix; Block Lanczos emitted 62 dependencies in one run, and the second yielded
the factors. The complete run is preserved as job D20260801-105654-1036.
One solution, six ways in.
A working factorizer, a live web workbench, distributed sieving, and interactive learning material — all in a single .NET solution.
Factor an integer
Run a one-shot factorization from the qs command line or the web
Factorize page. Every parameter — factor-base bound, multiplier, sieve
interval, large-prime bounds, parallelism — has a digit-size default and a CLI override.
Watch a live run
Phase status, elapsed time per phase, relation counters, matrix dimensions, and run artifacts are retained for inspection in the Jobs view. Interrupted runs resume from their workspace.
Distribute the sieve
Sieving dominates the cost, so the server can lease disjoint slices of polynomial work to volunteer clients over HTTP. Workers independently rebuild and verify the job parameters before sieving a single value.
Run self-contained workers
Download single-file sieve clients for Windows x64 and Linux x64 straight from the workbench — no .NET runtime required on the worker machine.
Learn it in Sieve School
A guided tour through a worked factorization, an animated sieve window, topic quizzes, and a historical timeline from Fermat and Kraitchik through Pomerance and RSA-129.
Work a stage at a time
Five focused CLI tools — qs-fb, qs-sieve, qs-filter,
qs-linalg, qs-sqrt — run each pipeline phase standalone over plain
text artifacts you can read and diff.
Everything serves one line of algebra.
The whole machine exists to build one congruence of squares. When
X ≢ ±Y, gcd(X − Y, N) reveals a factor. Everything below is bookkeeping
in service of this single line.
Factor base qs-fb → factor_base.txt
Pick a multiplier, then collect the primes p for which the scaled target is a quadratic residue — the only primes that can ever divide a sieve value.
Sieving qs-sieve → relations_*.txt
Generate families of polynomials and sieve them over a symmetric interval, adding logarithmic weights where factor-base primes divide. Survivors become relations; near-misses become large-prime partials. This is the hot path — and the part that distributes.
Filtering qs-filter → filtered_matrix.txt
Combine partial relations through large-prime graph cycles, remove duplicates and singletons, and trim the result into a lean sparse matrix over GF(2).
Linear algebra qs-linalg → dependencies.txt
Run Block Lanczos over GF(2) to find non-empty sets of relations whose exponent vectors XOR to zero — each one a candidate congruence of squares.
Square root qs-sqrt → factors.txt
Reconstruct X and Y from a dependency, verify every exponent sum is even, and take GCDs against N. A non-trivial answer is your factor.
One command, qs.exe, runs all five phases in a single process with live console
progress — the per-phase tools exist so you can study, debug, or benchmark any stage in
isolation against hand-crafted inputs.
The whole system, before you clone anything.
The SIQS.UI Blazor app is the easiest way to explore
SIQS.NET — start a run, watch every phase, browse archived jobs and artifacts, hand sieving
out to other machines, and learn the method.
Start a run from the browser.
Every tuning knob has a digit-size default and an override behind Advanced parameters. The live card follows the current phase to completion.
Every factorization, live and archived.
Target size, status, wall-clock duration, and discovered factors — filterable by kind and status, each one openable for the full record.
A per-phase timeline and every counter.
Elapsed times, the final congruence-of-squares result, factor-base size, relations found, matrix dimensions, Block Lanczos dependencies — the complete set each stage recorded.
Share sieving across machines.
Submit a job whose sieving is spread over a pool, and download self-contained Windows x64 and Linux x64 workers — no runtime required.
A guided tour and a randomized quiz.
Walk a worked factorization step by step, each one linked to the pipeline phase it explains — from foundations through square roots.
Divided by algorithmic responsibility.
Phase libraries with typed APIs, thin CLI front-ends, a shared contracts library, and an orchestration pipeline that both the console capstone and the web UI sit on top of.
Debugging a factorization is reading files, not attaching debuggers.
| Component | What it is |
|---|---|
qs.exe | The capstone: factors a number end-to-end in one process with live progress, resumable workspaces, and meaningful exit codes. |
qs-fb, qs-sieve, qs-filter, qs-linalg, qs-sqrt | Standalone per-phase tools that read and write the documented text artifacts. |
SIQS.UI | Blazor web workbench: Factorize, Jobs & artifacts, Distributed coordination, Sieve School, and history. |
SIQS.Pipeline | Orchestration library — owns defaults, runs phases in order, tracks the job workspace, reports progress. |
SIQS.Overlord + qs-sieve-client | Distributed sieving: the coordinator leases work slices; the self-contained client verifies, sieves, and uploads relations. |
Factorbase, Sieving, Filtering, LinearAlgebra, SquareRoot | The five phase libraries — the actual mathematics, each with its own xUnit test project. |
CompositeGenerator | Generates fresh RSA-shaped semiprime targets: CompositeGenerator.exe 55 | qs.exe. |
SIQS.Benchmarks | BenchmarkDotNet harness isolating the hot kernels — Block Lanczos multiplies and the sieve fill/scan seam. |
Everything is a text file.
Every phase writes plain UTF-8 artifacts —
factor_base.txt, relations_0000.txt,
filtered_matrix.txt, dependencies.txt, factors.txt —
with documented, versioned header contracts. Open any intermediate state of a factorization in
a text editor, diff two runs, or feed a hand-edited file back into the next phase.
Sieving is embarrassingly parallel.
Disjoint polynomial families run on different machines with no coordination beyond handing out assignments. SIQS.NET exploits that.
The Overlord coordinates
The server owns the job: it leases slices of polynomial indices, validates every uploaded relation, re-issues abandoned leases, and runs filtering, linear algebra, and square root centrally once enough relations arrive.
Workers verify, then trust
A client performs a protocol handshake and independently reconstructs the factor base and sieving parameters from the job descriptor. If its reconstruction disagrees with the server's, it declines the job.
A drop-in replacement
The distributed sieve produces byte-compatible relation artifacts, so the rest of the pipeline can't tell the difference between one machine and twenty.
# On each worker — download from the server's Distributed page, then:
.\qs-sieve-client.exe http://your-siqs-server:5078 # Windows
./qs-sieve-client http://your-siqs-server:5078 # Linux
The distributed API is designed for a trusted LAN. If you expose a server beyond one, put it behind authentication, TLS, firewalling, and rate limits.
Everything from a fresh clone.
No dependencies beyond the .NET 10 SDK.
# Build and test everything
dotnet build -c Release SIQS.slnx
dotnet test --solution SIQS.slnx
# Factor from the command line with the built binary
# (add --parallelism 1 for reproducible artifacts)
.\QS\bin\Release\net10.0\qs.exe <your composite>
# Explore the full workbench in a browser
dotnet run -c Release --project SIQS.UI/SIQS.UI.csproj --urls "http://localhost:5078"
# Generate a fresh 55-digit test target and factor it in one line
CompositeGenerator.exe 55 | qs.exe
SIQS.NET is for education, experimentation, benchmarking, and factoring integers you are authorized to factor. It owes an enormous debt to msieve and YAFU — extraordinary factoring software well worth studying.