Is MAX(a+b,c) = MAX(c,a+b) ?



On Fri, 2003-09-05 at 08:31, Raymond Toy wrote:
> >>>>> "Barton" == Barton Willis <willisb@unk.edu> writes:
> 
> [snip]
> 
>     Barton> The message that "...requires less than one thousand
>     Barton> arguments" isn't very useful! With 50 members, max works
>     Barton> okay
> 
> [snip]
> 
>     Barton> Maxima version: 5.9.0 Maxima build date: 19:10 2/9/2003
>     Barton> host type: i686-pc-mingw32 lisp-implementation-type: Kyoto
>     Barton> Common Lisp lisp-implementation-version: GCL-2-5.0
> 
> gcl 2.4.0 has a call-arguments-limit of 64.  
> 
> CMUCL has a call-arguments-limit of most-positive-fixnum; clisp, most
> positive 32-bit number.

call-arguments-limit in CLISP was recently restricted. It's now only
4096: <http://clisp.sourceforge.net/impnotes/data.html>;
(refer Table 5-1. Function call limits)

Further information:
<http://groups.google.co.nz/groups?selm=pan.2003.07.12.01.38.06.598166%40consulting.net.nz&output=gplain>;

>   But ANSI CL says call-arguments-limit must be
> at least 50.  Presumably the others Lisps have limits close to
> most-positive-fixnum.
> 
> Is maxima required to work around limitations of the underlying lisp?

Or to rephrase, is Maxima required to work around poor implementation
decisions?

I'd rather see implementations with a low call-arguments-limit improved.
This is an issue of expressiveness and speed. Even if using REDUCE is
possible it can be significantly slower than being able to operate on
the entire arguments list at once, e.g. compare these CMUCL results:

* (time (length (apply #'concatenate 'string (loop for x from 1 to 10000
collect "1"))))
; Compiling lambda nil: 
; Compiling Top-Level Form: 

; Evaluation took:
;   6.39f0 seconds of real time
;   6.38f0 seconds of user run time
;   0.01f0 seconds of system run time
;   3,202,204,680 CPU cycles
;   0 page faults and
;   490,128 bytes consed.
; 
10000

* (time (flet ((join (a b) (concatenate 'string a b))) (length (reduce
#'join (loop for x from 1 to 10000 collect "1")))))
; Compiling lambda nil: 
; Compiling Top-Level Form: 

; [GC threshold exceeded with 67,468,960 bytes in use.  Commencing GC.]
; [GC completed with 586,248 bytes retained and 66,882,712 bytes freed.]
; [GC will next occur when at least 67,695,112 bytes are in use.]

; Evaluation took:
;   16.16f0 seconds of real time
;   15.72f0 seconds of user run time
;   0.35f0 seconds of system run time
;   8,100,860,087 CPU cycles
;   [Run times include 0.15f0 seconds GC run time]
;   0 page faults and
;   51,732,472 bytes consed.
; 
10000

And compare the bytes consed. We can see why this is happening with a
smaller example using trace:

(defun join (a b) (concatenate 'string a b))
(defun test () (reduce #'join (loop for x from 1 to 9 collect (format nil "~D" x))))
(trace join test)

* (test)

  0: (test)
    1: (join "1" "2")
    1: join returned "12"
    1: (join "12" "3")
    1: join returned "123"
    1: (join "123" "4")
    1: join returned "1234"
    1: (join "1234" "5")
    1: join returned "12345"
    1: (join "12345" "6")
    1: join returned "123456"
    1: (join "123456" "7")
    1: join returned "1234567"
    1: (join "1234567" "8")
    1: join returned "12345678"
    1: (join "12345678" "9")
    1: join returned "123456789"
  0: test returned "123456789"
"123456789"

This is my first and last comment on the issue (opinions about poor
implementation decisions can invoke passionate disagreement). My main
aim was simply to update the list about CLISP's call-arguments-limit.

Regards,
Adam