An open-source number theory laboratory

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.

THE CONGRUENCE LABEXPERIMENT 001
x² ≡ y² (mod N)

Find matching squares. Reveal a hidden factor.

ILLUSTRATIVE SIEVE INTERVAL
16² ≡ 9² ≡ 25 (mod 77)
77 = 7 × 11

gcd(16 − 9, 77) = 7

A SMALL EXAMPLE OF THE FINAL STEP Why it works ↗
01 / MEASURE80 sizes. Before & Now. ↘02 / UNDERSTANDOne congruence. Five stages. ↘03 / SCALEA 115-digit expedition. ↘
01 / The performance notebook

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.

80SIZES
11–90 DIGITS
Ryzen 7 5800X · 8C / 16T32 GB RAMWindows · .NET 10 · ReleaseDefault parameters
BeforeNow
Before and Now: cold-run factorization times80 measurements per series, C11 through C90. Logarithmic seconds on the vertical axis; lower is faster. The complete values follow in a table. 0.1 s1 s10 s100 s2030405060708090TIME (s) · LOWER IS FASTERDigits of N
Drag the digit slider or use its arrow keys to compare a size.
CompositeC90
Before331.6 s
Now162.30 s
Less time51.1%
1190

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 ↗

Before and Now wall-clock seconds for every composite size
CompositeBeforeNowObserved change
C110.2 s0.284 s42.1% more time
C120.2 s0.281 s40.4% more time
C130.4 s0.599 s49.8% more time
C140.4 s0.646 s61.4% more time
C150.4 s0.642 s60.5% more time
C160.4 s0.683 s70.7% more time
C170.4 s0.741 s85.2% more time
C180.5 s0.684 s36.8% more time
C190.4 s0.598 s49.6% more time
C200.4 s0.717 s79.3% more time
C210.4 s0.823 s105.8% more time
C220.4 s0.880 s119.9% more time
C230.4 s0.669 s67.3% more time
C240.4 s0.628 s57.0% more time
C250.4 s0.856 s114.0% more time
C260.4 s0.798 s99.5% more time
C270.4 s0.833 s108.3% more time
C280.5 s0.919 s83.7% more time
C290.5 s0.693 s38.5% more time
C300.5 s0.708 s41.7% more time
C310.5 s0.968 s93.5% more time
C320.5 s0.904 s80.7% more time
C330.5 s0.756 s51.2% more time
C340.5 s0.728 s45.5% more time
C350.5 s0.747 s49.4% more time
C360.5 s0.762 s52.3% more time
C370.5 s0.787 s57.5% more time
C380.6 s0.763 s27.1% more time
C390.6 s0.802 s33.7% more time
C400.6 s0.808 s34.6% more time
C410.6 s0.874 s45.7% more time
C420.7 s1.001 s43.0% more time
C430.8 s1.193 s49.2% more time
C441.2 s1.170 s2.5% less time
C451.0 s1.566 s56.6% more time
C461.6 s1.980 s23.7% more time
C472.8 s2.356 s15.8% less time
C481.7 s1.881 s10.6% more time
C491.7 s1.851 s8.9% more time
C501.7 s1.948 s14.6% more time
C511.8 s2.041 s13.4% more time
C521.9 s2.380 s25.3% more time
C531.8 s2.414 s34.1% more time
C542.0 s2.222 s11.1% more time
C552.1 s2.359 s12.3% more time
C562.1 s2.451 s16.7% more time
C572.3 s2.805 s21.9% more time
C582.4 s2.907 s21.1% more time
C593.1 s3.384 s9.2% more time
C603.2 s3.756 s17.4% more time
C613.5 s4.114 s17.5% more time
C623.3 s4.581 s38.8% more time
C634.0 s4.454 s11.3% more time
C645.0 s4.808 s3.8% less time
C655.2 s5.373 s3.3% more time
C666.5 s5.390 s17.1% less time
C677.2 s5.998 s16.7% less time
C687.5 s5.825 s22.3% less time
C698.4 s7.505 s10.7% less time
C709.6 s9.117 s5.0% less time
C7111.0 s9.421 s14.4% less time
C7212.2 s9.219 s24.4% less time
C7313.4 s11.779 s12.1% less time
C7415.2 s13.062 s14.1% less time
C7519.9 s16.281 s18.2% less time
C7623.9 s15.307 s36.0% less time
C7727.5 s19.077 s30.6% less time
C7829.2 s20.887 s28.5% less time
C7933.8 s22.909 s32.2% less time
C8039.6 s31.173 s21.3% less time
C8144.1 s34.179 s22.5% less time
C8282.7 s33.576 s59.4% less time
C8362.5 s39.128 s37.4% less time
C8481.4 s54.855 s32.6% less time
C8572.0 s70.433 s2.2% less time
C86119.0 s79.666 s33.1% less time
C87186.8 s111.942 s40.1% less time
C88161.6 s126.331 s21.8% less time
C89203.4 s128.634 s36.8% less time
C90331.6 s162.302 s51.1% less time
The two-minute path

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.

The qs terminal UI mid-run: factor base done, sieving at 53% with a live progress bar showing elapsed time, estimated time left, and relations found, and the remaining phases still pending.

When it finishes, each phase collapses to a one-line summary above the factorization.

The qs terminal UI after completion: all five phases checked off with one-line summaries, the result N = p times q, and a dim job and artifacts footer.

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.

The crown jewel

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.

41:21submit to factors
15 × 48droplets × sieve cores
21:58distributed sieving
1.43Mmatrix rows
Timed work 40:27 total
Distributed sieve · 54.3%
Coordinator phases · 45.7%
The split 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.

What you can do with it

One solution, six ways in.

A working factorizer, a live web workbench, distributed sieving, and interactive learning material — all in a single .NET solution.

01

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.

02

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.

03

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.

04

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.

05

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.

06

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.

The pipeline at a glance

Everything serves one line of algebra.

X² ≡ Y² (mod N)

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.

1

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.

2

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.

3

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).

4

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.

5

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.

See the workbench

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.

The Factorize page: a target-N field, an advanced-parameters panel, and a recent-jobs list.
Factorize

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.

The Jobs list showing seven completed factorizations with sizes, durations, and factors.
Jobs

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 job-details page: a five-phase timeline, the factor result, and a per-phase counters table.
Job details

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.

The Distributed page: submit a composite and download self-contained Windows and Linux sieve clients.
Distributed

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.

Sieve School: a guided tour and a quiz, with a table mapping tour steps to pipeline phases.
Sieve School

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.

The toolchain

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.
ComponentWhat it is
qs.exeThe 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-sqrtStandalone per-phase tools that read and write the documented text artifacts.
SIQS.UIBlazor web workbench: Factorize, Jobs & artifacts, Distributed coordination, Sieve School, and history.
SIQS.PipelineOrchestration library — owns defaults, runs phases in order, tracks the job workspace, reports progress.
SIQS.Overlord + qs-sieve-clientDistributed sieving: the coordinator leases work slices; the self-contained client verifies, sieves, and uploads relations.
Factorbase, Sieving, Filtering, LinearAlgebra, SquareRootThe five phase libraries — the actual mathematics, each with its own xUnit test project.
CompositeGeneratorGenerates fresh RSA-shaped semiprime targets: CompositeGenerator.exe 55 | qs.exe.
SIQS.BenchmarksBenchmarkDotNet 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.

Distributed sieving

Sieving is embarrassingly parallel.

Disjoint polynomial families run on different machines with no coordination beyond handing out assignments. SIQS.NET exploits that.

A

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.

B

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.

C

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.

Get started

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.