Your code looks ok to me.
Dunno about rulecheck clause, to make Robert Dodier happy?

I don't know why GCL is slow but  looking around, here are some thoughts on
speeding stuff up more.  I hope you or someone has the time

1. do this:

  (setf (get 'mlist 'msimpind) '(mlist simp))

What this does is it uses the same list structure all the time for (mlist simp) in the header of the
list after simplification, instead of consing up 10^4 redundant lists.

2. (and this is in general to potentially speed up maxima' simplifier all over the place...)
This hack was put in the pre-dump-the-binary phase in an attempt to speed things up, but maybe in
the effort to use non-lisp for such things, got lost(?)
  Anyway, it is to put the property list of operators in an order in which the most time-critical
ones come first.
  Rationale:  if you are running the simplifier and encounter the operator %sin,  in order
to simplify it, you look on the property list of %sin for the place where the simplifier
program is stored.   It is stored under the property operators.  That is, you do
(get '%sin 'operators)  and you get the symbol  SIMP-%SIN.

(a) you would hope that this property, used most often, would be at the front of the plist
so as to make access fast.
It is not.  It is in position 22,  so that 44 memory references are needed to get to the simplifier
function.  Because other stuff was (uh) pushed on the plist later.  What time-critical stuff
might that be?  well,  wxmaxima display properties,  tex display properties,  integration properties,
file source-code data etc.   So a simple program to go through all the operators in Maxima and rearrange the
symbol-plists so that the operators property comes first,  could save time, and would use
no more storage.
Even the heavily-used operators have this lag built in.  to find the operators property of  MPLUS
requires 32 memory references.

(b) Yet  another level of memory reference could be removed.   This way: 
SIMP-%SIN  is an atom.  It is not actually the lisp function.  To get that, we can compute
(symbol-function 'simp-%sin)   and we get something that is essentially a machine address, though
how it is printed varies with the lisp system.  On GCL I get  #<compiled-function SIMP-%SIN>

Also it would pay to move msimpind near to the front of the plists.

So here's thelisp  program...

;; move property to front of property list

(in-package :maxima)

(defun motf(r p)            ; r is symbol, p is property
  (let ((q (get r p)))
    (cond (q (remf (symbol-plist r)p )
         (setf (get r p) q) ;; put it back
      (t 'not_found))))

(defun $speedup(r)
  (motf r 'msimpind)
  (motf r 'operators))

in maxima , how to use it?

map (speedup, [?mplus, ?mtimes, ?mexpt, sin,cos, tan,  nounify(integrate)])

note: the nounify(integrate) is necessary because the integration facility has mixed up evaluation and

So here's what you can do:
run this  speedup, once.  and see if it makes your favorite timing benchmark run faster.  It should
make simplification faster. Whether you notice it or not depends on how much other serious
computing is going on.

If you like it, the people who make binaries should
(a) make a list of all the common operators and run speedup on them, just before the system is dumped.
After wxmaxima or whatever has been loaded.
(b) then dump the system.

On 3/29/2014 4:45 AM, Barton Willis wrote:
The standard pop and push (defined in basic) are especially slow using Maxima compiled with GCL.
For N = 5*10^4, run times for  (l : [], for i : 1 thru N do push(x,l), for i : 1 thru N do pop(l)) are

   CCL    7.0500 seconds
   GCL 73.8600 seconds

For either GCL or CCL, my pop and push run the test OK

  CCL   0.6390 seconds
  GCL   0.52 seconds

For tellsimp rules on lists, there are plenty of restrictions--I don't think that a tellsimp rule on a list
could, for example, sort the list.


(defmspec $push (z)
  (let* ((o (car (pop z)))
(x (if z (pop z) (wna-err o)))
(l (if z (pop z) (wna-err o)))
(ll (meval l)))

    (if z (wna-err o))

    (if (and ($mapatom l) ($listp ll))
  (setq ll (cons (meval x) (cdr ll)))
  ;;alternative: (mset l (if (rulechk 'mlist) (simplifya (cons '(mlist) ll) t) (cons '(mlist simp) ll))))
  (mset l (simplifya (cons '(mlist) ll) t)))
      (merror "Second argument to push must be a mapatom that is bound to a list"))))

(defmspec $pop (z)
  (let* ((o (car (pop z)))
            (l (if z (pop z) (wna-err o)))
            (ll (meval l)))
    (if z (wna-err o))
    (cond ((and ($mapatom l) ($listp ll))
   (if ($emptyp ll) (merror "Pop called on an empty list")
          (setq ll (cdr ll))
          (pop ll)
       ;; alternative: (mset l (if (rulechk 'mlist) (simplifya (cons '(mlist) ll) t)  (cons (list 'mlist 'simp) ll))))))
       (mset l (simplifya (cons '(mlist) ll) t)))))
  (t (merror "Argument to pop must be a mapatom that is bound to a list")))))

And some tests








(l : [1,2],0);


errcatch(push(x,l, 2014));

(l : [1,2], push(x,l),l);

[pop(l), l];
[x, [1,2]]$

(l : [false], [pop(l), l]);

(l : [1,2], a : push(0,l), pop(l), [a,l]);

(l : [1,2], push(l,l));

(remvalue(a), a[%pi] : [0,1,[8]], 0);

(push(2014, a[%pi]), a[%pi]);

(pop(a[%pi]), a[%pi]);

(l1 : [0], l2 : [0,1], l3 : [0,1,2],0);

map('pop, '[l1,l2,l3]);


(a : b, b : c, c : d, d : e, e : f,0);

(l : [a,b,c,d,e], push(x,l), pop(l),l);


(remvalue(a,l,l1,l2,l3,b,c,d,e,f),remarray(a), 0);


Maxima-discuss mailing list