Subject: Repeatedly applying trigsimp, ratsimp etc.
From: Barton Willis
Date: Sun, 4 Nov 2012 22:59:57 +0000
>From code I see on this list, it seems that xxx[iii] is a super popular way to extract a list member. So I think it would be great if
somebody proposed and tested code that makes local values trump global arrays.
The slowness of "for i thru length(l) do... l[i]" compared to "for i in l do...i " can be dramatic:
(%i1) f(l) := block([x : 0], for lx in l do x : x + lx,x)$
(%i2) g(l) := block([x : 0, n : length(l)], for i : 1 thru n do x : x + l[i],x)$
(%i3) h(l) := block([x : 0, n : length(l)], for i : 1 thru n do x : x + inpart(l,i),x)$
(%i4) l : makelist(i,i,1,10^4)$
(%i5) showtime : all$
Evaluation took 0.0000 seconds (0.0000 elapsed)
(%i6) f(l);
Evaluation took 0.0500 seconds (0.0500 elapsed)
(%o6) 50005000
(%i7) g(l);
Evaluation took 7.1600 seconds (7.1600 elapsed)
(%o7) 50005000
(%i8) h(l);
Evaluation took 8.0400 seconds (8.0400 elapsed)
(%o8) 50005000
--Barton
________________________________
From: macrakis at gmail.com [macrakis at gmail.com] on behalf of Stavros Macrakis [macrakis at alum.mit.edu]
Sent: Sunday, November 04, 2012 16:30
To: Barton Willis
Cc: David Scherfgen; maxima at math.utexas.edu
Subject: Re: [Maxima] Repeatedly applying trigsimp, ratsimp etc.
Barton,
I agree that
for i in l do...i
is far better than
for i thru length(l) do... l[i]
After all, the latter takes quadratic time for lists (as opposed to arrays)!
As for the global 'r' problem, I agree that inpart is a reasonable workaround for the current semantics. But this seems like a good argument for getting rid of the current semantics, where a global array 'r' trumps a local value 'r'.
-s
On Sun, Nov 4, 2012 at 9:27 AM, Barton Willis <willisb at unk.edu<mailto:willisb at unk.edu>> wrote:
(1) To access a member of a list, I suggest using inpart, not [k]. Consider:
(%i1) larry(k) := block([r : [1,2,3]], r[k])$
(%i2) george(k) := block([r : [1,2,3]], inpart(r,k))$
(%i5) r[x] : 42$
Unintended:
(%i6) larry(1);
(%o6) r[1]
OK:
(%i7) george(1);
(%o7) 1
Alternatively,
larry(k) := block([r : [1,2,3]], local(r), r[k])$
is OK too.
(2) To loop over the members of a list r, consider using
for rk in r do ( ...
instead of
for k : 1 thru length(r) do ( ...
The function length gets called each time at the top of the loop--also you will also not need to do r[k] any more :)
(3) Consider giving the last argument of dssimp a goofy name such as %_r_%. This isn't foolproof, but it does give some protection against
problems such as
(%i5) dssimp(1,[fff]);
(%o5) 1
(%i6) dssimp(1,[r]);
apply: found r evaluates to [r] where a function was expected.
(4) To form a compound statement without local variables, an explicit 'block' isn't needed--just (XXX, YYY, ZZZ), not block(XXX, YYY, ZZZ).
--Barton
________________________________________
----------------------
(defmfun $conssize (x) (if (atom x) 0 (do ((x (cdr x) (cdr x)) (sz 1))
((null x) sz) (incf sz (1+ (conssize (car x)))))))
File dssimp.mac:
-----------------------
dssimp(expr, r) :=
block([exprSize, smallestExpr, smallestExprSize, simpdExpr,
simpdExprSize],
exprSize : conssize(expr),
smallestExpr : expr,
smallestExprSize : exprSize,
loop,
for i : 1 thru length(r) do
block(
simpdExpr : r[i](expr),
simpdExprSize : conssize(simpdExpr),
if simpdExprSize < smallestExprSize then
block(
smallestExpr : simpdExpr,
smallestExprSize : simpdExprSize
)
),
if smallestExprSize >= exprSize then
return(expr),
expr : smallestExpr,
exprSize : smallestExprSize,
go(loop)
);
dssimpall(expr) := dssimp(expr, [combine, logcontract, radcan, ratsimp,
rootscontract, trigrat, trigreduce, trigsimp, xthru]);