[PATCH] optimize "*" in SMP

13 views
Skip to first unread message

Qian Yun

unread,
Jun 28, 2026, 7:40:18 PM (4 days ago) Jun 28
to fricas-devel
This patch saves allocation when one of the multiplicand
is the unit polynomial.

For mapleok.input, it saves 0.8% memory.

(This is actually on the hot path of =$EXPR, where likely
that one of the multiplicand is 1.
Also this is real-world saving of 0.8%. In hand-crafted
benchmarks, it can be much higher.)

- Qian

diff --git a/src/algebra/multpoly.spad b/src/algebra/multpoly.spad
index 62a232e1..4385232c 100644
--- a/src/algebra/multpoly.spad
+++ b/src/algebra/multpoly.spad
@@ -375,10 +375,13 @@
false

p1 * p2 ==
- p1 case R => p1::R * p2
+ p1 case R =>
+ one?(p1::R) => p2
+ p1::R * p2
p2 case R =>
+ one?(p2::R) => p1
mvar := p1.v
- up := p1.ts*p2
+ up := p1.ts * (p2::R)
if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
p1.v = p2.v =>
mvar := p1.v

Waldek Hebisch

unread,
Jun 28, 2026, 7:59:44 PM (4 days ago) Jun 28
to fricas...@googlegroups.com
On Mon, Jun 29, 2026 at 07:40:13AM +0800, Qian Yun wrote:
> This patch saves allocation when one of the multiplicand
> is the unit polynomial.
>
> For mapleok.input, it saves 0.8% memory.
>
> (This is actually on the hot path of =$EXPR, where likely
> that one of the multiplicand is 1.
> Also this is real-world saving of 0.8%. In hand-crafted
> benchmarks, it can be much higher.)

OK, please commit.

> diff --git a/src/algebra/multpoly.spad b/src/algebra/multpoly.spad
> index 62a232e1..4385232c 100644
> --- a/src/algebra/multpoly.spad
> +++ b/src/algebra/multpoly.spad
> @@ -375,10 +375,13 @@
> false
>
> p1 * p2 ==
> - p1 case R => p1::R * p2
> + p1 case R =>
> + one?(p1::R) => p2
> + p1::R * p2
> p2 case R =>
> + one?(p2::R) => p1
> mvar := p1.v
> - up := p1.ts*p2
> + up := p1.ts * (p2::R)
> if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
> p1.v = p2.v =>
> mvar := p1.v
>
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/ff102520-d143-490f-901c-1ca2334628a6%40gmail.com.

--
Waldek Hebisch

Qian Yun

unread,
Jun 29, 2026, 5:22:26 AM (4 days ago) Jun 29
to fricas...@googlegroups.com
Just submitted a fixup for this:
https://github.com/fricas/fricas/commit/4073d787364979304a7419b39e80fe028c395412.patch

And then I noticed that
PolynomialCategory has VariablesCommuteWithCoefficients
so it could be further simplified:

diff --git a/src/algebra/multpoly.spad b/src/algebra/multpoly.spad
index e3c0f082..c6787ee6 100644
--- a/src/algebra/multpoly.spad
+++ b/src/algebra/multpoly.spad
@@ -334,12 +334,13 @@
if ground? up then leadingCoefficient(up) else [mvar,
up]$VPoly

c * p ==
- c = 0 => 0
+ zero? c => 0
c = m_one => p
p case R => c * p::R
mvar := p.v
up := c*p.ts
if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
+
p1 + p2 ==
p1 case R and p2 case R => p1 +$R p2
p1 case R => [p2.v, p1::D + p2.ts]$VPoly
@@ -376,13 +377,7 @@

p1 * p2 ==
p1 case R => p1::R * p2
- p2 case R =>
- -- the same technique as '* : (R, %) -> %' above
- zero?(p2::R) => 0
- p2::R = m_one => p1
- mvar := p1.v
- up := p1.ts * p2
- if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
+ p2 case R => p2::R * p1
p1.v = p2.v =>
mvar := p1.v
up := p1.ts*p2.ts

Waldek Hebisch

unread,
Jun 29, 2026, 6:52:13 AM (4 days ago) Jun 29
to fricas...@googlegroups.com
On Mon, Jun 29, 2026 at 05:22:21PM +0800, Qian Yun wrote:
> Just submitted a fixup for this:
> https://github.com/fricas/fricas/commit/4073d787364979304a7419b39e80fe028c395412.patch
>
> And then I noticed that
> PolynomialCategory has VariablesCommuteWithCoefficients
> so it could be further simplified:

Variables commute with coefficients, but coefficients may be
noncommutative, like:

POLY(SQMATRIX(2, INT))

So order still matters.
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/7987ed50-6943-4a77-bd12-4eb0726e0881%40gmail.com.

--
Waldek Hebisch

Qian Yun

unread,
Jun 29, 2026, 7:34:33 AM (4 days ago) Jun 29
to fricas...@googlegroups.com
Ah. For
f1 : (POLY INT, INT) -> POLY INT := *$POLY INT
shows the implementation is in MODULE.

But that is for CommutativeRing.

For
T ==> POLY SQMATRIX(2, INT)
f2 : (T, SquareMatrix(2,Integer)) -> T := *$T
the implementation is missing.

- Qian

Qian Yun

unread,
Jun 29, 2026, 7:43:38 AM (4 days ago) Jun 29
to fricas...@googlegroups.com
How about this patch in attachment?

- Qian
mult-in-smp.patch

Waldek Hebisch

unread,
Jun 29, 2026, 9:43:47 AM (4 days ago) Jun 29
to fricas...@googlegroups.com
On Mon, Jun 29, 2026 at 07:43:34PM +0800, Qian Yun wrote:
> How about this patch in attachment?

Looks OK.

> On 6/29/26 7:34 PM, Qian Yun wrote:
> > Ah. For
> > f1 : (POLY INT, INT) -> POLY INT := *$POLY INT
> > shows the implementation is in MODULE.
> >
> > But that is for CommutativeRing.
> >
> > For
> > T ==> POLY SQMATRIX(2, INT)
> > f2 : (T, SquareMatrix(2,Integer)) -> T := *$T
> > the implementation is missing.
> >

> diff --git a/src/algebra/multpoly.spad b/src/algebra/multpoly.spad
> index e3c0f082..5e301513 100644
> --- a/src/algebra/multpoly.spad
> +++ b/src/algebra/multpoly.spad
> @@ -334,12 +334,21 @@ SparseMultivariatePolynomial(R : Join(SemiRng, AbelianMonoid),
> if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
>
> c * p ==
> - c = 0 => 0
> + zero? c => 0
> c = m_one => p
> p case R => c * p::R
> mvar := p.v
> up := c*p.ts
> if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
> +
> + p * c ==
> + zero? c => 0
> + c = m_one => p
> + p case R => p::R * c
> + mvar := p.v
> + up := p.ts * c
> + if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
> +
> p1 + p2 ==
> p1 case R and p2 case R => p1 +$R p2
> p1 case R => [p2.v, p1::D + p2.ts]$VPoly
> @@ -376,13 +385,7 @@ SparseMultivariatePolynomial(R : Join(SemiRng, AbelianMonoid),
>
> p1 * p2 ==
> p1 case R => p1::R * p2
> - p2 case R =>
> - -- the same technique as '* : (R, %) -> %' above
> - zero?(p2::R) => 0
> - p2::R = m_one => p1
> - mvar := p1.v
> - up := p1.ts * p2
> - if ground? up then leadingCoefficient(up) else [mvar, up]$VPoly
> + p2 case R => p1 * p2::R
> p1.v = p2.v =>
> mvar := p1.v
> up := p1.ts*p2.ts


--
Waldek Hebisch

Waldek Hebisch

unread,
Jun 29, 2026, 8:02:29 PM (3 days ago) Jun 29
to fricas...@googlegroups.com
On Mon, Jun 29, 2026 at 07:40:13AM +0800, Qian Yun wrote:
The patch caused change to output below. It stays also after
commit 4073d787364979304a7419b39e80fe028c395412 (Fixup previous
commit)

This is expample page for UnivariatePolynomial. '1' below should
not be there.

--- ../fr-build582/target/x86_64-linux-gnu/share/hypertex/pages/UP.pht 2026-06-29 23:41:14.739896493 +0000
+++ target/x86_64-linux-gnu/share/hypertex/pages/UP.pht 2026-06-29 23:52:46.678535855 +0000
@@ -580,11 +580,11 @@
\pastebutton{UnivariatePolynomialXmpPageFull34}{\hidepaste}
\tab{5}\spadcommand{u : FRAC POLY INT := t\bound{u }\free{t }}
\indentrel{3}\begin{verbatim}
- 2 2 2 2
- a1 b2 + (b1 - b1 + 3 a1 - a1)b2 - 3 a1
- (34) -----------------------------------------
- 2
- b2 + 3 b2
+ 2 2 2 2
+ a1 b2 + (1 b1 - b1 + 3 a1 - a1)b2 - 3 a1
+ (34) -------------------------------------------
+ 2
+ b2 + 3 b2
Type: Fraction(Polynomial(Integer))
\end{verbatim}
\indentrel{-3}\end{paste}\end{patch}
--
Waldek Hebisch

Qian Yun

unread,
Jun 29, 2026, 9:44:21 PM (3 days ago) Jun 29
to fricas...@googlegroups.com
It exposes a bug in interpreter coercion code.

The following code should fix it.

- Qian


diff --git a/src/interp/i-coerfn.boot b/src/interp/i-coerfn.boot
index bf163080..792f1cd6 100644
--- a/src/interp/i-coerfn.boot
+++ b/src/interp/i-coerfn.boot
@@ -1511,7 +1511,9 @@ Up2P(u,source is [.,var,S],target is [.,T]) ==
multfunc := getFunctionFromDomain("*",target,[target,target])
for [e,:c] in u until not x repeat
x:= coerceInt(objNewWrap(c,S),target) =>
- term:= SPADCALL([1,var,[e,0,:one]],objValUnwrap(x),multfunc)
+ term :=
+ e = 0 => objValUnwrap(x)
+ SPADCALL([1, var, [e, 0, :one]], objValUnwrap(x), multfunc)
pol:= SPADCALL(pol,term,plusfunc)
coercionFailure()
x => pol

Waldek Hebisch

unread,
Jun 30, 2026, 2:42:59 AM (3 days ago) Jun 30
to fricas...@googlegroups.com
On Tue, Jun 30, 2026 at 09:44:16AM +0800, Qian Yun wrote:
> It exposes a bug in interpreter coercion code.
>
> The following code should fix it.

Thanks, please commit.
> --
> You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/fricas-devel/865c6d3d-49ef-4ee0-afda-c6aadb6c7a17%40gmail.com.

--
Waldek Hebisch
Reply all
Reply to author
Forward
0 new messages