root/trunk/lisp/calc/calc-vec.el

Revision 4220, 46.8 kB (checked in by miyoshi, 9 months ago)

Sync up with Emacs22.2.

Line 
1 ;;; calc-vec.el --- vector functions for Calc
2
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
4 ;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
6 ;; Author: David Gillespie <daveg@synaptics.com>
7 ;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
8
9 ;; This file is part of GNU Emacs.
10
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; any later version.
15
16 ;; GNU Emacs is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02110-1301, USA.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 ;; This file is autoloaded from calc-ext.el.
31
32 (require 'calc-ext)
33 (require 'calc-macs)
34
35 (defun calc-display-strings (n)
36   (interactive "P")
37   (calc-wrapper
38    (message (if (calc-change-mode 'calc-display-strings n t t)
39                 "Displaying vectors of integers as quoted strings"
40               "Displaying vectors of integers normally"))))
41
42
43 (defun calc-pack (n)
44   (interactive "P")
45   (calc-wrapper
46    (let* ((nn (if n 1 2))
47           (mode (if n (prefix-numeric-value n) (calc-top-n 1)))
48           (mode (if (and (Math-vectorp mode) (cdr mode)) (cdr mode)
49                   (if (integerp mode) mode
50                     (error "Packing mode must be an integer or vector of integers"))))
51           (num (calc-pack-size mode))
52           (items (calc-top-list num nn)))
53      (calc-enter-result (+ nn num -1) "pack" (calc-pack-items mode items)))))
54
55 (defun calc-pack-size (mode)
56   (cond ((consp mode)
57          (let ((size 1))
58            (while mode
59              (or (integerp (car mode)) (error "Vector of integers expected"))
60              (setq size (* size (calc-pack-size (car mode)))
61                    mode (cdr mode)))
62            (if (= size 0)
63                (error "Zero dimensions not allowed")
64              size)))
65         ((>= mode 0) mode)
66         (t (or (cdr (assq mode '((-3 . 3) (-13 . 1) (-14 . 3) (-15 . 6))))
67                2))))
68
69 (defun calc-pack-items (mode items)
70   (cond ((consp mode)
71          (if (cdr mode)
72              (let* ((size (calc-pack-size (cdr mode)))
73                     (len (length items))
74                     (new nil)
75                     p row)
76                (while (> len 0)
77                  (setq p (nthcdr (1- size) items)
78                        row items
79                        items (cdr p)
80                        len (- len size))
81                  (setcdr p nil)
82                  (setq new (cons (calc-pack-items (cdr mode) row) new)))
83                (calc-pack-items (car mode) (nreverse new)))
84            (calc-pack-items (car mode) items)))
85         ((>= mode 0)
86          (cons 'vec items))
87         ((= mode -3)
88          (if (and (math-objvecp (car items))
89                   (math-objvecp (nth 1 items))
90                   (math-objvecp (nth 2 items)))
91              (if (and (math-num-integerp (car items))
92                       (math-num-integerp (nth 1 items)))
93                  (if (math-realp (nth 2 items))
94                      (cons 'hms items)
95                    (error "Seconds must be real"))
96                (error "Hours and minutes must be integers"))
97            (math-normalize (list '+
98                                  (list '+
99                                        (if (eq calc-angle-mode 'rad)
100                                            (list '* (car items)
101                                                  '(hms 1 0 0))
102                                          (car items))
103                                        (list '* (nth 1 items) '(hms 0 1 0)))
104                                  (list '* (nth 2 items) '(hms 0 0 1))))))
105         ((= mode -13)
106          (if (math-realp (car items))
107              (cons 'date items)
108            (if (eq (car-safe (car items)) 'date)
109                (car items)
110              (if (math-objvecp (car items))
111                  (error "Date value must be real")
112                (cons 'calcFunc-date items)))))
113         ((memq mode '(-14 -15))
114          (let ((p items))
115            (while (and p (math-objvecp (car p)))
116              (or (math-integerp (car p))
117                  (error "Components must be integers"))
118              (setq p (cdr p)))
119            (if p
120                (cons 'calcFunc-date items)
121              (list 'date (math-dt-to-date items)))))
122         ((or (eq (car-safe (car items)) 'vec)
123              (eq (car-safe (nth 1 items)) 'vec))
124          (let* ((x (car items))
125                 (vx (eq (car-safe x) 'vec))
126                 (y (nth 1 items))
127                 (vy (eq (car-safe y) 'vec))
128                 (z nil)
129                 (n (1- (length (if vx x y)))))
130            (and vx vy
131                 (/= n (1- (length y)))
132                 (error "Vectors must be the same length"))
133            (while (>= (setq n (1- n)) 0)
134              (setq z (cons (calc-pack-items
135                             mode
136                             (list (if vx (car (setq x (cdr x))) x)
137                                   (if vy (car (setq y (cdr y))) y)))
138                            z)))
139            (cons 'vec (nreverse z))))
140         ((= mode -1)
141          (if (and (math-realp (car items)) (math-realp (nth 1 items)))
142              (cons 'cplx items)
143            (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
144                (error "Components must be real"))
145            (math-normalize (list '+ (car items)
146                                  (list '* (nth 1 items) '(cplx 0 1))))))
147         ((= mode -2)
148          (if (and (math-realp (car items)) (math-anglep (nth 1 items)))
149              (cons 'polar items)
150            (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
151                (error "Components must be real"))
152            (math-normalize (list '* (car items)
153                                  (if (math-anglep (nth 1 items))
154                                      (list 'polar 1 (nth 1 items))
155                                    (list 'calcFunc-exp
156                                          (list '*
157                                                (math-to-radians-2
158                                                 (nth 1 items))
159                                                (list 'polar
160                                                      1
161                                                      (math-quarter-circle
162                                                       nil)))))))))
163         ((= mode -4)
164          (let ((x (car items))
165                (sigma (nth 1 items)))
166            (if (or (math-scalarp x) (not (math-objvecp x)))
167                (if (or (math-anglep sigma) (not (math-objvecp sigma)))
168                    (math-make-sdev x sigma)
169                  (error "Error component must be real"))
170              (error "Mean component must be real or complex"))))
171         ((= mode -5)
172          (let ((a (car items))
173                (m (nth 1 items)))
174            (if (and (math-anglep a) (math-anglep m))
175                (if (math-posp m)
176                    (math-make-mod a m)
177                  (error "Modulus must be positive"))
178              (if (and (math-objectp a) (math-objectp m))
179                  (error "Components must be real"))
180              (list 'calcFunc-makemod a m))))
181         ((memq mode '(-6 -7 -8 -9))
182          (let ((lo (car items))
183                (hi (nth 1 items)))
184            (if (and (or (math-anglep lo) (eq (car lo) 'date)
185                         (not (math-objvecp lo)))
186                     (or (math-anglep hi) (eq (car hi) 'date)
187                         (not (math-objvecp hi))))
188                (math-make-intv (+ mode 9) lo hi)
189              (error "Components must be real"))))
190         ((eq mode -10)
191          (if (math-zerop (nth 1 items))
192              (error "Denominator must not be zero")
193            (if (and (math-integerp (car items)) (math-integerp (nth 1 items)))
194                (math-normalize (cons 'frac items))
195              (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
196                  (error "Components must be integers"))
197              (cons 'calcFunc-fdiv items))))
198         ((memq mode '(-11 -12))
199          (if (and (math-realp (car items)) (math-integerp (nth 1 items)))
200              (calcFunc-scf (math-float (car items)) (nth 1 items))
201            (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
202                (error "Components must be integers"))
203            (math-normalize
204             (list 'calcFunc-scf
205                   (list 'calcFunc-float (car items))
206                   (nth 1 items)))))
207         (t
208          (error "Invalid packing mode: %d" mode))))
209
210 (defvar calc-unpack-with-type nil)
211 (defun calc-unpack (mode)
212   (interactive "P")
213   (calc-wrapper
214    (let ((calc-unpack-with-type t))
215      (calc-pop-push-record-list 1 "unpk" (calc-unpack-item
216                                           (and mode
217                                                (prefix-numeric-value mode))
218                                           (calc-top))))))
219
220 (defun calc-unpack-type (item)
221   (cond ((eq (car-safe item) 'vec)
222          (1- (length item)))
223         ((eq (car-safe item) 'intv)
224          (- (nth 1 item) 9))
225         (t
226          (or (cdr (assq (car-safe item) '( (cplx . -1) (polar . -2)
227                                            (hms . -3) (sdev . -4) (mod . -5)
228                                            (frac . -10) (float . -11)
229                                            (date . -13) )))
230              (error "Argument must be a composite object")))))
231
232 (defun calc-unpack-item (mode item)
233   (cond ((not mode)
234          (if (or (and (not (memq (car-safe item) '(frac float cplx polar vec
235                                                         hms date sdev mod
236                                                         intv)))
237                       (math-objvecp item))
238                  (eq (car-safe item) 'var))
239              (error "Argument must be a composite object or function call"))
240          (if (eq (car item) 'intv)
241              (cdr (cdr item))
242            (cdr item)))
243         ((> mode 0)
244          (let ((dims nil)
245                type new row)
246            (setq item (list item))
247            (while (> mode 0)
248              (setq type (calc-unpack-type (car item))
249                    dims (cons type dims)
250                    new (calc-unpack-item nil (car item)))
251              (while (setq item (cdr item))
252                (or (= (calc-unpack-type (car item)) type)
253                    (error "Inconsistent types or dimensions in vector elements"))
254                (setq new (append new (calc-unpack-item nil (car item)))))
255              (setq item new
256                    mode (1- mode)))
257            (if (cdr dims) (setq dims (list (cons 'vec (nreverse dims)))))
258            (cond ((eq calc-unpack-with-type 'pair)
259                   (list (car dims) (cons 'vec item)))
260                  (calc-unpack-with-type
261                   (append item dims))
262                  (t item))))
263         ((eq calc-unpack-with-type 'pair)
264          (let ((calc-unpack-with-type nil))
265            (list mode (cons 'vec (calc-unpack-item mode item)))))
266         ((= mode -3)
267          (if (eq (car-safe item) 'hms)
268              (cdr item)
269            (error "Argument must be an HMS form")))
270         ((= mode -13)
271          (if (eq (car-safe item) 'date)
272              (cdr item)
273            (error "Argument must be a date form")))
274         ((= mode -14)
275          (if (eq (car-safe item) 'date)
276              (math-date-to-dt (math-floor (nth 1 item)))
277            (error "Argument must be a date form")))
278         ((= mode -15)
279          (if (eq (car-safe item) 'date)
280              (append (math-date-to-dt (nth 1 item))
281                      (and (not (math-integerp (nth 1 item)))
282                           (list 0 0 0)))
283            (error "Argument must be a date form")))
284         ((eq (car-safe item) 'vec)
285          (let ((x nil)
286                (y nil)
287                res)
288            (while (setq item (cdr item))
289              (setq res (calc-unpack-item mode (car item))
290                    x (cons (car res) x)
291                    y (cons (nth 1 res) y)))
292            (list (cons 'vec (nreverse x))
293                  (cons 'vec (nreverse y)))))
294         ((= mode -1)
295          (if (eq (car-safe item) 'cplx)
296              (cdr item)
297            (if (eq (car-safe item) 'polar)
298                (cdr (math-complex item))
299              (if (Math-realp item)
300                  (list item 0)
301                (error "Argument must be a complex number")))))
302         ((= mode -2)
303          (if (or (memq (car-safe item) '(cplx polar))
304                  (Math-realp item))
305              (cdr (math-polar item))
306            (error "Argument must be a complex number")))
307         ((= mode -4)
308          (if (eq (car-safe item) 'sdev)
309              (cdr item)
310            (list item 0)))
311         ((= mode -5)
312          (if (eq (car-safe item) 'mod)
313              (cdr item)
314            (error "Argument must be a modulo form")))
315         ((memq mode '(-6 -7 -8 -9))
316          (if (eq (car-safe item) 'intv)
317              (cdr (cdr item))
318            (list item item)))
319         ((= mode -10)
320          (if (eq (car-safe item) 'frac)
321              (cdr item)
322            (if (Math-integerp item)
323                (list item 1)
324              (error "Argument must be a rational number"))))
325         ((= mode -11)
326          (if (eq (car-safe item) 'float)
327              (list (nth 1 item) (math-normalize (nth 2 item)))
328            (error "Expected a floating-point number")))
329         ((= mode -12)
330          (if (eq (car-safe item) 'float)
331              (list (calcFunc-mant item) (calcFunc-xpon item))
332            (error "Expected a floating-point number")))
333         (t
334          (error "Invalid unpacking mode: %d" mode))))
335
336 (defun calc-diag (n)
337   (interactive "P")
338   (calc-wrapper
339    (calc-enter-result 1 "diag" (if n
340                                    (list 'calcFunc-diag (calc-top-n 1)
341                                          (prefix-numeric-value n))
342                                  (list 'calcFunc-diag (calc-top-n 1))))))
343
344 (defun calc-ident (n)
345   (interactive "NDimension of identity matrix = ")
346   (calc-wrapper
347    (calc-enter-result 0 "idn" (if (eq n 0)
348                                   '(calcFunc-idn 1)
349                                 (list 'calcFunc-idn 1
350                                       (prefix-numeric-value n))))))
351
352 (defun calc-index (n &optional stack)
353   (interactive "NSize of vector = \nP")
354   (calc-wrapper
355    (if (consp stack)
356        (calc-enter-result 3 "indx" (cons 'calcFunc-index (calc-top-list-n 3)))
357      (calc-enter-result 0 "indx" (list 'calcFunc-index
358                                        (prefix-numeric-value n))))))
359
360 (defun calc-build-vector (n)
361   (interactive "NSize of vector = ")
362   (calc-wrapper
363    (calc-enter-result 1 "bldv" (list 'calcFunc-cvec
364                                      (calc-top-n 1)
365                                      (prefix-numeric-value n)))))
366
367 (defun calc-cons (arg)
368   (interactive "P")
369   (calc-wrapper
370    (if (calc-is-hyperbolic)
371        (calc-binary-op "rcns" 'calcFunc-rcons arg)
372      (calc-binary-op "cons" 'calcFunc-cons arg))))
373
374
375 (defun calc-head (arg)
376   (interactive "P")
377   (calc-wrapper
378    (if (calc-is-inverse)
379        (if (calc-is-hyperbolic)
380            (calc-unary-op "rtai" 'calcFunc-rtail arg)
381          (calc-unary-op "tail" 'calcFunc-tail arg))
382      (if (calc-is-hyperbolic)
383          (calc-unary-op "rhed" 'calcFunc-rhead arg)
384        (calc-unary-op "head" 'calcFunc-head arg)))))
385
386 (defun calc-tail (arg)
387   (interactive "P")
388   (calc-invert-func)
389   (calc-head arg))
390
391 (defun calc-vlength (arg)
392   (interactive "P")
393   (calc-wrapper
394    (if (calc-is-hyperbolic)
395        (calc-unary-op "dims" 'calcFunc-mdims arg)
396      (calc-unary-op "len" 'calcFunc-vlen arg))))
397
398 (defun calc-arrange-vector (n)
399   (interactive "NNumber of columns = ")
400   (calc-wrapper
401    (calc-enter-result 1 "arng" (list 'calcFunc-arrange (calc-top-n 1)
402                                      (prefix-numeric-value n)))))
403
404 (defun calc-vector-find (arg)
405   (interactive "P")
406   (calc-wrapper
407    (let ((func (cons 'calcFunc-find (calc-top-list-n 2))))
408      (calc-enter-result
409       2 "find"
410       (if arg (append func (list (prefix-numeric-value arg))) func)))))
411
412 (defun calc-subvector ()
413   (interactive)
414   (calc-wrapper
415    (if (calc-is-inverse)
416        (calc-enter-result 3 "rsvc" (cons 'calcFunc-rsubvec
417                                          (calc-top-list-n 3)))
418      (calc-enter-result 3 "svec" (cons 'calcFunc-subvec (calc-top-list-n 3))))))
419
420 (defun calc-reverse-vector (arg)
421   (interactive "P")
422   (calc-wrapper
423    (calc-unary-op "rev" 'calcFunc-rev arg)))
424
425 (defun calc-mask-vector (arg)
426   (interactive "P")
427   (calc-wrapper
428    (calc-binary-op "vmsk" 'calcFunc-vmask arg)))
429
430 (defun calc-expand-vector (arg)
431   (interactive "P")
432   (calc-wrapper
433    (if (calc-is-hyperbolic)
434        (calc-enter-result 3 "vexp" (cons 'calcFunc-vexp (calc-top-list-n 3)))
435      (calc-binary-op "vexp" 'calcFunc-vexp arg))))
436
437 (defun calc-sort ()
438   (interactive)
439   (calc-slow-wrapper
440    (if (calc-is-inverse)
441        (calc-enter-result 1 "rsrt" (list 'calcFunc-rsort (calc-top-n 1)))
442      (calc-enter-result 1 "sort" (list 'calcFunc-sort (calc-top-n 1))))))
443
444 (defun calc-grade ()
445   (interactive)
446   (calc-slow-wrapper
447    (if (calc-is-inverse)
448        (calc-enter-result 1 "rgrd" (list 'calcFunc-rgrade (calc-top-n 1)))
449      (calc-enter-result 1 "grad" (list 'calcFunc-grade (calc-top-n 1))))))
450
451 (defun calc-histogram (n)
452   (interactive "NNumber of bins: ")
453   (calc-slow-wrapper
454    (if calc-hyperbolic-flag
455        (calc-enter-result 2 "hist" (list 'calcFunc-histogram
456                                          (calc-top-n 2)
457                                          (calc-top-n 1)
458                                          (prefix-numeric-value n)))
459      (calc-enter-result 1 "hist" (list 'calcFunc-histogram
460                                        (calc-top-n 1)
461                                        (prefix-numeric-value n))))))
462
463 (defun calc-transpose (arg)
464   (interactive "P")
465   (calc-wrapper
466    (calc-unary-op "trn" 'calcFunc-trn arg)))
467
468 (defun calc-conj-transpose (arg)
469   (interactive "P")
470   (calc-wrapper
471    (calc-unary-op "ctrn" 'calcFunc-ctrn arg)))
472
473 (defun calc-cross (arg)
474   (interactive "P")
475   (calc-wrapper
476    (calc-binary-op "cros" 'calcFunc-cross arg)))
477
478 (defun calc-remove-duplicates (arg)
479   (interactive "P")
480   (calc-wrapper
481    (calc-unary-op "rdup" 'calcFunc-rdup arg)))
482
483 (defun calc-set-union (arg)
484   (interactive "P")
485   (calc-wrapper
486    (calc-binary-op "unio" 'calcFunc-vunion arg '(vec) 'calcFunc-rdup)))
487
488 (defun calc-set-intersect (arg)
489   (interactive "P")
490   (calc-wrapper
491    (calc-binary-op "intr" 'calcFunc-vint arg '(vec) 'calcFunc-rdup)))
492
493 (defun calc-set-difference (arg)
494   (interactive "P")
495   (calc-wrapper
496    (calc-binary-op "diff" 'calcFunc-vdiff arg '(vec) 'calcFunc-rdup)))
497
498 (defun calc-set-xor (arg)
499   (interactive "P")
500   (calc-wrapper
501    (calc-binary-op "xor" 'calcFunc-vxor arg '(vec) 'calcFunc-rdup)))
502
503 (defun calc-set-complement (arg)
504   (interactive "P")
505   (calc-wrapper
506    (calc-unary-op "cmpl" 'calcFunc-vcompl arg)))
507
508 (defun calc-set-floor (arg)
509   (interactive "P")
510   (calc-wrapper
511    (calc-unary-op "vflr" 'calcFunc-vfloor arg)))
512
513 (defun calc-set-enumerate (arg)
514   (interactive "P")
515   (calc-wrapper
516    (calc-unary-op "enum" 'calcFunc-venum arg)))
517
518 (defun calc-set-span (arg)
519   (interactive "P")
520   (calc-wrapper
521    (calc-unary-op "span" 'calcFunc-vspan arg)))
522
523 (defun calc-set-cardinality (arg)
524   (interactive "P")
525   (calc-wrapper
526    (calc-unary-op "card" 'calcFunc-vcard arg)))
527
528 (defun calc-unpack-bits (arg)
529   (interactive "P")
530   (calc-wrapper
531    (if (calc-is-inverse)
532        (calc-unary-op "bpck" 'calcFunc-vpack arg)
533      (calc-unary-op "bupk" 'calcFunc-vunpack arg))))
534
535 (defun calc-pack-bits (arg)
536   (interactive "P")
537   (calc-invert-func)
538   (calc-unpack-bits arg))
539
540
541 (defun calc-rnorm (arg)
542   (interactive "P")
543   (calc-wrapper
544    (calc-unary-op "rnrm" 'calcFunc-rnorm arg)))
545
546 (defun calc-cnorm (arg)
547   (interactive "P")
548   (calc-wrapper
549    (calc-unary-op "cnrm" 'calcFunc-cnorm arg)))
550
551 (defun calc-mrow (n &optional nn)
552   (interactive "NRow number: \nP")
553   (calc-wrapper
554    (if (consp nn)
555        (calc-enter-result 2 "mrow" (cons 'calcFunc-mrow (calc-top-list-n 2)))
556      (setq n (prefix-numeric-value n))
557      (if (= n 0)
558          (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
559        (if (< n 0)
560            (calc-enter-result 1 "rrow" (list 'calcFunc-mrrow
561                                              (calc-top-n 1) (- n)))
562          (calc-enter-result 1 "mrow" (list 'calcFunc-mrow
563                                            (calc-top-n 1) n)))))))
564
565 (defun calc-mcol (n &optional nn)
566   (interactive "NColumn number: \nP")
567   (calc-wrapper
568    (if (consp nn)
569        (calc-enter-result 2 "mcol" (cons 'calcFunc-mcol (calc-top-list-n 2)))
570      (setq n (prefix-numeric-value n))
571      (if (= n 0)
572          (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
573        (if (< n 0)
574            (calc-enter-result 1 "rcol" (list 'calcFunc-mrcol
575                                              (calc-top-n 1) (- n)))
576          (calc-enter-result 1 "mcol" (list 'calcFunc-mcol
577                                            (calc-top-n 1) n)))))))
578
579
580 ;;;; Vectors.
581
582 (defun calcFunc-mdims (m)
583   (or (math-vectorp m)
584       (math-reject-arg m 'vectorp))
585   (cons 'vec (math-mat-dimens m)))
586
587
588 ;;; Apply a function elementwise to vector A.  [V X V; N X N] [Public]
589 (defun math-map-vec (f a)
590   (if (math-vectorp a)
591       (cons 'vec (mapcar f (cdr a)))
592     (funcall f a)))
593
594 (defun math-dimension-error ()
595   (calc-record-why "*Dimension error")
596   (signal 'wrong-type-argument nil))
597
598
599 ;;; Build a vector out of a list of objects.  [Public]
600 (defun calcFunc-vec (&rest objs)
601   (cons 'vec objs))
602
603
604 ;;; Build a constant vector or matrix.  [Public]
605 (defun calcFunc-cvec (obj &rest dims)
606   (math-make-vec-dimen obj dims))
607
608 (defun math-make-vec-dimen (obj dims)
609   (if dims
610       (if (natnump (car dims))
611           (if (or (cdr dims)
612                   (not (math-numberp obj)))
613               (cons 'vec (copy-sequence
614                           (make-list (car dims)
615                                      (math-make-vec-dimen obj (cdr dims)))))
616             (cons 'vec (make-list (car dims) obj)))
617         (math-reject-arg (car dims) 'fixnatnump))
618     obj))
619
620 (defun calcFunc-head (vec)
621   (if (and (Math-vectorp vec)
622            (cdr vec))
623       (nth 1 vec)
624     (calc-record-why 'vectorp vec)
625     (list 'calcFunc-head vec)))
626
627 (defun calcFunc-tail (vec)
628   (if (and (Math-vectorp vec)
629            (cdr vec))
630       (cons 'vec (cdr (cdr vec)))
631     (calc-record-why 'vectorp vec)
632     (list 'calcFunc-tail vec)))
633
634 (defun calcFunc-cons (head tail)
635   (if (Math-vectorp tail)
636       (cons 'vec (cons head (cdr tail)))
637     (calc-record-why 'vectorp tail)
638     (list 'calcFunc-cons head tail)))
639
640 (defun calcFunc-rhead (vec)
641   (if (and (Math-vectorp vec)
642            (cdr vec))
643       (let ((vec (copy-sequence vec)))
644         (setcdr (nthcdr (- (length vec) 2) vec) nil)
645         vec)
646     (calc-record-why 'vectorp vec)
647     (list 'calcFunc-rhead vec)))
648
649 (defun calcFunc-rtail (vec)
650   (if (and (Math-vectorp vec)
651            (cdr vec))
652       (nth (1- (length vec)) vec)
653     (calc-record-why 'vectorp vec)
654     (list 'calcFunc-rtail vec)))
655
656 (defun calcFunc-rcons (head tail)
657   (if (Math-vectorp head)
658       (append head (list tail))
659     (calc-record-why 'vectorp head)
660     (list 'calcFunc-rcons head tail)))
661
662
663
664 ;;; Apply a function elementwise to vectors A and B.  [O X O O] [Public]
665 (defun math-map-vec-2 (f a b)
666   (if (math-vectorp a)
667       (if (math-vectorp b)
668           (let ((v nil))
669             (while (setq a (cdr a))
670               (or (setq b (cdr b))
671                   (math-dimension-error))
672               (setq v (cons (funcall f (car a) (car b)) v)))
673             (if a (math-dimension-error))
674             (cons 'vec (nreverse v)))
675         (let ((v nil))
676           (while (setq a (cdr a))
677             (setq v (cons (funcall f (car a) b) v)))
678           (cons 'vec (nreverse v))))
679     (if (math-vectorp b)
680         (let ((v nil))
681           (while (setq b (cdr b))
682             (setq v (cons (funcall f a (car b)) v)))
683           (cons 'vec (nreverse v)))
684       (funcall f a b))))
685
686
687
688 ;;; "Reduce" a function over a vector (left-associatively).  [O X V] [Public]
689 (defun math-reduce-vec (f a)
690   (if (math-vectorp a)
691       (if (cdr a)
692           (let ((accum (car (setq a (cdr a)))))
693             (while (setq a (cdr a))
694               (setq accum (funcall f accum (car a))))
695             accum)
696         0)
697     a))
698
699 ;;; Reduce a function over the columns of matrix A.  [V X V] [Public]
700 (defun math-reduce-cols (f a)
701   (if (math-matrixp a)
702       (cons 'vec (math-reduce-cols-col-step f (cdr a) 1 (length (nth 1 a))))
703     a))
704
705 (defun math-reduce-cols-col-step (f a col cols)
706   (and (< col cols)
707        (cons (math-reduce-cols-row-step f (nth col (car a)) col (cdr a))
708              (math-reduce-cols-col-step f a (1+ col) cols))))
709
710 (defun math-reduce-cols-row-step (f tot col a)
711   (if a
712       (math-reduce-cols-row-step f
713                                  (funcall f tot (nth col (car a)))
714                                  col
715                                  (cdr a))
716     tot))
717
718
719
720 (defun math-dot-product (a b)
721   (if (setq a (cdr a) b (cdr b))
722       (let ((accum (math-mul (car a) (car b))))
723         (while (setq a (cdr a) b (cdr b))
724           (setq accum (math-add accum (math-mul (car a) (car b)))))
725         accum)
726     0))
727
728
729 ;;; Return the number of elements in vector V.  [Public]
730 (defun calcFunc-vlen (v)
731   (if (math-vectorp v)
732       (1- (length v))
733     (if (math-objectp v)
734         0
735       (list 'calcFunc-vlen v))))
736
737 ;;; Get the Nth row of a matrix.
738 (defun calcFunc-mrow (mat n)   ; [Public]
739   (if (Math-vectorp n)
740       (math-map-vec (function (lambda (x) (calcFunc-mrow mat x))) n)
741     (if (and (eq (car-safe n) 'intv) (math-constp n))
742         (calcFunc-subvec mat
743                          (math-add (nth 2 n) (if (memq (nth 1 n) '(2 3)) 0 1))
744                          (math-add (nth 3 n) (if (memq (nth 1 n) '(1 3)) 1 0)))
745       (or (and (integerp (setq n (math-check-integer n)))
746                (> n 0))
747           (math-reject-arg n 'fixposintp))
748       (or (Math-vectorp mat)
749           (math-reject-arg mat 'vectorp))
750       (or (nth n mat)
751           (math-reject-arg n "*Index out of range")))))
752
753 (defun calcFunc-subscr (mat n &optional m)
754   (setq mat (calcFunc-mrow mat n))
755   (if m
756       (if (math-num-integerp n)
757           (calcFunc-mrow mat m)
758         (calcFunc-mcol mat m))
759     mat))
760
761 ;;; Get the Nth column of a matrix.
762 (defun math-mat-col (mat n)
763   (cons 'vec (mapcar (function (lambda (x) (elt x n))) (cdr mat))))
764
765 (defun calcFunc-mcol (mat n)   ; [Public]
766   (if (Math-vectorp n)
767       (calcFunc-trn
768        (math-map-vec (function (lambda (x) (calcFunc-mcol mat x))) n))
769     (if (and (eq (car-safe n) 'intv) (math-constp n))
770         (if (math-matrixp mat)
771             (math-map-vec (function (lambda (x) (calcFunc-mrow x n))) mat)
772           (calcFunc-mrow mat n))
773       (or (and (integerp (setq n (math-check-integer n)))
774                (> n 0))
775           (math-reject-arg n 'fixposintp))
776       (or (Math-vectorp mat)
777           (math-reject-arg mat 'vectorp))
778       (or (if (math-matrixp mat)
779               (and (< n (length (nth 1 mat)))
780                    (math-mat-col mat n))
781             (nth n mat))
782           (math-reject-arg n "*Index out of range")))))
783
784 ;;; Remove the Nth row from a matrix.
785 (defun math-mat-less-row (mat n)
786   (if (<= n 0)
787       (cdr mat)
788     (cons (car mat)
789           (math-mat-less-row (cdr mat) (1- n)))))
790
791 (defun calcFunc-mrrow (mat n)   ; [Public]
792   (and (integerp (setq n (math-check-integer n)))
793        (> n 0)
794        (< n (length mat))
795        (math-mat-less-row mat n)))
796
797 ;;; Remove the Nth column from a matrix.
798 (defun math-mat-less-col (mat n)
799   (cons 'vec (mapcar (function (lambda (x) (math-mat-less-row x n)))
800                      (cdr mat))))
801
802 (defun calcFunc-mrcol (mat n)   ; [Public]
803   (and (integerp (setq n (math-check-integer n)))
804        (> n 0)
805        (if (math-matrixp mat)
806            (and (< n (length (nth 1 mat)))
807                 (math-mat-less-col mat n))
808          (math-mat-less-row mat n))))
809
810 (defun calcFunc-getdiag (mat)   ; [Public]
811   (if (math-square-matrixp mat)
812       (cons 'vec (math-get-diag-step (cdr mat) 1))
813     (calc-record-why 'square-matrixp mat)
814     (list 'calcFunc-getdiag mat)))
815
816 (defun math-get-diag-step (row n)
817   (and row
818        (cons (nth n (car row))
819              (math-get-diag-step (cdr row) (1+ n)))))
820
821 (defun math-transpose (mat)   ; [Public]
822   (let ((m nil)
823         (col (length (nth 1 mat))))
824     (while (> (setq col (1- col)) 0)
825       (setq m (cons (math-mat-col mat col) m)))
826     (cons 'vec m)))
827
828 (defun calcFunc-trn (mat)
829   (if (math-vectorp mat)
830       (if (math-matrixp mat)
831           (math-transpose mat)
832         (math-col-matrix mat))
833     (if (math-numberp mat)
834         mat
835       (math-reject-arg mat 'matrixp))))
836
837 (defun calcFunc-ctrn (mat)
838   (calcFunc-conj (calcFunc-trn mat)))
839
840 (defun calcFunc-pack (mode els)
841   (or (Math-vectorp els) (math-reject-arg els 'vectorp))
842   (if (and (Math-vectorp mode) (cdr mode))
843       (setq mode (cdr mode))
844     (or (integerp mode) (math-reject-arg mode 'fixnump)))
845   (condition-case err
846       (if (= (calc-pack-size mode) (1- (length els)))
847           (calc-pack-items mode (cdr els))
848         (math-reject-arg els "*Wrong number of elements"))
849     (error (math-reject-arg els (nth 1 err)))))
850
851 (defun calcFunc-unpack (mode thing)
852   (or (integerp mode) (math-reject-arg mode 'fixnump))
853   (condition-case err
854       (cons 'vec (calc-unpack-item mode thing))
855     (error (math-reject-arg thing (nth 1 err)))))
856
857 (defun calcFunc-unp