Additional freeof function // avoiding rat /disrep



Memo'izing the disrep'ed form could be useful, especially since much
code in Maxima blindly disrep's whenever it runs into an CRE (canonical
rational expression).

Let's look at what it would take to make it work.

As you say, any relevant globals should just be stored along with the
memo'ized form.  But figuring out which globals are relevant is not so
trivial....

In the disrep case, this includes all simplifier flags that might affect
the result, e.g. $numer, $bfloat, $domain, $expop/expop (if $ratfac is
true), $dotconstrules (and many other dot flags), $listarith,....  The
Features database can use timestamps.  Note that ratdisrep does NOT
re-simplify kernel objects, so things like $trigexpand do not need to be
saved -- as for $trigreduce, it is a function, not a global variable.
Also, I have not been able to find any cases where the Assume database
is relevant.  On the other hand, if there are any rewrite rules in the
pattern matcher database that affect +, *, and ^, then all bets are
off -- ANY AND ALL simplification flags may be relevant.  Perhaps that
should just disable memo'izing entirely.

In the ratrep case, the relevant globals include (a subset of) $ratvars,
$keepfloat, $ratepsilon, $ratfac, $algebraic, *ratweights, the Tellrat
database (timestamp).

I am sure there are others I haven't thought of.

Another complication is mutable elements.  As far as I can tell, the
only mutable elements in Maxima expressions are Mlists and Marrays.
(Top level Mlists and Marrays are not a problem, since ratrep'ing them
just maps ratrep over their components.)  I have gone through the
exercise of thinking about handling mutable elements with timestamps
etc., and it is messy.  Trust me.  I had written a long email explaining
the complications, but deleted it because I doubt anyone wants to see
the gory details.  A lot of complication for rare or contrived cases
like f([rat(x)]) and m . rat(matrix([a,b])).  So I would suggest simply
giving up whenever there is an embedded MList or MArray, and not
memo'izing at all.

This all seems messier than I would have thought at first.

Another approach would be to use a global assq list as a cache, and null
it out whenever any "dangerous" event happens.  A dangerous event is any
MSET to relevant variables or MList elements and any change to the
Tellsimp, Tellrat, Assume, or Feature databases.  This assumes, of
course, that we can effectively determine the list of relevant
variables.  This would get rid of the complications of timestamps, assq
lists of relevant flags, etc.  In fact, it would only be a dozen lines
of code total, and the danger of breaking something is small.  As for
the benefit, it benefits all operations which repeatedly disrep the same
objects within one command.  Probably not a huge win, but worth a dozen
lines of code.

I still think that the full memo'izing scheme could improve performance
in some cases, but is it worth the added complexity in the code?

Your thoughts?

      -s