Benchmarks
Here we present benchmarks of Symbolica versus other computer algebra systems and libraries.
Algebra performance
First, we compare Symbolica with other full computer algebra systems: Mathematica and SymPy. We test polynomial arithmetic through the computation of a greatest common divisor operation on multivariate polynomials. It is a useful test that stresses many areas, including memory management.
On this standard polynomial GCD benchmark, Symbolica comfortably outpaces both: 2 seconds, compared with 89 seconds and over an hour.
Code and timing provenance
The inputs have a known common factor. Construction is outside the timer; only the GCD call is timed, with verification afterward (allowing constant normalization of the common factor). Symbolica uses its polynomial representation, Mathematica receives expanded expressions, and SymPy performs any conversion required by its expression-level gcd call.
from time import perf_counter
from symbolica import S
xs = S("x1", "x2", "x3", "x4", "x5", "x6", "x7")
coefficients = [3, 5, 7, 9, 11, 13, 15]
def base(signs):
return 1 + sum(c*s*x for c, s, x in zip(coefficients, signs, xs))
degree = 7
a = (base([1]*7)**degree - 1).to_polynomial()
b = (base([-1,-1,-1,1,-1,-1,1])**degree + 1).to_polynomial()
g = (base([1,1,1,1,1,1,-1])**degree + 3).to_polynomial()
ag, bg = a*g, b*g
start = perf_counter()
result = ag.gcd(bg)
seconds = perf_counter() - start
assert result.monic() == g.monic()
print(seconds)xs = Symbol /@ Table["x" <> ToString[i], {i, 7}];
coefficients = Range[3, 15, 2];
base[signs_] := 1 + (coefficients signs).xs;
degree = 7;
a = base[ConstantArray[1, 7]]^degree - 1;
b = base[{-1,-1,-1,1,-1,-1,1}]^degree + 1;
g = base[{1,1,1,1,1,1,-1}]^degree + 3;
ag = Expand[a g]; bg = Expand[b g];
{seconds, result} = AbsoluteTiming[PolynomialGCD[ag, bg]];
If[Expand[result - g] =!= 0, Abort[]];
Print[seconds];from time import perf_counter
import sympy as sp
xs = sp.symbols("x1:8")
coefficients = [3, 5, 7, 9, 11, 13, 15]
def base(signs):
return 1 + sum(c*s*x for c, s, x in zip(coefficients, signs, xs))
degree = 7
a = base([1]*7)**degree - 1
b = base([-1,-1,-1,1,-1,-1,1])**degree + 1
g = base([1,1,1,1,1,1,-1])**degree + 3
ag, bg = a*g, b*g
start = perf_counter()
result = sp.gcd(ag, bg)
seconds = perf_counter() - start
assert sp.expand(result - g) == 0
print(seconds)Symbolica vs FLINT
Next, compare Symbolica with FLINT, a highly specialized C library for polynomial arithmetic and number theory.
Symbolica is faster in 179 of 291 paired cases in this suite. The table shows wins and the median of the individual FLINT / Symbolica timing ratios for each operation. A ratio above 1 favors Symbolica; below 1 favors FLINT. These ratios describe individual cases, not total-suite speedups.
| Operation | Cases | Symbolica wins | Median FLINT / Symbolica |
|---|---|---|---|
| Multiplication | 100 | 62 | 1.05× |
| Exact division | 33 | 2 | 0.34× |
| GCD | 61 | 44 | 1.87× |
| Factorization | 53 | 40 | 1.78× |
| Resultant | 38 | 27 | 1.22× |
| Discriminant | 6 | 4 | 1.05× |
The suite covers 291 paired cases: polynomial multiplication, exact division, GCD, factorization, resultants, and discriminants in native Rust and C, with both generated inputs and fixed polynomial fixtures.
Both axes are logarithmic. The dashed line means equal time.
Hover, focus, or tap a point to inspect a case.
291 cases shown
Explore the exact timings
| Case | Symbolica (ms) | FLINT (ms) | FLINT / Symbolica | Samples |
|---|---|---|---|---|
| rational/sparse8_d128/b12/qfalse/multiply | 0.007945 | 0.007193 | 0.905× | 3 |
| rational/sparse8_d128/b12/qfalse/exact_division | 0.074881 | 0.009308 | 0.124× | 3 |
| rational/sparse8_d128/b12/qtrue/multiply | 0.014538 | 0.007094 | 0.488× | 3 |
| rational/sparse8_d128/b12/qtrue/exact_division | 0.090441 | 0.009027 | 0.0998× | 3 |
| rational/sparse8_d128/b63/qfalse/multiply | 0.007755 | 0.009178 | 1.18× | 3 |
| rational/sparse8_d128/b63/qfalse/exact_division | 0.070874 | 0.016381 | 0.231× | 3 |
| rational/sparse8_d128/b63/qtrue/multiply | 0.016711 | 0.010720 | 0.641× | 3 |
| rational/sparse8_d128/b63/qtrue/exact_division | 0.089109 | 0.019817 | 0.222× | 3 |
| rational/sparse8_d128/b127/qfalse/multiply | 0.015960 | 0.010981 | 0.688× | 3 |
| rational/sparse8_d128/b127/qfalse/exact_division | 0.091112 | 0.020870 | 0.229× | 3 |
| rational/sparse8_d128/b127/qtrue/multiply | 0.050074 | 0.014417 | 0.288× | 3 |
| rational/sparse8_d128/b127/qtrue/exact_division | 0.139534 | 0.024677 | 0.177× | 3 |
| rational/dense3_d12/b12/qfalse/multiply | 0.854596 | 0.115298 | 0.135× | 3 |
| rational/dense3_d12/b12/qfalse/exact_division | 3.365926 | 1.273408 | 0.378× | 3 |
| rational/dense3_d12/b12/qtrue/multiply | 13.155903 | 0.119096 | 0.00905× | 3 |
| rational/dense3_d12/b12/qtrue/exact_division | 3.423173 | 1.276294 | 0.373× | 3 |
| rational/dense3_d12/b63/qfalse/multiply | 2.093660 | 1.861141 | 0.889× | 3 |
| rational/dense3_d12/b63/qfalse/exact_division | 4.493509 | 3.516311 | 0.783× | 3 |
| rational/dense3_d12/b63/qtrue/multiply | 40.839292 | 3.633703 | 0.089× | 3 |
| rational/dense3_d12/b63/qtrue/exact_division | 6.572872 | 5.105757 | 0.777× | 3 |
| rational/dense3_d12/b127/qfalse/multiply | 3.749922 | 3.911588 | 1.04× | 3 |
| rational/dense3_d12/b127/qfalse/exact_division | 6.461512 | 5.321014 | 0.823× | 3 |
| rational/dense3_d12/b127/qtrue/multiply | 52.839028 | 8.120999 | 0.154× | 3 |
| rational/dense3_d12/b127/qtrue/exact_division | 7.102183 | 7.456523 | 1.05× | 3 |
| rational/dense3_d20/b12/qfalse/multiply | 13.470117 | 1.543459 | 0.115× | 3 |
| rational/dense3_d20/b12/qfalse/exact_division | 53.472576 | 20.300977 | 0.38× | 3 |
| rational/dense3_d20/b12/qtrue/multiply | 217.797334 | 1.492562 | 0.00685× | 3 |
| rational/dense3_d20/b12/qtrue/exact_division | 52.787600 | 20.451531 | 0.387× | 3 |
| rational/dense3_d20/b63/qfalse/multiply | 35.314071 | 31.239265 | 0.885× | 3 |
| rational/dense3_d20/b63/qfalse/exact_division | 65.816653 | 54.834863 | 0.833× | 3 |
| rational/dense3_d20/b63/qtrue/multiply | 677.372206 | 60.126841 | 0.0888× | 3 |
| rational/dense3_d20/b63/qtrue/exact_division | 94.155111 | 84.555114 | 0.898× | 3 |
| rational/dense3_d20/b127/qfalse/multiply | 58.163177 | 61.560994 | 1.06× | 3 |
| rational/dense3_d20/b127/qfalse/exact_division | 91.851054 | 85.905348 | 0.935× | 3 |
| rational/dense3_d20/b127/qtrue/multiply | 864.581691 | 91.711199 | 0.106× | 3 |
| rational/dense3_d20/b127/qtrue/exact_division | 104.703602 | 122.742249 | 1.17× | 3 |
| rational/sparse8_div127/b12/qfalse/multiply | 0.013816 | 0.009137 | 0.661× | 3 |
| rational/sparse8_div127/b12/qfalse/exact_division | 0.051818 | 0.011411 | 0.22× | 3 |
| rational/sparse8_div127/b12/qtrue/multiply | 0.027212 | 0.008486 | 0.312× | 3 |
| rational/sparse8_div127/b12/qtrue/exact_division | 0.050205 | 0.006692 | 0.133× | 3 |
| rational/sparse8_div127/b63/qfalse/multiply | 0.007865 | 0.006843 | 0.87× | 3 |
| rational/sparse8_div127/b63/qfalse/exact_division | 0.034175 | 0.013285 | 0.389× | 3 |
| rational/sparse8_div127/b63/qtrue/multiply | 0.014898 | 0.008846 | 0.594× | 3 |
| rational/sparse8_div127/b63/qtrue/exact_division | 0.050575 | 0.017273 | 0.342× | 3 |
| rational/sparse8_div127/b127/qfalse/multiply | 0.015068 | 0.008717 | 0.579× | 3 |
| rational/sparse8_div127/b127/qfalse/exact_division | 0.053702 | 0.017613 | 0.328× | 3 |
| rational/sparse8_div127/b127/qtrue/multiply | 0.042541 | 0.013465 | 0.317× | 3 |
| rational/sparse8_div127/b127/qtrue/exact_division | 0.099458 | 0.021571 | 0.217× | 3 |
| rational/sparse8_div128/b12/qfalse/multiply | 0.007485 | 0.007053 | 0.942× | 3 |
| rational/sparse8_div128/b12/qfalse/exact_division | 0.069791 | 0.009007 | 0.129× | 3 |
| rational/sparse8_div128/b12/qtrue/multiply | 0.013696 | 0.006953 | 0.508× | 3 |
| rational/sparse8_div128/b12/qtrue/exact_division | 0.088036 | 0.009258 | 0.105× | 3 |
| rational/sparse8_div128/b63/qfalse/multiply | 0.007313 | 0.009608 | 1.31× | 3 |
| rational/sparse8_div128/b63/qfalse/exact_division | 0.068820 | 0.016571 | 0.241× | 3 |
| rational/sparse8_div128/b63/qtrue/multiply | 0.016020 | 0.011321 | 0.707× | 3 |
| rational/sparse8_div128/b63/qtrue/exact_division | 0.089209 | 0.020479 | 0.23× | 3 |
| rational/sparse8_div128/b127/qfalse/multiply | 0.014939 | 0.011171 | 0.748× | 3 |
| rational/sparse8_div128/b127/qfalse/exact_division | 0.089759 | 0.021751 | 0.242× | 3 |
| rational/sparse8_div128/b127/qtrue/multiply | 0.036900 | 0.014567 | 0.395× | 3 |
| rational/sparse8_div128/b127/qtrue/exact_division | 0.137510 | 0.025668 | 0.187× | 3 |
| dense small multiplication | 0.188687 | 0.118935 | 0.63× | 3 |
| dense high multiplication | 3.424106 | 5.086571 | 1.49× | 3 |
| dense large multiplication | 10.895287 | 18.531028 | 1.7× | 3 |
| dense very large multiplication | 100.054629 | 211.228978 | 2.11× | 3 |
| dense high large multiplication | 76.538571 | 129.925464 | 1.7× | 3 |
| sparse separated multiplication | 16.737476 | 13.766889 | 0.823× | 3 |
| sparse large multiplication | 330.094152 | 343.017024 | 1.04× | 3 |
| seven-variable power-minus-one multiplication | 45.978391 | 85.356238 | 1.86× | 3 |
| dense exact division | 1.093959 | 0.460862 | 0.421× | 3 |
| dense large exact division | 14.690776 | 5.828164 | 0.397× | 3 |
| high-height exact division | 4.760473 | 4.418797 | 0.928× | 3 |
| GF(17) dense univariate degree-4912 multiplication | 0.291512 | 0.268468 | 0.921× | 3 |
| GF(17) dense large multiplication | 0.191973 | 0.196571 | 1.02× | 3 |
| GF(17) dense very large multiplication | 0.731964 | 0.721004 | 0.985× | 3 |
| GF(17) five-variable total-degree multiplication | 333.371107 | 346.492264 | 1.04× | 3 |
| GF(17) sparse large multiplication | 85.760622 | 72.204423 | 0.842× | 3 |
| GF(17) seven-variable power-minus-one multiplication | 55.504067 | 77.691621 | 1.4× | 3 |
| GF(18446744073709551557) dense univariate degree-4912 multiplication | 0.439551 | 1.458208 | 3.32× | 3 |
| GF(18446744073709551557) dense large multiplication | 4.996541 | 20.404342 | 4.08× | 3 |
| GF(18446744073709551557) dense very large multiplication | 64.468772 | 118.738003 | 1.84× | 3 |
| GF(18446744073709551557) five-variable total-degree multiplication | 376.371022 | 353.130918 | 0.938× | 3 |
| GF(18446744073709551557) sparse large multiplication | 344.583580 | 329.950926 | 0.958× | 3 |
| GF(18446744073709551557) seven-variable power-minus-one multiplication | 72.457471 | 79.497446 | 1.1× | 3 |
| GF(65000011) dense univariate degrees 128/64 accumulator-bound multiplication | 0.007304 | 0.007534 | 1.03× | 3 |
| GF(500000003) dense univariate degrees 128/64 accumulator-bound multiplication | 0.006762 | 0.007955 | 1.18× | 3 |
| resultant Brown: dense outer degrees 7/6 | 10.761323 | 7.517788 | 0.699× | 3 |
| resultant Ducos: dense outer degrees 7/6 | 4.004825 | 7.475068 | 1.87× | 3 |
| resultant CRT: dense outer degrees 7/6 | 26.232875 | 7.446313 | 0.284× | 3 |
| resultant Brown: lacunary outer degrees 18/11 | 63.305532 | 54.393876 | 0.859× | 3 |
| resultant Ducos: lacunary outer degrees 18/11 | 27.486816 | 54.633691 | 1.99× | 3 |
| resultant CRT: lacunary outer degrees 18/11 | 183.159233 | 54.364311 | 0.297× | 3 |
| resultant Brown: nonunit leading degrees 9/7 | 5.915428 | 4.927850 | 0.833× | 3 |
| resultant Ducos: nonunit leading degrees 9/7 | 2.848758 | 4.879899 | 1.71× | 3 |
| resultant CRT: nonunit leading degrees 9/7 | 8.846642 | 4.863238 | 0.55× | 3 |
| resultant Brown: large high-height degrees 14/10 | 8408.854547 | 4623.354291 | 0.55× | 3 |
| resultant Ducos: large high-height degrees 14/10 | 3040.571170 | 4683.198087 | 1.54× | 3 |
| resultant CRT: large high-height degrees 14/10 | 10904.909677 | 4696.211669 | 0.431× | 3 |
| resultant Brown: dense outer degrees 10/8 CRT crossover | 264.699006 | 151.290499 | 0.572× | 3 |
| resultant Ducos: dense outer degrees 10/8 CRT crossover | 90.949853 | 151.299786 | 1.66× | 3 |
| resultant CRT: dense outer degrees 10/8 CRT crossover | 152.952011 | 155.734623 | 1.02× | 3 |
| resultant Brown: outer-sparse degrees 12/9 CRT crossover | 504.090227 | 397.725231 | 0.789× | 3 |
| resultant Ducos: outer-sparse degrees 12/9 CRT crossover | 228.834207 | 385.685632 | 1.69× | 3 |
| resultant CRT: outer-sparse degrees 12/9 CRT crossover | 255.766300 | 383.833509 | 1.5× | 3 |
| GCD products: dense 7 variables degree 7 | 93.719030 | 169.902285 | 1.81× | 3 |
| GCD auto: dense 7 variables degree 7 | 5023.687657 | 3362.028771 | 0.669× | 3 |
| generated GCD products: dense 1 variables degree 32 | 0.008166 | 0.008005 | 0.98× | 3 |
| generated GCD auto: dense 1 variables degree 32 | 0.096823 | 0.069682 | 0.72× | 3 |
| generated GCD products: dense 2 variables degree 5 | 0.004519 | 0.010199 | 2.26× | 3 |
| generated GCD auto: dense 2 variables degree 5 | 0.068569 | 0.053171 | 0.775× | 3 |
| generated GCD products: dense 3 variables degree 7 | 0.023895 | 0.028784 | 1.2× | 3 |
| generated GCD auto: dense 3 variables degree 7 | 1.088669 | 4.196737 | 3.85× | 3 |
| generated GCD products: dense 5 variables degree 7 | 1.829600 | 3.694847 | 2.02× | 3 |
| generated GCD auto: dense 5 variables degree 7 | 210.334755 | 96.443560 | 0.459× | 3 |
| generated GCD products: dense 8 variables degree 5 | 14.273103 | 24.219463 | 1.7× | 3 |
| generated GCD auto: dense 8 variables degree 5 | 175.315778 | 779.666737 | 4.45× | 3 |
| generated GCD products: dense 8 variables asymmetric cofactor terms 8/45 common terms 165 degrees 1/2/3 | 0.078839 | 0.092415 | 1.17× | 3 |
| generated GCD auto: dense 8 variables asymmetric cofactor terms 8/45 common terms 165 degrees 1/2/3 | 0.934357 | 2.593755 | 2.78× | 3 |
| generated GCD products: dense 8 variables asymmetric cofactor terms 8/45 common terms 495 degrees 1/2/4 | 0.222311 | 0.275902 | 1.24× | 3 |
| generated GCD auto: dense 8 variables asymmetric cofactor terms 8/45 common terms 495 degrees 1/2/4 | 2.059495 | 5.724486 | 2.78× | 3 |
| generated GCD products: dense 8 variables asymmetric cofactor terms 8/45 common terms 1287 degrees 1/2/5 | 0.540301 | 0.708140 | 1.31× | 3 |
| generated GCD auto: dense 8 variables asymmetric cofactor terms 8/45 common terms 1287 degrees 1/2/5 | 4.457880 | 12.243484 | 2.75× | 3 |
| generated GCD products: sparse 5 variables degree 7 | 0.156937 | 0.168188 | 1.07× | 3 |
| generated GCD auto: sparse 5 variables degree 7 | 7.837252 | 9.030919 | 1.15× | 3 |
| generated GCD products: sparse 8 variables degree 5 | 0.403293 | 0.413923 | 1.03× | 3 |
| generated GCD auto: sparse 8 variables degree 5 | 12.288649 | 45.335677 | 3.69× | 3 |
| generated GCD products: high-gap 5 variables degree 5 gap 64 | 0.093577 | 0.097304 | 1.04× | 3 |
| generated GCD auto: high-gap 5 variables degree 5 gap 64 | 1.478245 | 25.525532 | 17.3× | 3 |
| generated GCD products: high-gap 8 variables degree 4 gap 256 | 0.321618 | 0.446064 | 1.39× | 3 |
| generated GCD auto: high-gap 8 variables degree 4 gap 256 | 4.162291 | 231.571115 | 55.6× | 3 |
| generated GCD products: high-height 5 variables degree 4 coefficient bits 128 | 1.543468 | 2.396001 | 1.55× | 3 |
| generated GCD auto: high-height 5 variables degree 4 coefficient bits 128 | 9.316489 | 31.525259 | 3.38× | 3 |
| generated GCD products: high-height 5 variables degree 4 coefficient bits 256 | 4.049348 | 4.818282 | 1.19× | 3 |
| generated GCD auto: high-height 5 variables degree 4 coefficient bits 256 | 17.679584 | 58.130273 | 3.29× | 3 |
| generated GCD products: high-height 5 variables degree 4 coefficient bits 512 | 11.818832 | 12.707612 | 1.08× | 3 |
| generated GCD auto: high-height 5 variables degree 4 coefficient bits 512 | 40.404010 | 123.895244 | 3.07× | 3 |
| generated GCD products: high-height 5 variables degree 4 coefficient bits 1024 | 34.830199 | 35.904751 | 1.03× | 3 |
| generated GCD auto: high-height 5 variables degree 4 coefficient bits 1024 | 107.413134 | 286.567551 | 2.67× | 3 |
| generated GCD products: high-height 8 variables degree 3 coefficient bits 256 | 4.494309 | 5.350028 | 1.19× | 3 |
| generated GCD auto: high-height 8 variables degree 3 coefficient bits 256 | 33.042899 | 117.539083 | 3.56× | 3 |
| generated GCD products: high-height 8 variables asymmetric cofactor terms 8/45 common terms 165 degrees 1/2/3 coefficient bits 256 | 0.642425 | 0.669135 | 1.04× | 3 |
| generated GCD auto: high-height 8 variables asymmetric cofactor terms 8/45 common terms 165 degrees 1/2/3 coefficient bits 256 | 8.343349 | 10.554260 | 1.26× | 3 |
| rational GCD control: divisible, power 2 | 0.008326 | 0.008075 | 0.97× | 3 |
| rational GCD control: proportional, power 2 | 0.003506 | 0.003336 | 0.952× | 3 |
| rational GCD control: coprime, power 2 | 0.012613 | 0.004299 | 0.341× | 3 |
| rational GCD control: shared factor, power 2 | 0.120398 | 0.080382 | 0.668× | 3 |
| rational GCD control: divisible, power 3 | 0.014528 | 0.014227 | 0.979× | 3 |
| rational GCD control: proportional, power 3 | 0.009278 | 0.007565 | 0.815× | 3 |
| rational GCD control: coprime, power 3 | 0.014237 | 0.008456 | 0.594× | 3 |
| rational GCD control: shared factor, power 3 | 0.195760 | 0.135486 | 0.692× | 3 |
| rational GCD control: divisible, power 4 | 0.025448 | 0.023645 | 0.929× | 3 |
| rational GCD control: proportional, power 4 | 0.016631 | 0.014277 | 0.858× | 3 |
| rational GCD control: coprime, power 4 | 0.026600 | 0.014738 | 0.554× | 3 |
| rational GCD control: shared factor, power 4 | 0.297813 | 0.190049 | 0.638× | 3 |
| generated factor product: dense 1-variable degrees 32/31 | 0.004398 | 0.004679 | 1.06× | 3 |
| generated factorization: dense 1-variable degrees 32/31 | 6.544948 | 2.794685 | 0.427× | 3 |
| generated factor product: dense 2-variable degrees 10/9 | 0.008286 | 0.006242 | 0.753× | 3 |
| generated factorization: dense 2-variable degrees 10/9 | 3.527320 | 9.970035 | 2.83× | 3 |
| generated factor product: dense 3-variable degrees 6/5 | 0.006973 | 0.007093 | 1.02× | 3 |
| generated factorization: dense 3-variable degrees 6/5 | 1.167989 | 3.962985 | 3.39× | 3 |
| generated factor product: dense high-height 1-variable degrees 17/16 total 33 | 0.008536 | 0.010490 | 1.23× | 3 |
| generated factorization: dense high-height 1-variable degrees 17/16 total 33 | 1.288667 | 1.258260 | 0.976× | 3 |
| generated factor product: dense 1-variable degrees 33/31 total 64 | 0.004909 | 0.004359 | 0.888× | 3 |
| generated factorization: dense 1-variable degrees 33/31 total 64 | 2.830984 | 2.521418 | 0.891× | 3 |
| generated factor product: dense 1-variable degrees 33/32 total 65 | 0.004689 | 0.004809 | 1.03× | 3 |
| generated factorization: dense 1-variable degrees 33/32 total 65 | 3.893394 | 2.916475 | 0.749× | 3 |
| polybench GCD products: polybench 5v uniform nontrivial GCD #11 | 0.129394 | 0.168248 | 1.3× | 3 |
| polybench GCD: polybench 5v uniform nontrivial GCD #11 | 7.084999 | 12.092959 | 1.71× | 3 |
| polybench GCD products: polybench 5v sharp nontrivial GCD #11 | 0.079169 | 0.087896 | 1.11× | 3 |
| polybench GCD: polybench 5v sharp nontrivial GCD #11 | 1.995003 | 5.049429 | 2.53× | 3 |
| polybench GCD products: polybench 8v uniform nontrivial GCD #11 | 0.133312 | 0.164831 | 1.24× | 3 |
| polybench GCD: polybench 8v uniform nontrivial GCD #11 | 5.050070 | 9.427429 | 1.87× | 3 |
| polybench GCD products: polybench 8v uniform nontrivial GCD #55 | 0.118314 | 0.134885 | 1.14× | 3 |
| polybench GCD: polybench 8v uniform nontrivial GCD #55 | 5.437924 | 9.051618 | 1.66× | 3 |
| polybench GCD products: polybench 8v uniform nontrivial GCD #56 | 0.100730 | 0.119566 | 1.19× | 3 |
| polybench GCD: polybench 8v uniform nontrivial GCD #56 | 2.962943 | 8.617557 | 2.91× | 3 |
| polybench GCD products: polybench 8v uniform nontrivial GCD #168 | 0.116189 | 0.138803 | 1.19× | 3 |
| polybench GCD: polybench 8v uniform nontrivial GCD #168 | 3.817670 | 8.812235 | 2.31× | 3 |
| polybench GCD products: polybench 8v uniform nontrivial GCD #188 | 0.101983 | 0.114456 | 1.12× | 3 |
| polybench GCD: polybench 8v uniform nontrivial GCD #188 | 2.908911 | 7.422547 | 2.55× | 3 |
| polybench GCD products: polybench 8v sharp nontrivial GCD #11 | 0.081343 | 0.082165 | 1.01× | 3 |
| polybench GCD: polybench 8v sharp nontrivial GCD #11 | 2.334775 | 7.204655 | 3.09× | 3 |
| polybench GCD products: polybench 8v sharp nontrivial GCD #53 | 0.086905 | 0.082987 | 0.955× | 3 |
| polybench GCD: polybench 8v sharp nontrivial GCD #53 | 2.182057 | 6.491988 | 2.98× | 3 |
| polybench GCD products: polybench 8v sharp nontrivial GCD #35 | 0.097956 | 0.109707 | 1.12× | 3 |
| polybench GCD: polybench 8v sharp nontrivial GCD #35 | 2.251798 | 7.551281 | 3.35× | 3 |
| polybench GCD products: polybench 8v sharp nontrivial GCD #140 | 0.087104 | 0.117802 | 1.35× | 3 |
| polybench GCD: polybench 8v sharp nontrivial GCD #140 | 2.212775 | 6.483231 | 2.93× | 3 |
| polybench GCD products: polybench 8v uniform trivial GCD #11 | 0.137651 | 0.161696 | 1.17× | 3 |
| polybench GCD: polybench 8v uniform trivial GCD #11 | 0.493914 | 0.710854 | 1.44× | 3 |
| polybench factor product: polybench 5v uniform nontrivial factor #32 | 0.067678 | 0.080332 | 1.19× | 3 |
| polybench factorization: polybench 5v uniform nontrivial factor #32 | 8.796085 | 90.729883 | 10.3× | 3 |
| polybench factor product: polybench 5v uniform nontrivial factor #159 | 0.050185 | 0.058711 | 1.17× | 3 |
| polybench factorization: polybench 5v uniform nontrivial factor #159 | 9.701908 | 95.595434 | 9.85× | 3 |
| polybench factor product: polybench 5v uniform nontrivial factor #163 | 0.065193 | 0.077477 | 1.19× | 3 |
| polybench factorization: polybench 5v uniform nontrivial factor #163 | 8.362635 | 45.060716 | 5.39× | 3 |
| polybench factor product: polybench 5v uniform nontrivial factor #131 | 0.046397 | 0.055885 | 1.2× | 3 |
| polybench factorization: polybench 5v uniform nontrivial factor #131 | 7.196851 | 42.763722 | 5.94× | 3 |
| polybench factor product: polybench 8v sharp nontrivial factor #178 | 0.045927 | 0.050225 | 1.09× | 3 |
| polybench factorization: polybench 8v sharp nontrivial factor #178 | 3.228276 | 10.461945 | 3.24× | 3 |
| polybench factor product: polybench 8v sharp nontrivial factor #92 | 0.049814 | 0.053651 | 1.08× | 3 |
| polybench factorization: polybench 8v sharp nontrivial factor #92 | 6.933533 | 13.893123 | 2× | 3 |
| polybench factor product: polybench 8v sharp nontrivial factor #84 | 0.042681 | 0.046688 | 1.09× | 3 |
| polybench factorization: polybench 8v sharp nontrivial factor #84 | 6.028520 | 20.768967 | 3.45× | 3 |
| polybench factor product: polybench 8v sharp nontrivial factor #176 | 0.063390 | 0.061557 | 0.971× | 3 |
| polybench factorization: polybench 8v sharp nontrivial factor #176 | 20.830033 | 14.741357 | 0.708× | 3 |
| polybench factor product: polybench 8v uniform nontrivial factor #44 | 0.047550 | 0.053401 | 1.12× | 3 |
| polybench factorization: polybench 8v uniform nontrivial factor #44 | 13.774660 | 202.301220 | 14.7× | 3 |
| polybench factor product: polybench 8v uniform nontrivial factor #105 | 0.062258 | 0.071435 | 1.15× | 3 |
| polybench factorization: polybench 8v uniform nontrivial factor #105 | 16.651610 | 34.794081 | 2.09× | 3 |
| polybench factor product: polybench 8v uniform nontrivial factor #159 | 0.052059 | 0.061466 | 1.18× | 3 |
| polybench factorization: polybench 8v uniform nontrivial factor #159 | 13.670001 | 729.897789 | 53.4× | 3 |
| polynomial/resultant/g33D-res-01-1715cd542f | 0.102173 | 0.098616 | 0.965× | 3 |
| polynomial/discriminant/g33D-dis-05-eaa3ad4f21 | 0.795504 | 0.859956 | 1.08× | 3 |
| polynomial/resultant/g30base-res-01-81738fb00b | 0.249461 | 0.256815 | 1.03× | 3 |
| polynomial/resultant/g30base-res-04-526f9a9d80 | 0.018234 | 0.025809 | 1.42× | 3 |
| polynomial/discriminant/g30base-dis-07-c740dd2c56 | 0.133793 | 0.136859 | 1.02× | 3 |
| polynomial/resultant/fixedA377-res-00-c3f6f2e500 | 0.685206 | 0.806606 | 1.18× | 3 |
| polynomial/resultant/fixedA377-res-01-db885cb0b3 | 0.433169 | 0.502861 | 1.16× | 3 |
| polynomial/resultant/fixedA377-res-02-a5fe517439 | 0.220527 | 0.229554 | 1.04× | 3 |
| polynomial/resultant/fixedA377-res-03-8f93b7ef68 | 0.228191 | 0.248981 | 1.09× | 3 |
| polynomial/discriminant/fixedA377-dis-06-0b154e382f | 1.017885 | 1.256556 | 1.23× | 3 |
| polynomial/discriminant/fixedA377-dis-07-959550185e | 0.229845 | 0.228081 | 0.992× | 3 |
| polynomial/discriminant/fixedA377-dis-08-cf10338d93 | 0.091603 | 0.085272 | 0.931× | 3 |
| polynomial/resultant/symA5_31-res-00-dee965d81f | 0.009729 | 0.015178 | 1.56× | 3 |
| polynomial/resultant/symA5_31-res-01-9aba7cdcc3 | 0.010961 | 0.019638 | 1.79× | 3 |
| polynomial/resultant/symA5_31-res-02-ba5210d195 | 0.007384 | 0.014317 | 1.94× | 3 |
| polynomial/resultant/symA5_31-res-03-fc97cfbbef | 0.010309 | 0.018996 | 1.84× | 3 |
| polynomial/resultant/g33S2-res-12-0bcabfb761 | 87.792417 | 142.555943 | 1.62× | 3 |
| polynomial/resultant/g33S2-res-13-9b5ef38ded | 20.988072 | 32.878448 | 1.57× | 3 |
| polynomial/resultant/g33S2-res-17-fc148e65de | 0.146236 | 0.172586 | 1.18× | 3 |
| polynomial/resultant/g33S2-res-19-21abb3fee9 | 0.017704 | 0.036599 | 2.07× | 3 |
| polynomial/discriminant/g33S2-dis-27-60776320bd | 0.020679 | 0.023203 | 1.12× | 3 |
| polynomial/resultant/symA317-res-03-db3a4322d9 | 34.840118 | 56.043726 | 1.61× | 3 |
| polynomial/resultant/symA317-res-06-ff0b838eb1 | 0.074351 | 0.094279 | 1.27× | 3 |
| polynomial/resultant/symA317-res-07-c1b2d66c5c | 0.042641 | 0.055966 | 1.31× | 3 |
| polynomial/resultant/symA317-res-08-4dd94dfa1e | 0.002314 | 0.014528 | 6.28× | 3 |
| polynomial/resultant/g33S2-res-02-41f64e7684-segenc | 10754.930289 | 11758.085403 | 1.09× | 3 |
| polynomial/factor/g33D-fac-08-967b2265b1 | 1.291292 | 2.364812 | 1.83× | 3 |
| polynomial/gcd/g33D-fac-08-967b2265b1 | 0.275811 | 0.958843 | 3.48× | 3 |
| polynomial/factor/g33D-fac-09-a4744cff24 | 0.123163 | 0.222461 | 1.81× | 3 |
| polynomial/factor/g33D-fac-10-abe6a8ebdd | 0.285730 | 0.426837 | 1.49× | 3 |
| polynomial/gcd/g33D-fac-10-abe6a8ebdd | 0.080562 | 0.243260 | 3.02× | 3 |
| polynomial/factor/g33D-fac-11-d2c3440e52 | 0.170844 | 0.622708 | 3.64× | 3 |
| polynomial/gcd/g33D-fac-11-d2c3440e52 | 0.014097 | 0.021241 | 1.51× | 3 |
| polynomial/factor/g33D-fac-12-124c41fcf7 | 0.054363 | 0.054303 | 0.999× | 3 |
| polynomial/factor/g30base-fac-10-de301fb47b | 0.709812 | 0.415366 | 0.585× | 3 |
| polynomial/factor/g30base-fac-11-7421067c62 | 0.452656 | 0.263649 | 0.582× | 3 |
| polynomial/factor/g30base-fac-12-6a00291643 | 0.271173 | 0.353117 | 1.3× | 3 |
| polynomial/factor/g30base-fac-13-399b6b3505 | 0.247928 | 0.211891 | 0.855× | 3 |
| polynomial/factor/g30base-fac-14-45bf0db98e | 0.065604 | 0.115629 | 1.76× | 3 |
| polynomial/factor/g30base-fac-15-a0ed6c27bf | 0.018695 | 0.041999 | 2.25× | 3 |
| polynomial/factor/fixedA377-fac-10-ed80d981cd | 0.639349 | 0.515725 | 0.807× | 3 |
| polynomial/factor/fixedA377-fac-11-79a6584b20 | 0.246536 | 0.266484 | 1.08× | 3 |
| polynomial/factor/fixedA377-fac-12-09df769d8f | 0.138682 | 0.156887 | 1.13× | 3 |
| polynomial/factor/fixedA377-fac-13-86542ce6d5 | 0.930770 | 0.673463 | 0.724× | 3 |
| polynomial/factor/fixedA377-fac-14-ead5d84725 | 0.080582 | 0.109027 | 1.35× | 3 |
| polynomial/factor/fixedA377-fac-15-07877f0571 | 0.010129 | 0.021510 | 2.12× | 3 |
| polynomial/factor/symA5_31-fac-10-b7e40fd7bb | 0.289978 | 0.641543 | 2.21× | 3 |
| polynomial/gcd/symA5_31-fac-10-b7e40fd7bb | 0.009448 | 0.016000 | 1.69× | 3 |
| polynomial/factor/symA5_31-fac-11-b93dca9a03 | 0.175121 | 0.787930 | 4.5× | 3 |
| polynomial/gcd/symA5_31-fac-11-b93dca9a03 | 0.047720 | 0.369388 | 7.74× | 3 |
| polynomial/factor/symA5_31-fac-12-4262afaab8 | 0.102815 | 0.108035 | 1.05× | 3 |
| polynomial/factor/symA5_31-fac-13-b08fda434b | 0.184539 | 0.265963 | 1.44× | 3 |
| polynomial/gcd/symA5_31-fac-13-b08fda434b | 0.154913 | 0.808189 | 5.22× | 3 |
| polynomial/factor/symA5_31-fac-14-9ed62b27e5 | 0.008636 | 0.026851 | 3.11× | 3 |
| polynomial/factor/symA5_31-fac-15-7db2f4e614 | 0.013015 | 0.023925 | 1.84× | 3 |
| polynomial/factor/g33S2-fac-28-3a75cafd52 | 289.446154 | 1536.940330 | 5.31× | 3 |
| polynomial/gcd/g33S2-fac-28-3a75cafd52 | 266.477960 | 472.163566 | 1.77× | 3 |
| polynomial/factor/g33S2-fac-35-b4319ee36c | 168.782971 | 299.600706 | 1.78× | 3 |
| polynomial/gcd/g33S2-fac-35-b4319ee36c | 132.354732 | 228.783757 | 1.73× | 3 |
| polynomial/factor/g33S2-fac-36-b41f46e3ca | 15.889087 | 16.547252 | 1.04× | 3 |
| polynomial/gcd/g33S2-fac-36-b41f46e3ca | 7.933443 | 9.696256 | 1.22× | 3 |
| polynomial/factor/g33S2-fac-37-12e6b014e4 | 4.160629 | 6.619368 | 1.59× | 3 |
| polynomial/gcd/g33S2-fac-37-12e6b014e4 | 1.722207 | 4.814735 | 2.8× | 3 |
| polynomial/factor/g33S2-fac-38-fd912ec349 | 2.712078 | 2.566344 | 0.946× | 3 |
| polynomial/gcd/g33S2-fac-38-fd912ec349 | 0.975666 | 1.350765 | 1.38× | 3 |
| polynomial/factor/g33S2-fac-39-035774c28d | 1.416438 | 1.644630 | 1.16× | 3 |
| polynomial/gcd/g33S2-fac-39-035774c28d | 0.429042 | 0.842784 | 1.96× | 3 |
| polynomial/factor/g33S2-fac-40-2e7bf33ca7 | 0.657042 | 0.543618 | 0.827× | 3 |
| polynomial/gcd/g33S2-fac-40-2e7bf33ca7 | 0.242508 | 0.230346 | 0.95× | 3 |
| polynomial/factor/g33S2-fac-41-a2d1fd70cf | 0.140896 | 0.184890 | 1.31× | 3 |
| polynomial/gcd/g33S2-fac-41-a2d1fd70cf | 0.011511 | 0.021180 | 1.84× | 3 |
| polynomial/factor/symA317-fac-15-83da5119a0 | 2.485400 | 4.183572 | 1.68× | 3 |
| polynomial/gcd/symA317-fac-15-83da5119a0 | 1.998830 | 4.930143 | 2.47× | 3 |
| polynomial/factor/symA317-fac-16-37628a37c1 | 1.538278 | 6.071693 | 3.95× | 3 |
| polynomial/gcd/symA317-fac-16-37628a37c1 | 1.839368 | 7.651950 | 4.16× | 3 |
| polynomial/factor/symA317-fac-17-4521c9cb95 | 0.456152 | 1.147790 | 2.52× | 3 |
| polynomial/gcd/symA317-fac-17-4521c9cb95 | 0.054664 | 0.079831 | 1.46× | 3 |
| polynomial/factor/symA317-fac-18-b3e6617037 | 0.486460 | 1.750210 | 3.6× | 3 |
| polynomial/gcd/symA317-fac-18-b3e6617037 | 0.166174 | 0.914128 | 5.5× | 3 |
| polynomial/factor/symA317-fac-19-593adb827e | 0.033814 | 0.064221 | 1.9× | 3 |
Measurement and reproduction
Download the timings (CSV) · Download the plot (SVG) · Run metadata
Measured on 20 October 2026, on an AMD Ryzen 9 5900X running Linux x86-64. Both libraries use one thread, pinned to the same logical CPU. Each operation gets one untimed warmup and three measured samples; the plot shows the median. Symbolica-first and FLINT-first measurements alternate. Input construction, parsing, correctness checks, and dropping the output are outside the timer; allocation of the output is included.
Symbolica uses the native Rust workspace at 3bbffc2e (package version 3.0.1), compiled with Rust 1.99.0 and native CPU optimizations. FLINT is 3.6.0, linked through flint3-sys 3.6.1.
The suite covers generated dense and sparse inputs, integer and rational coefficients, finite fields, and fixtures from polybench (seed 42, generator revision f3a25498).
The polynomial fixtures cover 36 factorizations, 18 derivative-based GCDs, 25 multivariate resultants and discriminants, and one large segmentation-encoded resultant. Their inputs and source hashes are recorded in the committed fixture manifest. Fixture factorization and GCD, and the 12 rational GCD controls, use rational polynomials in Symbolica and integer polynomials in FLINT; GCDs are compared after monic normalization. Resultants and discriminants use integer inputs. The large encoded case uses FLINT’s univariate Euclidean resultant. All inputs, factor reconstructions, and exact outputs are checked before timing.
To reproduce, check out the revision above and use the benchmark source:
SYMBOLICA_FLINT_BENCH_PAIRED=1 \
SYMBOLICA_FLINT_BENCH_CSV=1 \
SYMBOLICA_FLINT_BENCH_SAMPLES=3 \
cargo bench --bench flint_comparison --features flint_benchmarks \
> flint-comparison-results.csvThe flint_benchmarks feature builds its bundled FLINT. To match this run’s installed FLINT 3.6.0, use --features flint_system_benchmarks with that version available through pkg-config. On Linux, pin the benchmark process to a CPU with taskset -c 0. The complete paired results are retained, including cases where FLINT is faster; this workload selection is not an overall library ranking.
Numerical evaluation
Symbolica can turn large symbolic expressions into fast numerical code. These benchmarks compare the resulting native programs on two inputs: the F13 polynomial and a nested analytic expression containing polynomials, exponentials, sines, and cosines.
Evaluation time measures how fast the generated program runs. Generation time and peak memory measure the cost of building that program. Lower is better in all three plots. Generation time uses a logarithmic scale to show results ranging from fractions of a second to many minutes. Hatched memory bars marked ≥ show lower bounds observed before a build failed.
F13 polynomial
105,114 terms in 29 variables. Symbolica evaluates F13 1.39× as fast as FORM O4.
Exact measurements
| Native program | Evaluation / point | Generate code | Peak build memory |
|---|---|---|---|
| Symbolica | 5.64 µs | 5.62 s | 173 MiB |
| FORM O4 | 7.87 µs | 3.3 min | 813 MiB |
| FORM O2 | 8.96 µs | 2.1 min | 822 MiB |
| Mathematica | GCC compilation failed | GCC compilation failed | ≥ 4,892 MiB |
Mathematica’s generated C is very large and triggers an internal compiler error in GCC.
Nested analytic expression
A large expression in seven variables, containing polynomial products, exponentials, sines, and cosines.
Exact measurements
| Native program | Evaluation / point | Generate code | Peak build memory |
|---|---|---|---|
| Symbolica · nested | 3.63 µs | 0.68 s | 148 MiB |
| Mathematica · nested | 33.92 µs | 1.9 min | 1,922 MiB |
| Symbolica · expanded | 46.24 µs | 1.1 min | 2,233 MiB |
| Mathematica · expanded | GCC compilation failed | GCC compilation failed | ≥ 15,674 MiB |
| FORM O4 | 61.66 µs | 34.2 min | 3,019 MiB |
| FORM CSEGreedy | 72.38 µs | 14.6 min | 3,534 MiB |
FORM cannot represent nested expressions and does not optimize arithmetic inside. The above demonstration shows that not being able to represent nested expressions comes at a large performance cost. For a more direct comparison, we expanded the Symbolica output before optimizing, and the resulting code is still faster than FORM’s output.
Mathematica’s original nested input compiled successfully, however the fully expanded input triggered a GCC internal compiler error after reaching ≥ 15,674 MiB of process-tree memory.
Arithmetic counts and generation stages
| Input | Native program | Multiplications | Additions | Function calls | Evaluation / point |
|---|---|---|---|---|---|
| F13 polynomial | Symbolica | 18,538 | 26,965 | 0 | 5.64 µs |
| F13 polynomial | FORM O4 | 17,536 | 27,314 | 0 | 7.87 µs |
| F13 polynomial | FORM O2 | 27,421 | 29,385 | 0 | 8.96 µs |
| Nested analytic expression | Symbolica | 3,220 | 22,243 | 24 | 3.63 µs |
| Nested analytic expression | FORM O4 | 181,610 | 190,520 | 24 | 61.66 µs |
| Nested analytic expression | FORM CSEGreedy | 199,019 | 193,707 | 24 | 72.38 µs |
| Nested analytic expression | Mathematica | 92,007 | 27,622 | 24 | 33.92 µs |
| Nested analytic expression · expanded | Symbolica | 162,371 | 193,916 | 24 | 46.24 µs |
| Nested analytic expression · expanded | FORM O4 | 181,610 | 190,520 | 24 | 62.35 µs |
| Nested analytic expression · expanded | FORM CSEGreedy | 199,019 | 193,707 | 24 | 73.08 µs |
FORM O4 uses fewer arithmetic operations on F13, while Symbolica’s native program evaluates faster in this measurement. Operation counts alone do not determine execution time. Multiplication counts include negations (sign changes) for every system. Integer powers also count as multiplications using repeated squaring: for example, \(x^4\) counts as two multiplications. Function calls are counted separately; a divisions column appears only when needed.
| Symbolica input | Parse | Expand | Optimize | Native compile | Total build |
|---|---|---|---|---|---|
| F13 polynomial | 0.23 s | 0.00 s | 5.51 s | 0.11 s | 5.86 s |
| Nested analytic expression | 0.07 s | 0.00 s | 0.55 s | 0.05 s | 0.68 s |
| Nested analytic expression · expanded | 0.07 s | 6.26 s | 59.71 s | 0.90 s | 66.91 s |
Complete results · Build memory measurements · Additional constructor memory measurements, including 128 non-inlined functions with 90.5 MiB of expression bodies.
Run the examples
Download F13 or the nested analytic expression, the Python runner, and its reference points into one folder. Use the Symbolica source build identified above, with NumPy installed:
python run-output-example.py --case f13
python run-output-example.py --case nested
python run-output-example.py --case nested-expandedThe runner builds the native evaluator and checks it against 32 independent reference points. To use the nested expression directly:
from symbolica import E, S
expression = E(open("large_nested.txt").read())
parameters = [S(f"x{i}") for i in range(7)]
evaluator = expression.evaluator(
parameters, iterations=10, n_cores=1,
horner_use_cpe=True, jit_compile=False,
)
evaluator.jit_compile(True, direct_translation=True, optimization_level=3)
print(evaluator.evaluate([[0.125] * 7]))For FORM, this complete input file generates the optimized arithmetic for the nested expression; save it beside large_nested.txt and run form benchmark.frm:
Symbols x0,x1,x2,x3,x4,x5,x6;
CFunctions exp,sin,cos;
Local F =
#include large_nested.txt
;
.sort
ExtraSymbols,array,w;
Format C;
Format O4;
#optimize F
#write <generated.inc> "double w[1+`optimmaxvar_'];"
#write <generated.inc> "%O"
#write <generated.inc> "double result = %e",F
.end
The full nested harness supplies the C++ wrapper and Mathematica Compile route; keep its shared helper beside it. Mathematica’s input uses the same expression with function-call syntax translated.
To reproduce the source build, apply the source patch to Symbolica commit 3bbffc2ecb32, use the supplied Cargo lockfile, and build a release wheel with maturin build --release --locked. The horner_use_cpe option ranks each Horner candidate after common-pair elimination; final pair elimination runs to completion. Ten candidates are tried per algebraic region.
Method, platform limitations, and raw data
Symbolica and paired FORM evaluation timings were measured on 20 October 2026, AMD Ryzen 9 5900X, Linux x86-64, pinned to logical CPU 10. Python 3.12.13, NumPy 2.5.4, and Symbolica development build 16e6fcfb. Symbolica uses scalar real SymJIT at optimization level three. The retained FORM 5.0.1 programs were compiled with GCC 16.2.1, -O3 -march=native, without fast-math. O4 uses its default 1,000 simulated-annealing iterations; O2 and CSEGreedy use their recorded defaults without a greedy time cutoff.
Each timing session warms up all programs and alternates their execution order. Batches contain 4,096 points for F13 and 1,024 for the nested expression. Output allocation is included; numerical verification is outside the timer. Every program passes the same independent 32-point check before and after timing, and Symbolica’s evaluator is also checked after serialization and reload. Speed ratios are medians of paired rounds; they can differ slightly from ratios of the plotted medians. These workloads are examples, not an overall system ranking.
Mathematica uses Wolfram Engine 13.2.0, Compile with expression optimization, the C target, listable real arguments, and no callbacks to the interpreter. Its original nested results are from 19 October on the same machine, measured through the native compiled function in the Wolfram kernel; they were not retimed in the interleaved Python session. FORM and Mathematica build costs are from the original 17–19 October runs. Raw records retain each run’s date, CPU affinity, compiler commands, and sampling details.
FORM expands products, so it cannot retain the original nested products in an ordinary expression. Its output optimizer also leaves arithmetic inside function arguments unoptimized, as demonstrated by this small example and its output. The expanded Symbolica case expands the outer expression and every elementary-function argument, without applying trigonometric identities.
Mathematica-generated C has repeatedly triggered GCC internal compiler errors on these large inputs. The F13 attempts failed with expression optimization off and on; the expanded nested attempt also failed. These are compilation failures, so no runtime is assigned to them. The completed original nested Mathematica runs are included above and in the original measurements.
F13 polynomial · Nested analytic expression · Nested analytic expression · expanded
The complete summary links the three builds for each input. All timing samples, program hashes, compiler settings, and validation results are retained in those files. Timing driver · Shared timing helper · Memory profiler · Arithmetic counter.
Memory efficiency
Compare the same expression before and after expansion:
\[ P_n = \prod_{i=1}^{n}(1+a+b+c+f(i)). \]
The factored comparison uses 100,000 factors, each with a distinct function argument. The expanded comparison uses 10 factors, producing 66,304 terms. These are separate workloads, not a before/after comparison at the same value of \(n\).
For the expanded case, Symbolica’s specialized Polynomial representation is smaller and supports faster polynomial arithmetic than working with a general expression.
Mathematica and SymPy can share repeated subexpressions, recycling common parts instead of storing every occurrence separately. FORM’s native term representation stores repeated parts inline. Symbolica’s general expression representation also stores its packed payload directly, but the Rust API’s AliasedAtom lets you introduce explicit aliases for common subexpressions.
FORM does not support factored expressions, and therefore each factor had to be wrapped in a function. Due to maximum term limits, FORM 5.0.1 failed to construct the factored product with 100,000 factors. Generating the expanded product required careful treatment: a factor must be expanded one at a time with a .sort after every multiplication, to prevent a rapid growth of intermediate terms.
Measurement and reproduction
Factored-product measurements · Expanded-product measurements · Complete benchmark script
Measured on 16 October 2026, on an AMD Ryzen 9 5900X running Linux x86-64, pinned to one logical CPU. Software: Symbolica 3.0.2, FORM 5.0.1, Wolfram Engine 13.2.0, SymPy 1.14.0, and Python 3.12.13. These results apply to these workloads and versions, including the older Wolfram Engine available for this run.
The factored validator checks every sum and requires exactly the distinct indices \(1,\ldots,n\). FORM’s internal wrappers must preserve those same sums. The expanded validator checks the term count and an exact evaluation with a different value for every function call.
FORM’s 10,000-factor construction attempts failed, including attempts with larger buffers and a balanced construction. No FORM value is plotted for the 100,000-factor case; the raw data records the failed attempts.
The engine-specific counters are:
- Symbolica:
expression.get_byte_size(), its packed expression payload, excluding the Python wrapper and global symbol definitions. - FORM: uncompressed
Bytes usedwithOff Compress;, cross-checked againstsizeof_(Expression)and an in-memory dollar variable. FORM words occupy four bytes in this build. - Mathematica: live kernel bytes released when deleting the expression, after
ClearSystemCache[], with history disabled and an empty-expression control. Normal construction and construction followed byShareuse separate fresh kernels. Shared branches count once.ByteCount, which ignores sharing, is recorded only as a diagnostic. - SymPy: live Python allocations released after clearing SymPy caches, deleting the expression, and collecting garbage, measured with
tracemalloc. Tracing starts before construction; an empty control corrects measurement overhead.
These are representation-storage counters, not total process RAM or peak memory. Startup, unused allocator reserves, construction workspaces, and external caches are excluded. All individual samples and failed FORM attempts are retained in the raw data.
Install uv and make an activated wolframscript and form available on your path. From the folder containing the downloaded script:
uv run expression-storage.py --case factored_indexed_functions --factors 100000 --engines symbolica mathematica sympy --runs 3 --output factored-product-storage-results.json
uv run expression-storage.py --case indexed_functions --factors 10 --runs 3 --output indexed-product-storage-results.jsonThe script installs pinned Python packages in an isolated environment. FORM construction limits are included in the script; the measured expression counter excludes those workspaces.