Performance Improvements in Maple 2024
Operations on Matrices Containing Quantities with Units• A new Units indexing function has been created which allows a matrix, vector, or arrayto keep units separate from the data. This allows the data to be a single block of
hardware type values, including datatype=float[8] and datatype=complex[8].
LinearAlgebra and other package routines can then dispatch to fast hardware algorithms
providing optimal performance.
• Here is an example that creates a 100x100 matrix of random data, each element has
the unit of meters per second. Computing the inverse takes milliseconds, which is overa thousand times faster than the way done in previous versions which required
datatype=anything.

> M := LinearAlgebra:-RandomMatrix(100,datatype=float[8],shape=Unit(m/s)):> CodeTools:-Usage( LinearAlgebra:-MatrixInverse(M) ):memory used=413.27KiB, alloc change=0 bytes, cpu time=33.00ms, realtime=178.00ms, gc time=0ns• A matrix with the Units indexing function can be used seamlessly in place of a matrix
that has no indexing function, but keeps quantities with units. Such a matrix allows asingle unit for all data, different units on different entries, and even entries with no unit
assigned. The matrix will adapt to the situation.

> M := Matrix( 2, (i,j)->(10*i+j)*Unit(kg), shape=Unit(kg) );Md

11 kg 12 kg
21 kg 22 kg> M[1,1] := 1.23 * Unit(ohm);
M1, 1 d 1.23 W> M[1,2] := 17;
M1, 2 d 17
> M;
1.23 W

17

21 kg

22 kg

• Quantities assigned into the matrix will be converted into the default unit specified forthat matrix whenever possible.

> M[2,2] := 35.2 * Unit(lb);M2, 2 d 35.2 lb

> M;
1.23 W

1721 kg

15.96645142 kg• The unit and data can be easily separated, so algorithms can inspect and takeadvantage of the new structure as needed. In this example we perform a matrix powerby operating on just the data, and only apply a unit transformation at the end. Thiskind of manipulation is used behind the scenes in many built-in operations in theLinearAlgebra package.

> A := Matrix(2,(i,j)->(10*i+j)*Unit(m), shape=Unit(m), datatype=float[8] );
Ad

11. m 12. m
21. m 22. m> default_unit, data := op(rtable_split_unit(A));
default_unit, data d m,

11. 12.
««> newA := rtable_set_indfn(data^4,Units:-Simple:-simplify(default_unit^4));
newA d413557. m4 439164. m4768537. m4 816124. m4• The Units:-Simple package makes use of this new data structure by default whenpossible.

> with(Units:-Simple);`*`, `C`, `-`, `/`, `!`, !=, !O, `=`, `^`, arccos, arccosh, arccot, arccoth, arccsc, arccsch, arcsec, arcsech,arcsin, arcsinh, arctan, arctanh, argument, collect, combine, cos, cosh, cot, coth, csc, csch, diff, eval,evalc, evalr, exp, factor, frem, ln, log, log10, log2, max, min, piecewise, polar, root, sec, sech, shake, sin,sinh, sqrt, surd, tan, tanh, type, verify> A := <1,2;3,4>*Unit(m);
Adm2m

3m 4m
> B := <5,6;7,8>*Unit(s);
Bd

5s 6s
7s 8s

> C := A . B^(-1);
3msL2ms

2ms

L

ms

Cd> rtable_indfns(A);m> rtable_indfns(B);s> rtable_indfns(C);ms• For additional improvements involving units in Maple 2024, see Improvements in
Handling of Units in Maple 2024.

Floating-Point Matrix and Vector Initialization• Maple uses hardware double-precision floating-point representations when constructing
matrices and vectors specified with datatype=float[8]. On initialization Maple 2024 calls
directly to the evalhf implementation of known functions and avoids conversion fromhardware to software floats. Performance of examples such as the following has
dramatically sped up.

> tt:=time[real]():> signal:=Vector(10^5,i->sin(i*1.0),datatype=float[8]):> time[real]()-tt;
0.425

Faster Univariate Complex Solver• Maple 2024 contains a new solver for isolating and approximating all complex roots of a
univariate polynomial with numeric or complex(numeric) coefficients. This solver isavailable through the method=PW option of the RootFinding:-Isolate command. Except
when the domain option is given, the new solver is considerably faster than the oneused when method=HR is specified, in particular for high accuracy, and it is now thedefault when option complex is used. Here are a few examples and timing comparisons
for the two solvers.
• Random polynomial, increasing accuracy.

> f := randpoly(x, dense, coeffs=rand(-2^32+1..2^32-1), degree=512):

> CodeTools:-Usage(RootFinding:-Isolate(f, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=10, method=PW)):
memory used=6.80MiB, alloc change=0 bytes, cpu time=7.29s, real time=7.38s, gc time=0ns
memory used=5.61MiB, alloc change=0 bytes, cpu time=1.89s, real time=1.94s, gc time=0ns> CodeTools:-Usage(RootFinding:-Isolate(f, digits=15, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=15, method=PW)):
memory used=5.20MiB, alloc change=0 bytes, cpu time=8.18s, real time=8.18s, gc time=0ns
memory used=5.61MiB, alloc change=0 bytes, cpu time=1.96s, real time=1.96s, gc time=0ns> CodeTools:-Usage(RootFinding:-Isolate(f, digits=30, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=30, method=PW)):
memory used=5.42MiB, alloc change=0 bytes, cpu time=8.32s, real time=8.32s, gc time=0ns
memory used=5.57MiB, alloc change=0 bytes, cpu time=1.47s, real time=1.47s, gc time=0ns• Bernoulli polynomials, increasing degree.

> g1 := expand(bernoulli(128,x)):> CodeTools:-Usage(RootFinding:-Isolate(g1, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(g1, digits=10, method=PW)):
memory used=1.57MiB, alloc change=0 bytes, cpu time=13.20s, real time=13.20s, gc time=0ns
memory used=1.35MiB, alloc change=0 bytes, cpu time=2.00s, real time=2.00s, gc time=0ns> g2 := expand(bernoulli(255,x)):> CodeTools:-Usage(RootFinding:-Isolate(g2, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(g2, digits=10, method=PW)):
memory used=3.61MiB, alloc change=0 bytes, cpu time=65.20s, real time=65.21s, gc time=0ns
memory used=2.94MiB, alloc change=0 bytes, cpu time=4.63s, real time=4.63s, gc time=0ns

RootFinding• The EvaluateAtRoot command in the RootFinding package has a new option`avoidsymbolic`. Its main purpose is to improve the command's efficiency. Whenspecified, symbolic processing to ascertain whether the given root is an exact zero of aconstraint or not will be skipped. In general this will lead to weaker answers, e.g., FAIL

•

being returned instead of true or false .
• In the following example, the unique root of sys contained in sysroot is actually an exact
root of the non-strict inequality in cons .

> vars := [x, y];vars d x, y
> sys := [-7*x^5+22*x^4-55*x^3-94*x^2+87*x-56,-10*y^5+62*y^4-82*y^3+80*y^2-44*y+71];
sys d L7 x5 C 22 x4 L 55 x3 L 94 x2 C 87 x L 56, L10 y5 C 62 y4 L 82 y3 C 80 y2 L 44 y C 71
> sysroot := [[-228940483906911495/144115188075855872,-57235120976727867/36028797018963968],[338902091289333/70368744177664,
677804182578693/140737488355328]];228940483906911495
57235120976727867,L,144115188075855872
36028797018963968
677804182578693
140737488355328

sysroot dL

338902091289333,70368744177664> cons := [434*x^9-2043*x^8+6055*x^7-1085*x^6-10004*x^5+17167*x^4-6842*x^3+11542*x^2-6997*x <= -4648,-50*y^5+23*y^4+75*y^3-92*y^2+6*y+74 > 0];cons d 434 x9 L 2043 x8 C 6055 x7 L 1085 x6 L 10004 x5 C 17167 x4 L 6842 x3 C 11542 x2 L 6997 x% L4648, 0 ! L50 y5 C 23 y4 C 75 y3 L 92 y2 C 6 y C 74
> consSet := convert(cons, 'set');consSet d 434 x9 L 2043 x8 C 6055 x7 L 1085 x6 L 10004 x5 C 17167 x4 L 6842 x3 C 11542 x2
L 6997 x % L4648, 0 ! L50 y5 C 23 y4 C 75 y3 L 92 y2 C 6 y C 74
• By default, EvaluateAtRoot uses symbolic computation to prove that the first constraint
is satisfied:> CodeTools:-Usage(RootFinding:-EvaluateAtRoot(cons, sysroot, sys,vars));
memory used=3.14MiB, alloc change=0 bytes, cpu time=62.00ms, real time=75.00ms, gc time=0ns
true, false> CodeTools:-Usage(RootFinding:-EvaluateAtRoot(consSet, sysroot, sys,vars));
memory used=446.36KiB, alloc change=0 bytes, cpu time=10.00ms, realtime=10.00ms, gc time=0ns
false• When specifying the avoidsymbolic option and giving a maximum value of 100 for thefloating-point precision, the underlying numerical computation will not be able to provethat the first constraint is satisfied, and therefore FAIL is returned:> CodeTools:-Usage(RootFinding:-EvaluateAtRoot(cons, sysroot, sys,vars, 'avoidsymbolic' = true, 'threshold' = 100));
memory used=143.32KiB, alloc change=0 bytes, cpu time=3.00ms, real time=3.00ms, gc time=0ns
FAIL, false• Nevertheless, in the following calling sequence, where we are only interested in thetruth value of the logical conjunction of the two constraints, this weaker result is still
sufficient, since the 2nd constraint, and therefore the whole conjunction, is false :> CodeTools:-Usage(RootFinding:-EvaluateAtRoot(consSet, sysroot, sys,vars, 'avoidsymbolic' = true, 'threshold' = 100));
memory used=133.91KiB, alloc change=0 bytes, cpu time=3.00ms, real time=3.00ms, gc time=0ns
false

Quantifier Elimination• Significant performance improvements have been made to the QuantifierElimination
package, including faster evaluation at sample points by using RootFinding:EvaluateAtRoot and caching of intermediate results.
• The following examples are 6-7 times faster than Maple 2023.

> formula1 := forall([x,y,t], Implies(And(x^3+y^2-x=t, t^2=4/27, t<0),x^2+y^2>=rho));formula1 d cx, y, t , x3 C y2 L x = t o t2 =4ot!027

r % x2 C y2

> CodeTools:-Usage(QuantifierElimination:-QuantifierEliminate(formula1));
memory used=2.89GiB, alloc change=191.09MiB, cpu time=76.62s, real time=65.76s, gc time=13.37s
673038004593441041303
2692152018373764165185
2r L RootOf 729 _Z C 270 _Z L 83, L..L
1180591620717411303424
4722366482869645213696
2! 0 n r L RootOf 729 _Z C 270 _Z L 83, L

673038004593441041303..
1180591620717411303424

L

2692152018373764165185
4722366482869645213696

L

673038004593441041303
2692152018373764165185..L1180591620717411303424
4722366482869645213696

2= 0 n RootOf 729 _Z C 270 _Z L 83,
2

L r ! 0 o r L RootOf 27 _Z

L673038004593441041303
2692152018373764165185..L1180591620717411303424
4722366482869645213696

L 18 _Z L 13, L

2L r ! 0 o r L RootOf 27 _Z

64411164140810191969
1030578626252963071477..L
147573952589676412928
2361183241434822606848

2L RootOf 27 _Z L 18 _Z L 13, L!0 nr

64411164140810191969
1030578626252963071477..L
147573952589676412928
2361183241434822606848

2= 0 n RootOf 27 _Z L 18 _Z L 13, L

64411164140810191969..
147573952589676412928

L

1030578626252963071477
2361183241434822606848L

1817639706731237273789
908819853365618636881..L
4722366482869645213696
2361183241434822606848! 0 n r L RootOf 27 _Z L 4,

L1817639706731237273789
908819853365618636881..L
4722366482869645213696
2361183241434822606848= 0 n RootOf 27 _Z L 4,

L1817639706731237273789
908819853365618636881..L
4722366482869645213696
2361183241434822606848

L r ! 0 o 27 r ! L5 n 27 r2

L r ! 0 o r L RootOf 27 _Z L 4,22

2C 5 = 0 n L27 r ! 5 o r L RootOf 27 _Z L 18 _Z L 1, LL

121758772887344434585
2361183241434822606848

L30439693221836108653
121758772887344434585..L
590295810358705651712
2361183241434822606848

L 1, L

2! 0 n r L RootOf 27 _Z L 18 _Z L 1,2471563697544355191183
2361183241434822606848=0Lr!0or!0 nr = 0

1886254790177420764705
9444732965739290427392
2! 0 n r L RootOf 729 _Z C 270 _Z L 83,

1886254790177420764705
471563697544355191183..
9444732965739290427392 2361183241434822606848
L 83,

2= 0 n RootOf 27 _Z L 18 _Z

30439693221836108653
121758772887344434585..L590295810358705651712
2361183241434822606848

n Lr ! 0 o r L RootOf 729 _Z C 270 _Z L 83,..

30439693221836108653..
590295810358705651712

2= 0 n RootOf 729 _Z C 270 _Z

1886254790177420764705
471563697544355191183..
9444732965739290427392 2361183241434822606848

Lr!0o3r!1 n3rL1

> formula2 := exists([t__10,t__11,t__12,t__6,b__12,t__5], And(0<=t__10, 0<=t__11, 0<=t__12, 0<=t__6, 0<=b__12,t__10<=1, t__11<=1, t__12<=1, t__6<=1, b__12<=1,0<t__5, t__5<1, t__5^3-2*t__5^2+t__5<0, 0<t__5^3-2*t__5^2+t__5+1,
t__6+1-t__5=0, -t__5^2+t__10+t__5=0, t__5^2-t__11+t__12-2*
t__5+1=0,-t__5^2+t__11+2*t__5+b__12-2 = 0));formula2 d dt10, t11, t12, t6, b12, t5 , 0 % t10 o 0 % t11 o 0 % t12 o 0 % t6 o 0 % b12 o t10 % 1 o t11
3232% 1 o t12 % 1 o t6 % 1 o b12 % 1 o 0 ! t5 o t5 ! 1 o t5 L 2 t5 C t5 ! 0 o 0 ! t5 L 2 t5 C t5
222C 1 o t6 C 1 L t5 = 0 o Lt5 C t10 C t5 = 0 o t5 L t11 C t12 L 2 t5 C 1 = 0 o Lt5 C b12 C t11
C 2 t5 L 2 = 0> CodeTools:-Usage(QuantifierElimination:-QuantifierEliminate(formula2));
memory used=2.59GiB, alloc change=0 bytes, cpu time=72.46s, real time=62.72s, gc time=11.90s
false• In addition, the display of various data structures in the QuantifierElimination package
has been improved.

> formula := exists(x, x^2+b*x+c=0);
formula d d x, b x C x2 C c = 0> C := QuantifierElimination:-PartialCylindricalAlgebraicDecompose(formula, 'output'=['data']);CdVariables=c, b, x

Input Formula=d x, b x C x2 C c = 0# Cells=17

Projection polynomials for level 1=«

Projection polynomials for level 2=b2 L 4 c

Projection polynomials for level 3=b x C x2 C c

> GetLeafCells(C)[1..5];
2

Description=

c ! 0 o x ! RootOf _Z C b _Z C c, index = real1

Sample Point=c = L1, b = 0, x = L2Index=1, 1, 1,2

Description=c ! 0 o x = RootOf _Z C b _Z C c, index = real1

Sample Point=c = L1, b = 0, x = L1

Index

=

1, 1, 2

Description=c = 0 o b ! 0 o x ! RootOf _Z _Z C b , index = real1

Sample Point=c = 0, b = L1, x = L1

Index

=

2, 1, 1

Description=c = 0 o b ! 0 o x = RootOf _Z _Z C b , index = real1

Sample Point=c = 0, b = L1, x = 0

Index=2, 1, 2

Description=c = 0ob = 0ox!0Sample Point=c = 0, b = 0, x = L1Index=2, 2, 1,,,• The new GetCells method, which supersedes GetLeafCells, also has additional options
to control the output.

> r := GetCells(C, output=[samplepoints,descriptions]):> r[1][1..5];c = L1, b = 0, x = L2 , c = L1, b = 0, x = L1 , c = 0, b = L1, x = L1 , c = 0, b = L1, x = 0 , c = 0,b = 0, x = L1
> r[2][1..5];
22c ! 0 o x ! RootOf _Z C b _Z C c, index = real1 , c ! 0 o x = RootOf _Z C b _Z C c, index= real1 , c = 0 o b ! 0 o x ! RootOf _Z _Z C b , index = real1 , c = 0 o b ! 0 o x= RootOf _Z _Z C b , index = real1 , c = 0 o b = 0 o x ! 0Various Small Improvements• The ceil, floor, and round functions are 1.5-2x faster for some numeric arguments inMaple 2024.

> CodeTools:-Usage([seq(round(n), n=1..10^5)]):
memory used=85.45MiB, alloc change=0 bytes, cpu time=355.00ms, realtime=355.00ms, gc time=0ns> CodeTools:-Usage([seq(floor(n/13), n=1..10^5)]):
memory used=191.96MiB, alloc change=0 bytes, cpu time=2.48s, real time=1.78s, gc time=862.99ms• The evalhf command uses a more accurate formula for computing the tangent,cotangent, hyperbolic tangent, and hyperbolic cotangent function in certain areas of thecomplex plane. As a consequence, evalhf is now used for computing these functions
numerically in those parts of the complex plane whenever the requested precision issuitable for hardware float computation. This speeds the following computation up by 4-5x.

> CodeTools:-Usage([seq(tan(n * 1e-4 + 20.*I), n=1..10^4)]):
memory used=75.78MiB, alloc change=0 bytes, cpu time=2.49s, real time=1.80s, gc time=846.68ms