Merge changes from emacs-23 branch.
[bpt/emacs.git] / lisp / calc / calc-vec.el
CommitLineData
3132f345
CW
1;;; calc-vec.el --- vector functions for Calc
2
58ba2f8f 3;; Copyright (C) 1990, 1991, 1992, 1993, 2001, 2002, 2003, 2004,
114f9c96 4;; 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
3132f345
CW
5
6;; Author: David Gillespie <daveg@synaptics.com>
e8fff8ed 7;; Maintainer: Jay Belanger <jay.p.belanger@gmail.com>
136211a9
EZ
8
9;; This file is part of GNU Emacs.
10
662c9c64 11;; GNU Emacs is free software: you can redistribute it and/or modify
7c671b23 12;; it under the terms of the GNU General Public License as published by
662c9c64
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
7c671b23 15
136211a9 16;; GNU Emacs is distributed in the hope that it will be useful,
7c671b23
GM
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
662c9c64 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
136211a9 23
3132f345 24;;; Commentary:
136211a9 25
3132f345 26;;; Code:
136211a9
EZ
27
28;; This file is autoloaded from calc-ext.el.
136211a9 29
429dae43 30(require 'calc-ext)
136211a9
EZ
31(require 'calc-macs)
32
c4efb858
JB
33;; Declare functions which are defined elsewhere.
34(declare-function math-read-expr-level "calc-aent" (exp-prec &optional exp-term))
35
36
136211a9
EZ
37(defun calc-display-strings (n)
38 (interactive "P")
39 (calc-wrapper
40 (message (if (calc-change-mode 'calc-display-strings n t t)
3132f345
CW
41 "Displaying vectors of integers as quoted strings"
42 "Displaying vectors of integers normally"))))
136211a9
EZ
43
44
45(defun calc-pack (n)
46 (interactive "P")
47 (calc-wrapper
48 (let* ((nn (if n 1 2))
49 (mode (if n (prefix-numeric-value n) (calc-top-n 1)))
50 (mode (if (and (Math-vectorp mode) (cdr mode)) (cdr mode)
51 (if (integerp mode) mode
52 (error "Packing mode must be an integer or vector of integers"))))
53 (num (calc-pack-size mode))
54 (items (calc-top-list num nn)))
bf77c646 55 (calc-enter-result (+ nn num -1) "pack" (calc-pack-items mode items)))))
136211a9
EZ
56
57(defun calc-pack-size (mode)
58 (cond ((consp mode)
59 (let ((size 1))
60 (while mode
61 (or (integerp (car mode)) (error "Vector of integers expected"))
62 (setq size (* size (calc-pack-size (car mode)))
63 mode (cdr mode)))
64 (if (= size 0)
65 (error "Zero dimensions not allowed")
66 size)))
67 ((>= mode 0) mode)
68 (t (or (cdr (assq mode '((-3 . 3) (-13 . 1) (-14 . 3) (-15 . 6))))
bf77c646 69 2))))
136211a9
EZ
70
71(defun calc-pack-items (mode items)
72 (cond ((consp mode)
73 (if (cdr mode)
74 (let* ((size (calc-pack-size (cdr mode)))
75 (len (length items))
76 (new nil)
77 p row)
78 (while (> len 0)
79 (setq p (nthcdr (1- size) items)
80 row items
81 items (cdr p)
82 len (- len size))
83 (setcdr p nil)
84 (setq new (cons (calc-pack-items (cdr mode) row) new)))
85 (calc-pack-items (car mode) (nreverse new)))
86 (calc-pack-items (car mode) items)))
87 ((>= mode 0)
88 (cons 'vec items))
89 ((= mode -3)
90 (if (and (math-objvecp (car items))
91 (math-objvecp (nth 1 items))
92 (math-objvecp (nth 2 items)))
93 (if (and (math-num-integerp (car items))
94 (math-num-integerp (nth 1 items)))
95 (if (math-realp (nth 2 items))
96 (cons 'hms items)
97 (error "Seconds must be real"))
98 (error "Hours and minutes must be integers"))
99 (math-normalize (list '+
100 (list '+
101 (if (eq calc-angle-mode 'rad)
102 (list '* (car items)
103 '(hms 1 0 0))
104 (car items))
105 (list '* (nth 1 items) '(hms 0 1 0)))
106 (list '* (nth 2 items) '(hms 0 0 1))))))
107 ((= mode -13)
108 (if (math-realp (car items))
109 (cons 'date items)
110 (if (eq (car-safe (car items)) 'date)
111 (car items)
112 (if (math-objvecp (car items))
113 (error "Date value must be real")
114 (cons 'calcFunc-date items)))))
115 ((memq mode '(-14 -15))
116 (let ((p items))
117 (while (and p (math-objvecp (car p)))
118 (or (math-integerp (car p))
119 (error "Components must be integers"))
120 (setq p (cdr p)))
121 (if p
122 (cons 'calcFunc-date items)
123 (list 'date (math-dt-to-date items)))))
124 ((or (eq (car-safe (car items)) 'vec)
125 (eq (car-safe (nth 1 items)) 'vec))
126 (let* ((x (car items))
127 (vx (eq (car-safe x) 'vec))
128 (y (nth 1 items))
129 (vy (eq (car-safe y) 'vec))
130 (z nil)
131 (n (1- (length (if vx x y)))))
132 (and vx vy
133 (/= n (1- (length y)))
134 (error "Vectors must be the same length"))
135 (while (>= (setq n (1- n)) 0)
136 (setq z (cons (calc-pack-items
137 mode
138 (list (if vx (car (setq x (cdr x))) x)
139 (if vy (car (setq y (cdr y))) y)))
140 z)))
141 (cons 'vec (nreverse z))))
142 ((= mode -1)
143 (if (and (math-realp (car items)) (math-realp (nth 1 items)))
144 (cons 'cplx items)
145 (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
146 (error "Components must be real"))
147 (math-normalize (list '+ (car items)
148 (list '* (nth 1 items) '(cplx 0 1))))))
149 ((= mode -2)
150 (if (and (math-realp (car items)) (math-anglep (nth 1 items)))
151 (cons 'polar items)
152 (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
153 (error "Components must be real"))
154 (math-normalize (list '* (car items)
155 (if (math-anglep (nth 1 items))
156 (list 'polar 1 (nth 1 items))
157 (list 'calcFunc-exp
158 (list '*
159 (math-to-radians-2
160 (nth 1 items))
161 (list 'polar
162 1
163 (math-quarter-circle
164 nil)))))))))
165 ((= mode -4)
166 (let ((x (car items))
167 (sigma (nth 1 items)))
168 (if (or (math-scalarp x) (not (math-objvecp x)))
169 (if (or (math-anglep sigma) (not (math-objvecp sigma)))
170 (math-make-sdev x sigma)
171 (error "Error component must be real"))
172 (error "Mean component must be real or complex"))))
173 ((= mode -5)
174 (let ((a (car items))
175 (m (nth 1 items)))
176 (if (and (math-anglep a) (math-anglep m))
177 (if (math-posp m)
178 (math-make-mod a m)
179 (error "Modulus must be positive"))
180 (if (and (math-objectp a) (math-objectp m))
181 (error "Components must be real"))
182 (list 'calcFunc-makemod a m))))
183 ((memq mode '(-6 -7 -8 -9))
184 (let ((lo (car items))
185 (hi (nth 1 items)))
186 (if (and (or (math-anglep lo) (eq (car lo) 'date)
187 (not (math-objvecp lo)))
188 (or (math-anglep hi) (eq (car hi) 'date)
189 (not (math-objvecp hi))))
190 (math-make-intv (+ mode 9) lo hi)
191 (error "Components must be real"))))
192 ((eq mode -10)
193 (if (math-zerop (nth 1 items))
194 (error "Denominator must not be zero")
195 (if (and (math-integerp (car items)) (math-integerp (nth 1 items)))
196 (math-normalize (cons 'frac items))
197 (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
198 (error "Components must be integers"))
199 (cons 'calcFunc-fdiv items))))
200 ((memq mode '(-11 -12))
201 (if (and (math-realp (car items)) (math-integerp (nth 1 items)))
202 (calcFunc-scf (math-float (car items)) (nth 1 items))
203 (if (and (math-objectp (car items)) (math-objectp (nth 1 items)))
204 (error "Components must be integers"))
205 (math-normalize
206 (list 'calcFunc-scf
207 (list 'calcFunc-float (car items))
208 (nth 1 items)))))
209 (t
bf77c646 210 (error "Invalid packing mode: %d" mode))))
136211a9 211
3132f345 212(defvar calc-unpack-with-type nil)
136211a9
EZ
213(defun calc-unpack (mode)
214 (interactive "P")
215 (calc-wrapper
216 (let ((calc-unpack-with-type t))
217 (calc-pop-push-record-list 1 "unpk" (calc-unpack-item
218 (and mode
219 (prefix-numeric-value mode))
bf77c646 220 (calc-top))))))
136211a9
EZ
221
222(defun calc-unpack-type (item)
223 (cond ((eq (car-safe item) 'vec)
224 (1- (length item)))
225 ((eq (car-safe item) 'intv)
226 (- (nth 1 item) 9))
227 (t
228 (or (cdr (assq (car-safe item) '( (cplx . -1) (polar . -2)
229 (hms . -3) (sdev . -4) (mod . -5)
230 (frac . -10) (float . -11)
231 (date . -13) )))
bf77c646 232 (error "Argument must be a composite object")))))
136211a9
EZ
233
234(defun calc-unpack-item (mode item)
235 (cond ((not mode)
236 (if (or (and (not (memq (car-safe item) '(frac float cplx polar vec
237 hms date sdev mod
238 intv)))
239 (math-objvecp item))
240 (eq (car-safe item) 'var))
241 (error "Argument must be a composite object or function call"))
242 (if (eq (car item) 'intv)
243 (cdr (cdr item))
244 (cdr item)))
245 ((> mode 0)
246 (let ((dims nil)
247 type new row)
248 (setq item (list item))
249 (while (> mode 0)
250 (setq type (calc-unpack-type (car item))
251 dims (cons type dims)
252 new (calc-unpack-item nil (car item)))
253 (while (setq item (cdr item))
254 (or (= (calc-unpack-type (car item)) type)
255 (error "Inconsistent types or dimensions in vector elements"))
256 (setq new (append new (calc-unpack-item nil (car item)))))
257 (setq item new
258 mode (1- mode)))
259 (if (cdr dims) (setq dims (list (cons 'vec (nreverse dims)))))
260 (cond ((eq calc-unpack-with-type 'pair)
261 (list (car dims) (cons 'vec item)))
262 (calc-unpack-with-type
263 (append item dims))
264 (t item))))
265 ((eq calc-unpack-with-type 'pair)
266 (let ((calc-unpack-with-type nil))
267 (list mode (cons 'vec (calc-unpack-item mode item)))))
268 ((= mode -3)
269 (if (eq (car-safe item) 'hms)
270 (cdr item)
271 (error "Argument must be an HMS form")))
272 ((= mode -13)
273 (if (eq (car-safe item) 'date)
274 (cdr item)
275 (error "Argument must be a date form")))
276 ((= mode -14)
277 (if (eq (car-safe item) 'date)
278 (math-date-to-dt (math-floor (nth 1 item)))
279 (error "Argument must be a date form")))
280 ((= mode -15)
281 (if (eq (car-safe item) 'date)
282 (append (math-date-to-dt (nth 1 item))
283 (and (not (math-integerp (nth 1 item)))
284 (list 0 0 0)))
285 (error "Argument must be a date form")))
286 ((eq (car-safe item) 'vec)
287 (let ((x nil)
288 (y nil)
289 res)
290 (while (setq item (cdr item))
291 (setq res (calc-unpack-item mode (car item))
292 x (cons (car res) x)
293 y (cons (nth 1 res) y)))
294 (list (cons 'vec (nreverse x))
295 (cons 'vec (nreverse y)))))
296 ((= mode -1)
297 (if (eq (car-safe item) 'cplx)
298 (cdr item)
299 (if (eq (car-safe item) 'polar)
300 (cdr (math-complex item))
301 (if (Math-realp item)
302 (list item 0)
303 (error "Argument must be a complex number")))))
304 ((= mode -2)
305 (if (or (memq (car-safe item) '(cplx polar))
306 (Math-realp item))
307 (cdr (math-polar item))
308 (error "Argument must be a complex number")))
309 ((= mode -4)
310 (if (eq (car-safe item) 'sdev)
311 (cdr item)
312 (list item 0)))
313 ((= mode -5)
314 (if (eq (car-safe item) 'mod)
315 (cdr item)
316 (error "Argument must be a modulo form")))
317 ((memq mode '(-6 -7 -8 -9))
318 (if (eq (car-safe item) 'intv)
319 (cdr (cdr item))
320 (list item item)))
321 ((= mode -10)
322 (if (eq (car-safe item) 'frac)
323 (cdr item)
324 (if (Math-integerp item)
325 (list item 1)
326 (error "Argument must be a rational number"))))
327 ((= mode -11)
328 (if (eq (car-safe item) 'float)
329 (list (nth 1 item) (math-normalize (nth 2 item)))
330 (error "Expected a floating-point number")))
331 ((= mode -12)
332 (if (eq (car-safe item) 'float)
333 (list (calcFunc-mant item) (calcFunc-xpon item))
334 (error "Expected a floating-point number")))
335 (t
bf77c646 336 (error "Invalid unpacking mode: %d" mode))))
136211a9
EZ
337
338(defun calc-diag (n)
339 (interactive "P")
340 (calc-wrapper
341 (calc-enter-result 1 "diag" (if n
342 (list 'calcFunc-diag (calc-top-n 1)
343 (prefix-numeric-value n))
bf77c646 344 (list 'calcFunc-diag (calc-top-n 1))))))
136211a9
EZ
345
346(defun calc-ident (n)
347 (interactive "NDimension of identity matrix = ")
348 (calc-wrapper
349 (calc-enter-result 0 "idn" (if (eq n 0)
350 '(calcFunc-idn 1)
351 (list 'calcFunc-idn 1
bf77c646 352 (prefix-numeric-value n))))))
136211a9
EZ
353
354(defun calc-index (n &optional stack)
355 (interactive "NSize of vector = \nP")
356 (calc-wrapper
357 (if (consp stack)
358 (calc-enter-result 3 "indx" (cons 'calcFunc-index (calc-top-list-n 3)))
359 (calc-enter-result 0 "indx" (list 'calcFunc-index
bf77c646 360 (prefix-numeric-value n))))))
136211a9
EZ
361
362(defun calc-build-vector (n)
363 (interactive "NSize of vector = ")
364 (calc-wrapper
365 (calc-enter-result 1 "bldv" (list 'calcFunc-cvec
366 (calc-top-n 1)
bf77c646 367 (prefix-numeric-value n)))))
136211a9
EZ
368
369(defun calc-cons (arg)
370 (interactive "P")
371 (calc-wrapper
372 (if (calc-is-hyperbolic)
373 (calc-binary-op "rcns" 'calcFunc-rcons arg)
bf77c646 374 (calc-binary-op "cons" 'calcFunc-cons arg))))
136211a9
EZ
375
376
377(defun calc-head (arg)
378 (interactive "P")
379 (calc-wrapper
380 (if (calc-is-inverse)
381 (if (calc-is-hyperbolic)
382 (calc-unary-op "rtai" 'calcFunc-rtail arg)
383 (calc-unary-op "tail" 'calcFunc-tail arg))
384 (if (calc-is-hyperbolic)
385 (calc-unary-op "rhed" 'calcFunc-rhead arg)
bf77c646 386 (calc-unary-op "head" 'calcFunc-head arg)))))
136211a9
EZ
387
388(defun calc-tail (arg)
389 (interactive "P")
390 (calc-invert-func)
bf77c646 391 (calc-head arg))
136211a9
EZ
392
393(defun calc-vlength (arg)
394 (interactive "P")
395 (calc-wrapper
396 (if (calc-is-hyperbolic)
397 (calc-unary-op "dims" 'calcFunc-mdims arg)
bf77c646 398 (calc-unary-op "len" 'calcFunc-vlen arg))))
136211a9
EZ
399
400(defun calc-arrange-vector (n)
401 (interactive "NNumber of columns = ")
402 (calc-wrapper
403 (calc-enter-result 1 "arng" (list 'calcFunc-arrange (calc-top-n 1)
bf77c646 404 (prefix-numeric-value n)))))
136211a9
EZ
405
406(defun calc-vector-find (arg)
407 (interactive "P")
408 (calc-wrapper
409 (let ((func (cons 'calcFunc-find (calc-top-list-n 2))))
410 (calc-enter-result
411 2 "find"
bf77c646 412 (if arg (append func (list (prefix-numeric-value arg))) func)))))
136211a9
EZ
413
414(defun calc-subvector ()
415 (interactive)
416 (calc-wrapper
417 (if (calc-is-inverse)
418 (calc-enter-result 3 "rsvc" (cons 'calcFunc-rsubvec
419 (calc-top-list-n 3)))
bf77c646 420 (calc-enter-result 3 "svec" (cons 'calcFunc-subvec (calc-top-list-n 3))))))
136211a9
EZ
421
422(defun calc-reverse-vector (arg)
423 (interactive "P")
424 (calc-wrapper
bf77c646 425 (calc-unary-op "rev" 'calcFunc-rev arg)))
136211a9
EZ
426
427(defun calc-mask-vector (arg)
428 (interactive "P")
429 (calc-wrapper
bf77c646 430 (calc-binary-op "vmsk" 'calcFunc-vmask arg)))
136211a9
EZ
431
432(defun calc-expand-vector (arg)
433 (interactive "P")
434 (calc-wrapper
435 (if (calc-is-hyperbolic)
436 (calc-enter-result 3 "vexp" (cons 'calcFunc-vexp (calc-top-list-n 3)))
bf77c646 437 (calc-binary-op "vexp" 'calcFunc-vexp arg))))
136211a9
EZ
438
439(defun calc-sort ()
440 (interactive)
441 (calc-slow-wrapper
442 (if (calc-is-inverse)
443 (calc-enter-result 1 "rsrt" (list 'calcFunc-rsort (calc-top-n 1)))
bf77c646 444 (calc-enter-result 1 "sort" (list 'calcFunc-sort (calc-top-n 1))))))
136211a9
EZ
445
446(defun calc-grade ()
447 (interactive)
448 (calc-slow-wrapper
449 (if (calc-is-inverse)
450 (calc-enter-result 1 "rgrd" (list 'calcFunc-rgrade (calc-top-n 1)))
bf77c646 451 (calc-enter-result 1 "grad" (list 'calcFunc-grade (calc-top-n 1))))))
136211a9
EZ
452
453(defun calc-histogram (n)
597517ef
JB
454 (interactive "P")
455 (unless (natnump n)
456 (setq n (math-read-expr (read-string "Centers of bins: "))))
136211a9
EZ
457 (calc-slow-wrapper
458 (if calc-hyperbolic-flag
459 (calc-enter-result 2 "hist" (list 'calcFunc-histogram
460 (calc-top-n 2)
461 (calc-top-n 1)
597517ef 462 n))
136211a9
EZ
463 (calc-enter-result 1 "hist" (list 'calcFunc-histogram
464 (calc-top-n 1)
597517ef 465 n)))))
136211a9
EZ
466
467(defun calc-transpose (arg)
468 (interactive "P")
469 (calc-wrapper
bf77c646 470 (calc-unary-op "trn" 'calcFunc-trn arg)))
136211a9
EZ
471
472(defun calc-conj-transpose (arg)
473 (interactive "P")
474 (calc-wrapper
bf77c646 475 (calc-unary-op "ctrn" 'calcFunc-ctrn arg)))
136211a9
EZ
476
477(defun calc-cross (arg)
478 (interactive "P")
479 (calc-wrapper
bf77c646 480 (calc-binary-op "cros" 'calcFunc-cross arg)))
136211a9 481
1aa484e3
JB
482(defun calc-kron (arg)
483 (interactive "P")
484 (calc-wrapper
485 (calc-binary-op "kron" 'calcFunc-kron arg)))
486
136211a9
EZ
487(defun calc-remove-duplicates (arg)
488 (interactive "P")
489 (calc-wrapper
bf77c646 490 (calc-unary-op "rdup" 'calcFunc-rdup arg)))
136211a9
EZ
491
492(defun calc-set-union (arg)
493 (interactive "P")
494 (calc-wrapper
bf77c646 495 (calc-binary-op "unio" 'calcFunc-vunion arg '(vec) 'calcFunc-rdup)))
136211a9
EZ
496
497(defun calc-set-intersect (arg)
498 (interactive "P")
499 (calc-wrapper
bf77c646 500 (calc-binary-op "intr" 'calcFunc-vint arg '(vec) 'calcFunc-rdup)))
136211a9
EZ
501
502(defun calc-set-difference (arg)
503 (interactive "P")
504 (calc-wrapper
bf77c646 505 (calc-binary-op "diff" 'calcFunc-vdiff arg '(vec) 'calcFunc-rdup)))
136211a9
EZ
506
507(defun calc-set-xor (arg)
508 (interactive "P")
509 (calc-wrapper
bf77c646 510 (calc-binary-op "xor" 'calcFunc-vxor arg '(vec) 'calcFunc-rdup)))
136211a9
EZ
511
512(defun calc-set-complement (arg)
513 (interactive "P")
514 (calc-wrapper
bf77c646 515 (calc-unary-op "cmpl" 'calcFunc-vcompl arg)))
136211a9
EZ
516
517(defun calc-set-floor (arg)
518 (interactive "P")
519 (calc-wrapper
bf77c646 520 (calc-unary-op "vflr" 'calcFunc-vfloor arg)))
136211a9
EZ
521
522(defun calc-set-enumerate (arg)
523 (interactive "P")
524 (calc-wrapper
bf77c646 525 (calc-unary-op "enum" 'calcFunc-venum arg)))
136211a9
EZ
526
527(defun calc-set-span (arg)
528 (interactive "P")
529 (calc-wrapper
bf77c646 530 (calc-unary-op "span" 'calcFunc-vspan arg)))
136211a9
EZ
531
532(defun calc-set-cardinality (arg)
533 (interactive "P")
534 (calc-wrapper
bf77c646 535 (calc-unary-op "card" 'calcFunc-vcard arg)))
136211a9
EZ
536
537(defun calc-unpack-bits (arg)
538 (interactive "P")
539 (calc-wrapper
540 (if (calc-is-inverse)
541 (calc-unary-op "bpck" 'calcFunc-vpack arg)
bf77c646 542 (calc-unary-op "bupk" 'calcFunc-vunpack arg))))
136211a9
EZ
543
544(defun calc-pack-bits (arg)
545 (interactive "P")
546 (calc-invert-func)
bf77c646 547 (calc-unpack-bits arg))
136211a9
EZ
548
549
550(defun calc-rnorm (arg)
551 (interactive "P")
552 (calc-wrapper
bf77c646 553 (calc-unary-op "rnrm" 'calcFunc-rnorm arg)))
136211a9
EZ
554
555(defun calc-cnorm (arg)
556 (interactive "P")
557 (calc-wrapper
bf77c646 558 (calc-unary-op "cnrm" 'calcFunc-cnorm arg)))
136211a9
EZ
559
560(defun calc-mrow (n &optional nn)
561 (interactive "NRow number: \nP")
562 (calc-wrapper
563 (if (consp nn)
564 (calc-enter-result 2 "mrow" (cons 'calcFunc-mrow (calc-top-list-n 2)))
565 (setq n (prefix-numeric-value n))
566 (if (= n 0)
567 (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
568 (if (< n 0)
569 (calc-enter-result 1 "rrow" (list 'calcFunc-mrrow
570 (calc-top-n 1) (- n)))
571 (calc-enter-result 1 "mrow" (list 'calcFunc-mrow
bf77c646 572 (calc-top-n 1) n)))))))
136211a9
EZ
573
574(defun calc-mcol (n &optional nn)
575 (interactive "NColumn number: \nP")
576 (calc-wrapper
577 (if (consp nn)
578 (calc-enter-result 2 "mcol" (cons 'calcFunc-mcol (calc-top-list-n 2)))
579 (setq n (prefix-numeric-value n))
580 (if (= n 0)
581 (calc-enter-result 1 "getd" (list 'calcFunc-getdiag (calc-top-n 1)))
582 (if (< n 0)
583 (calc-enter-result 1 "rcol" (list 'calcFunc-mrcol
584 (calc-top-n 1) (- n)))
585 (calc-enter-result 1 "mcol" (list 'calcFunc-mcol
bf77c646 586 (calc-top-n 1) n)))))))
136211a9
EZ
587
588
589;;;; Vectors.
590
591(defun calcFunc-mdims (m)
592 (or (math-vectorp m)
593 (math-reject-arg m 'vectorp))
bf77c646 594 (cons 'vec (math-mat-dimens m)))
136211a9
EZ
595
596
597;;; Apply a function elementwise to vector A. [V X V; N X N] [Public]
598(defun math-map-vec (f a)
599 (if (math-vectorp a)
600 (cons 'vec (mapcar f (cdr a)))
bf77c646 601 (funcall f a)))
136211a9
EZ
602
603(defun math-dimension-error ()
604 (calc-record-why "*Dimension error")
bf77c646 605 (signal 'wrong-type-argument nil))
136211a9
EZ
606
607
608;;; Build a vector out of a list of objects. [Public]
609(defun calcFunc-vec (&rest objs)
bf77c646 610 (cons 'vec objs))
136211a9
EZ
611
612
613;;; Build a constant vector or matrix. [Public]
614(defun calcFunc-cvec (obj &rest dims)
bf77c646 615 (math-make-vec-dimen obj dims))
136211a9
EZ
616
617(defun math-make-vec-dimen (obj dims)
618 (if dims
619 (if (natnump (car dims))
620 (if (or (cdr dims)
621 (not (math-numberp obj)))
622 (cons 'vec (copy-sequence
623 (make-list (car dims)
624 (math-make-vec-dimen obj (cdr dims)))))
625 (cons 'vec (make-list (car dims) obj)))
626 (math-reject-arg (car dims) 'fixnatnump))
bf77c646 627 obj))
136211a9
EZ
628
629(defun calcFunc-head (vec)
630 (if (and (Math-vectorp vec)
631 (cdr vec))
632 (nth 1 vec)
633 (calc-record-why 'vectorp vec)
bf77c646 634 (list 'calcFunc-head vec)))
136211a9
EZ
635
636(defun calcFunc-tail (vec)
637 (if (and (Math-vectorp vec)
638 (cdr vec))
639 (cons 'vec (cdr (cdr vec)))
640 (calc-record-why 'vectorp vec)
bf77c646 641 (list 'calcFunc-tail vec)))
136211a9
EZ
642
643(defun calcFunc-cons (head tail)
644 (if (Math-vectorp tail)
645 (cons 'vec (cons head (cdr tail)))
646 (calc-record-why 'vectorp tail)
bf77c646 647 (list 'calcFunc-cons head tail)))
136211a9
EZ
648
649(defun calcFunc-rhead (vec)
650 (if (and (Math-vectorp vec)
651 (cdr vec))
652 (let ((vec (copy-sequence vec)))
653 (setcdr (nthcdr (- (length vec) 2) vec) nil)
654 vec)
655 (calc-record-why 'vectorp vec)
bf77c646 656 (list 'calcFunc-rhead vec)))
136211a9
EZ
657
658(defun calcFunc-rtail (vec)
659 (if (and (Math-vectorp vec)
660 (cdr vec))
661 (nth (1- (length vec)) vec)
662 (calc-record-why 'vectorp vec)
bf77c646 663 (list 'calcFunc-rtail vec)))
136211a9
EZ
664
665(defun calcFunc-rcons (head tail)
666 (if (Math-vectorp head)
667 (append head (list tail))
668 (calc-record-why 'vectorp head)
bf77c646 669 (list 'calcFunc-rcons head tail)))
136211a9
EZ
670
671
672
673;;; Apply a function elementwise to vectors A and B. [O X O O] [Public]
674(defun math-map-vec-2 (f a b)
675 (if (math-vectorp a)
676 (if (math-vectorp b)
677 (let ((v nil))
678 (while (setq a (cdr a))
679 (or (setq b (cdr b))
680 (math-dimension-error))
681 (setq v (cons (funcall f (car a) (car b)) v)))
682 (if a (math-dimension-error))
683 (cons 'vec (nreverse v)))
684 (let ((v nil))
685 (while (setq a (cdr a))
686 (setq v (cons (funcall f (car a) b) v)))
687 (cons 'vec (nreverse v))))
688 (if (math-vectorp b)
689 (let ((v nil))
690 (while (setq b (cdr b))
691 (setq v (cons (funcall f a (car b)) v)))
692 (cons 'vec (nreverse v)))
bf77c646 693 (funcall f a b))))
136211a9
EZ
694
695
696
697;;; "Reduce" a function over a vector (left-associatively). [O X V] [Public]
698(defun math-reduce-vec (f a)
699 (if (math-vectorp a)
700 (if (cdr a)
701 (let ((accum (car (setq a (cdr a)))))
702 (while (setq a (cdr a))
703 (setq accum (funcall f accum (car a))))
704 accum)
705 0)
bf77c646 706 a))
136211a9
EZ
707
708;;; Reduce a function over the columns of matrix A. [V X V] [Public]
709(defun math-reduce-cols (f a)
710 (if (math-matrixp a)
711 (cons 'vec (math-reduce-cols-col-step f (cdr a) 1 (length (nth 1 a))))
bf77c646 712 a))
136211a9
EZ
713
714(defun math-reduce-cols-col-step (f a col cols)
715 (and (< col cols)
716 (cons (math-reduce-cols-row-step f (nth col (car a)) col (cdr a))
bf77c646 717 (math-reduce-cols-col-step f a (1+ col) cols))))
136211a9
EZ
718
719(defun math-reduce-cols-row-step (f tot col a)
720 (if a
721 (math-reduce-cols-row-step f
722 (funcall f tot (nth col (car a)))
723 col
724 (cdr a))
bf77c646 725 tot))
136211a9
EZ
726
727
728
729(defun math-dot-product (a b)
730 (if (setq a (cdr a) b (cdr b))
731 (let ((accum (math-mul (car a) (car b))))
732 (while (setq a (cdr a) b (cdr b))
733 (setq accum (math-add accum (math-mul (car a) (car b)))))
734 accum)
bf77c646 735 0))
136211a9
EZ
736
737
738;;; Return the number of elements in vector V. [Public]
739(defun calcFunc-vlen (v)
740 (if (math-vectorp v)
741 (1- (length v))
742 (if (math-objectp v)
743 0
bf77c646 744 (list 'calcFunc-vlen v))))
136211a9
EZ
745
746;;; Get the Nth row of a matrix.
747(defun calcFunc-mrow (mat n) ; [Public]
748 (if (Math-vectorp n)
749 (math-map-vec (function (lambda (x) (calcFunc-mrow mat x))) n)
750 (if (and (eq (car-safe n) 'intv) (math-constp n))
751 (calcFunc-subvec mat
752 (math-add (nth 2 n) (if (memq (nth 1 n) '(2 3)) 0 1))
753 (math-add (nth 3 n) (if (memq (nth 1 n) '(1 3)) 1 0)))
754 (or (and (integerp (setq n (math-check-integer n)))
755 (> n 0))
756 (math-reject-arg n 'fixposintp))
757 (or (Math-vectorp mat)
758 (math-reject-arg mat 'vectorp))
759 (or (nth n mat)
bf77c646 760 (math-reject-arg n "*Index out of range")))))
136211a9
EZ
761
762(defun calcFunc-subscr (mat n &optional m)
763 (setq mat (calcFunc-mrow mat n))
764 (if m
765 (if (math-num-integerp n)
766 (calcFunc-mrow mat m)
767 (calcFunc-mcol mat m))
bf77c646 768 mat))
136211a9
EZ
769
770;;; Get the Nth column of a matrix.
771(defun math-mat-col (mat n)
bf77c646 772 (cons 'vec (mapcar (function (lambda (x) (elt x n))) (cdr mat))))
136211a9
EZ
773
774(defun calcFunc-mcol (mat n) ; [Public]
775 (if (Math-vectorp n)
776 (calcFunc-trn
777 (math-map-vec (function (lambda (x) (calcFunc-mcol mat x))) n))
778 (if (and (eq (car-safe n) 'intv) (math-constp n))
779 (if (math-matrixp mat)
780 (math-map-vec (function (lambda (x) (calcFunc-mrow x n))) mat)
781 (calcFunc-mrow mat n))
782 (or (and (integerp (setq n (math-check-integer n)))
783 (> n 0))
784 (math-reject-arg n 'fixposintp))
785 (or (Math-vectorp mat)
786 (math-reject-arg mat 'vectorp))
787 (or (if (math-matrixp mat)
788 (and (< n (length (nth 1 mat)))
789 (math-mat-col mat n))
790 (nth n mat))
bf77c646 791 (math-reject-arg n "*Index out of range")))))
136211a9
EZ
792
793;;; Remove the Nth row from a matrix.
794(defun math-mat-less-row (mat n)
795 (if (<= n 0)
796 (cdr mat)
797 (cons (car mat)
bf77c646 798 (math-mat-less-row (cdr mat) (1- n)))))
136211a9
EZ
799
800(defun calcFunc-mrrow (mat n) ; [Public]
801 (and (integerp (setq n (math-check-integer n)))
802 (> n 0)
803 (< n (length mat))
bf77c646 804 (math-mat-less-row mat n)))
136211a9
EZ
805
806;;; Remove the Nth column from a matrix.
807(defun math-mat-less-col (mat n)
808 (cons 'vec (mapcar (function (lambda (x) (math-mat-less-row x n)))
bf77c646 809 (cdr mat))))
136211a9
EZ
810
811(defun calcFunc-mrcol (mat n) ; [Public]
812 (and (integerp (setq n (math-check-integer n)))
813 (> n 0)
814 (if (math-matrixp mat)
815 (and (< n (length (nth 1 mat)))
816 (math-mat-less-col mat n))
bf77c646 817 (math-mat-less-row mat n))))
136211a9
EZ
818
819(defun calcFunc-getdiag (mat) ; [Public]
820 (if (math-square-matrixp mat)
821 (cons 'vec (math-get-diag-step (cdr mat) 1))
822 (calc-record-why 'square-matrixp mat)
bf77c646 823 (list 'calcFunc-getdiag mat)))
136211a9
EZ
824
825(defun math-get-diag-step (row n)
826 (and row
827 (cons (nth n (car row))
bf77c646 828 (math-get-diag-step (cdr row) (1+ n)))))
136211a9
EZ
829
830(defun math-transpose (mat) ; [Public]
831 (let ((m nil)
832 (col (length (nth 1 mat))))
833 (while (> (setq col (1- col)) 0)
834 (setq m (cons (math-mat-col mat col) m)))
bf77c646 835 (cons 'vec m)))
136211a9
EZ
836
837(defun calcFunc-trn (mat)
838 (if (math-vectorp mat)
839 (if (math-matrixp mat)
840 (math-transpose mat)
841 (math-col-matrix mat))
842 (if (math-numberp mat)
843 mat
bf77c646 844 (math-reject-arg mat 'matrixp))))
136211a9
EZ
845
846(defun calcFunc-ctrn (mat)
bf77c646 847 (calcFunc-conj (calcFunc-trn mat)))
136211a9
EZ
848
849(defun calcFunc-pack (mode els)
850 (or (Math-vectorp els) (math-reject-arg els 'vectorp))
851 (if (and (Math-vectorp mode) (cdr mode))
852 (setq mode (cdr mode))
853 (or (integerp mode) (math-reject-arg mode 'fixnump)))
854 (condition-case err
855 (if (= (calc-pack-size mode) (1- (length els)))
856 (calc-pack-items mode (cdr els))
857 (math-reject-arg els "*Wrong number of elements"))
bf77c646 858 (error (math-reject-arg els (nth 1 err)))))
136211a9
EZ
859
860(defun calcFunc-unpack (mode thing)
861 (or (integerp mode) (math-reject-arg mode 'fixnump))
862 (condition-case err
863 (cons 'vec (calc-unpack-item mode thing))
bf77c646 864 (error (math-reject-arg thing (nth 1 err)))))
136211a9
EZ
865
866(defun calcFunc-unpackt (mode thing)
867 (let ((calc-unpack-with-type 'pair))
bf77c646 868 (calcFunc-unpack mode thing)))
136211a9
EZ
869
870(defun calcFunc-arrange (vec cols) ; [Public]
871 (setq cols (math-check-fixnum cols t))
872 (if (math-vectorp vec)
873 (let* ((flat (math-flatten-vector vec))
874 (mat (list 'vec))
875 next)
876 (if (<= cols 0)
877 (nconc mat flat)
878 (while (>= (length flat) cols)
879 (setq next (nthcdr cols flat))
880 (setcdr (nthcdr (1- cols) flat) nil)
881 (setq mat (nconc mat (list (cons 'vec flat)))
882 flat next))
883 (if flat
884 (setq mat (nconc mat (list (cons 'vec flat)))))
bf77c646 885 mat))))
136211a9
EZ
886
887(defun math-flatten-vector (vec) ; [L V]
888 (if (math-vectorp vec)
889 (apply 'append (mapcar 'math-flatten-vector (cdr vec)))
bf77c646 890 (list vec)))
136211a9
EZ
891
892(defun calcFunc-vconcat (a b)
bf77c646 893 (math-normalize (list '| a b)))
136211a9
EZ
894
895(defun calcFunc-vconcatrev (a b)
bf77c646 896 (math-normalize (list '| b a)))
136211a9
EZ
897
898(defun calcFunc-append (v1 v2)
899 (if (and (math-vectorp v1) (math-vectorp v2))
900 (append v1 (cdr v2))
bf77c646 901 (list 'calcFunc-append v1 v2)))
136211a9
EZ
902
903(defun calcFunc-appendrev (v1 v2)
bf77c646 904 (calcFunc-append v2 v1))
136211a9
EZ
905
906
907;;; Copy a matrix. [Public]
908(defun math-copy-matrix (m)
909 (if (math-vectorp (nth 1 m))
910 (cons 'vec (mapcar 'copy-sequence (cdr m)))
bf77c646 911 (copy-sequence m)))
136211a9
EZ
912
913;;; Convert a scalar or vector into an NxN diagonal matrix. [Public]
914(defun calcFunc-diag (a &optional n)
915 (and n (not (integerp n))
916 (setq n (math-check-fixnum n)))
917 (if (math-vectorp a)
918 (if (and n (/= (length a) (1+ n)))
919 (list 'calcFunc-diag a n)
920 (if (math-matrixp a)
921 (if (and n (/= (length (elt a 1)) (1+ n)))
922 (list 'calcFunc-diag a n)
923 a)
924 (cons 'vec (math-diag-step (cdr a) 0 (1- (length a))))))
925 (if n
926 (cons 'vec (math-diag-step (make-list n a) 0 n))
bf77c646 927 (list 'calcFunc-diag a))))
136211a9
EZ
928
929(defun calcFunc-idn (a &optional n)
930 (if n
931 (if (math-vectorp a)
932 (math-reject-arg a 'numberp)
933 (calcFunc-diag a n))
934 (if (integerp calc-matrix-mode)
935 (calcFunc-idn a calc-matrix-mode)
bf77c646 936 (list 'calcFunc-idn a))))
136211a9
EZ
937
938(defun math-mimic-ident (a m)
939 (if (math-square-matrixp m)
940 (calcFunc-idn a (1- (length m)))
941 (if (math-vectorp m)
942 (if (math-zerop a)
943 (cons 'vec (mapcar (function (lambda (x)
944 (if (math-vectorp x)
945 (math-mimic-ident a x)
946 a)))
947 (cdr m)))
948 (math-dimension-error))
bf77c646 949 (calcFunc-idn a))))
136211a9
EZ
950
951(defun math-diag-step (a n m)
952 (if (< n m)
953 (cons (cons 'vec
954 (nconc (make-list n 0)
955 (cons (car a)
956 (make-list (1- (- m n)) 0))))
957 (math-diag-step (cdr a) (1+ n) m))
bf77c646 958 nil))
136211a9
EZ
959
960;;; Create a vector of consecutive integers. [Public]
961(defun calcFunc-index (n &optional start incr)
962 (if (math-messy-integerp n)
963 (math-float (calcFunc-index (math-trunc n) start incr))
964 (and (not (integerp n))
965 (setq n (math-check-fixnum n)))
966 (let ((vec nil))
967 (if start
968 (progn
969 (if (>= n 0)
970 (while (>= (setq n (1- n)) 0)
971 (setq vec (cons start vec)
972 start (math-add start (or incr 1))))
973 (while (<= (setq n (1+ n)) 0)
974 (setq vec (cons start vec)
975 start (math-mul start (or incr 2)))))
976 (setq vec (nreverse vec)))
977 (if (>= n 0)
978 (while (> n 0)
979 (setq vec (cons n vec)
980 n (1- n)))
981 (let ((i -1))
982 (while (>= i n)
983 (setq vec (cons i vec)
984 i (1- i))))))
bf77c646 985 (cons 'vec vec))))
136211a9
EZ
986
987;;; Find an element in a vector.
988(defun calcFunc-find (vec x &optional start)
989 (setq start (if start (math-check-fixnum start t) 1))
990 (if (< start 1) (math-reject-arg start 'posp))
991 (setq vec (nthcdr start vec))
992 (let ((n start))
993 (while (and vec (not (Math-equal x (car vec))))
994 (setq n (1+ n)
995 vec (cdr vec)))
bf77c646 996 (if vec n 0)))
136211a9
EZ
997
998;;; Return a subvector of a vector.
999(defun calcFunc-subvec (vec start &optional end)
1000 (setq start (math-check-fixnum start t)
1001 end (math-check-fixnum (or end 0) t))
1002 (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
1003 (let ((len (1- (length vec))))
1004 (if (<= start 0)
1005 (setq start (+ len start 1)))
1006 (if (<= end 0)
1007 (setq end (+ len end 1)))
1008 (if (or (> start len)
1009 (<= end start))
1010 '(vec)
1011 (setq vec (nthcdr start vec))
1012 (if (<= end len)
1013 (let ((chop (nthcdr (- end start 1) (setq vec (copy-sequence vec)))))
1014 (setcdr chop nil)))
bf77c646 1015 (cons 'vec vec))))
136211a9
EZ
1016
1017;;; Remove a subvector from a vector.
1018(defun calcFunc-rsubvec (vec start &optional end)
1019 (setq start (math-check-fixnum start t)
1020 end (math-check-fixnum (or end 0) t))
1021 (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
1022 (let ((len (1- (length vec))))
1023 (if (<= start 0)
1024 (setq start (+ len start 1)))
1025 (if (<= end 0)
1026 (setq end (+ len end 1)))
1027 (if (or (> start len)
1028 (<= end start))
1029 vec
1030 (let ((tail (nthcdr end vec))
1031 (chop (nthcdr (1- start) (setq vec (copy-sequence vec)))))
1032 (setcdr chop nil)
bf77c646 1033 (append vec tail)))))
136211a9
EZ
1034
1035;;; Reverse the order of the elements of a vector.
1036(defun calcFunc-rev (vec)
1037 (if (math-vectorp vec)
1038 (cons 'vec (reverse (cdr vec)))
bf77c646 1039 (math-reject-arg vec 'vectorp)))
136211a9
EZ
1040
1041;;; Compress a vector according to a mask vector.
1042(defun calcFunc-vmask (mask vec)
1043 (if (math-numberp mask)
1044 (if (math-zerop mask)
1045 '(vec)
1046 vec)
1047 (or (math-vectorp mask) (math-reject-arg mask 'vectorp))
1048 (or (math-constp mask) (math-reject-arg mask 'constp))
1049 (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
1050 (or (= (length mask) (length vec)) (math-dimension-error))
1051 (let ((new nil))
1052 (while (setq mask (cdr mask) vec (cdr vec))
1053 (or (math-zerop (car mask))
1054 (setq new (cons (car vec) new))))
bf77c646 1055 (cons 'vec (nreverse new)))))
136211a9
EZ
1056
1057;;; Expand a vector according to a mask vector.
1058(defun calcFunc-vexp (mask vec &optional filler)
1059 (or (math-vectorp mask) (math-reject-arg mask 'vectorp))
1060 (or (math-constp mask) (math-reject-arg mask 'constp))
1061 (or (math-vectorp vec) (math-reject-arg vec 'vectorp))
1062 (let ((new nil)
1063 (fvec (and filler (math-vectorp filler))))
1064 (while (setq mask (cdr mask))
1065 (if (math-zerop (car mask))
1066 (setq new (cons (or (if fvec
1067 (car (setq filler (cdr filler)))
1068 filler)
1069 (car mask)) new))
1070 (setq vec (cdr vec)
1071 new (cons (or (car vec) (car mask)) new))))
bf77c646 1072 (cons 'vec (nreverse new))))
136211a9
EZ
1073
1074
1075;;; Compute the row and column norms of a vector or matrix. [Public]
1076(defun calcFunc-rnorm (a)
1077 (if (and (Math-vectorp a)
1078 (math-constp a))
1079 (if (math-matrixp a)
1080 (math-reduce-vec 'math-max (math-map-vec 'calcFunc-cnorm a))
1081 (math-reduce-vec 'math-max (math-map-vec 'math-abs a)))
1082 (calc-record-why 'vectorp a)
bf77c646 1083 (list 'calcFunc-rnorm a)))
136211a9
EZ
1084
1085(defun calcFunc-cnorm (a)
1086 (if (and (Math-vectorp a)
1087 (math-constp a))
1088 (if (math-matrixp a)
1089 (math-reduce-vec 'math-max
1090 (math-reduce-cols 'math-add-abs a))
1091 (math-reduce-vec 'math-add-abs a))
1092 (calc-record-why 'vectorp a)
bf77c646 1093 (list 'calcFunc-cnorm a)))
136211a9
EZ
1094
1095(defun math-add-abs (a b)
bf77c646 1096 (math-add (math-abs a) (math-abs b)))
136211a9
EZ
1097
1098
1099;;; Sort the elements of a vector into increasing order.
1100(defun calcFunc-sort (vec) ; [Public]
1101 (if (math-vectorp vec)
1102 (cons 'vec (sort (copy-sequence (cdr vec)) 'math-beforep))
bf77c646 1103 (math-reject-arg vec 'vectorp)))
136211a9
EZ
1104
1105(defun calcFunc-rsort (vec) ; [Public]
1106 (if (math-vectorp vec)
1107 (cons 'vec (nreverse (sort (copy-sequence (cdr vec)) 'math-beforep)))
bf77c646 1108 (math-reject-arg vec 'vectorp)))
136211a9 1109
866ebaa9
JB
1110;; The variable math-grade-vec is local to calcFunc-grade and
1111;; calcFunc-rgrade, but is used by math-grade-beforep, which is called
1112;; by calcFunc-grade and calcFunc-rgrade.
1113(defvar math-grade-vec)
1114
1115(defun calcFunc-grade (math-grade-vec)
1116 (if (math-vectorp math-grade-vec)
1117 (let* ((len (1- (length math-grade-vec))))
136211a9 1118 (cons 'vec (sort (cdr (calcFunc-index len)) 'math-grade-beforep)))
866ebaa9 1119 (math-reject-arg math-grade-vec 'vectorp)))
136211a9 1120
866ebaa9
JB
1121(defun calcFunc-rgrade (math-grade-vec)
1122 (if (math-vectorp math-grade-vec)
1123 (let* ((len (1- (length math-grade-vec))))
136211a9
EZ
1124 (cons 'vec (nreverse (sort (cdr (calcFunc-index len))
1125 'math-grade-beforep))))
866ebaa9 1126 (math-reject-arg math-grade-vec 'vectorp)))
136211a9
EZ
1127
1128(defun math-grade-beforep (i j)
866ebaa9 1129 (math-beforep (nth i math-grade-vec) (nth j math-grade-vec)))
136211a9
EZ
1130
1131
1132;;; Compile a histogram of data from a vector.
1133(defun calcFunc-histogram (vec wts &optional n)
1134 (or n (setq n wts wts 1))
1135 (or (Math-vectorp vec)
1136 (math-reject-arg vec 'vectorp))
1137 (if (Math-vectorp wts)
1138 (or (= (length vec) (length wts))
1139 (math-dimension-error)))
597517ef
JB
1140 (cond ((natnump n)
1141 (let ((res (make-vector n 0))
1142 (vp vec)
1143 (wvec (Math-vectorp wts))
1144 (wp wts)
1145 bin)
1146 (while (setq vp (cdr vp))
1147 (setq bin (car vp))
1148 (or (natnump bin)
1149 (setq bin (math-floor bin)))
1150 (and (natnump bin)
1151 (< bin n)
1152 (aset res bin
1153 (math-add (aref res bin)
1154 (if wvec (car (setq wp (cdr wp))) wts)))))
1155 (cons 'vec (append res nil))))
1156 ((Math-vectorp n) ;; n is a vector of midpoints
1157 (let* ((bds (math-vector-avg n))
1158 (res (make-vector (1- (length n)) 0))
1159 (vp (cdr vec))
1160 (wvec (Math-vectorp wts))
1161 (wp wts)
1162 num)
1163 (while vp
1164 (setq num (car vp))
1165 (let ((tbds (cdr bds))
1166 (i 0))
1167 (while (and tbds (Math-lessp (car tbds) num))
1168 (setq i (1+ i))
1169 (setq tbds (cdr tbds)))
1170 (aset res i
1171 (math-add (aref res i)
1172 (if wvec (car (setq wp (cdr wp))) wts))))
1173 (setq vp (cdr vp)))
1174 (cons 'vec (append res nil))))
1175 (t
1176 (math-reject-arg n "*Expecting an integer or vector"))))
1177
1178;;; Replace a vector [a b c ...] with a vector of averages
1179;;; [(a+b)/2 (b+c)/2 ...]
1180(defun math-vector-avg (vec)
00681a3c 1181 (let ((vp (sort (copy-sequence (cdr vec)) 'math-beforep))
597517ef
JB
1182 (res nil))
1183 (while (and vp (cdr vp))
1184 (setq res (cons (math-div (math-add (car vp) (cadr vp)) 2) res)
1185 vp (cdr vp)))
1186 (cons 'vec (reverse res))))
136211a9
EZ
1187
1188
1189;;; Set operations.
1190
1191(defun calcFunc-vunion (a b)
1192 (if (Math-objectp a)
1193 (setq a (list 'vec a))
1194 (or (math-vectorp a) (math-reject-arg a 'vectorp)))
1195 (if (Math-objectp b)
1196 (setq b (list b))
1197 (or (math-vectorp b) (math-reject-arg b 'vectorp))
1198 (setq b (cdr b)))
bf77c646 1199 (calcFunc-rdup (append a b)))
136211a9
EZ
1200
1201(defun calcFunc-vint (a b)
1202 (if (and (math-simple-set a) (math-simple-set b))
1203 (progn
1204 (setq a (cdr (calcFunc-rdup a)))
1205 (setq b (cdr (calcFunc-rdup b)))
1206 (let ((vec (list 'vec)))
1207 (while (and a b)
1208 (if (math-beforep (car a) (car b))
1209 (setq a (cdr a))
1210 (if (Math-equal (car a) (car b))
1211 (setq vec (cons (car a) vec)
1212 a (cdr a)))
1213 (setq b (cdr b))))
1214 (nreverse vec)))
1215 (calcFunc-vcompl (calcFunc-vunion (calcFunc-vcompl a)
bf77c646 1216 (calcFunc-vcompl b)))))
136211a9
EZ
1217
1218(defun calcFunc-vdiff (a b)
1219 (if (and (math-simple-set a) (math-simple-set b))
1220 (progn
1221 (setq a (cdr (calcFunc-rdup a)))
1222 (setq b (cdr (calcFunc-rdup b)))
1223 (let ((vec (list 'vec)))
1224 (while a
1225 (while (and b (math-beforep (car b) (car a)))
1226 (setq b (cdr b)))
1227 (if (and b (Math-equal (car a) (car b)))
1228 (setq a (cdr a)
1229 b (cdr b))
1230 (setq vec (cons (car a) vec)
1231 a (cdr a))))
1232 (nreverse vec)))
bf77c646 1233 (calcFunc-vcompl (calcFunc-vunion (calcFunc-vcompl a) b))))
136211a9
EZ
1234
1235(defun calcFunc-vxor (a b)
1236 (if (and (math-simple-set a) (math-simple-set b))
1237 (progn
1238 (setq a (cdr (calcFunc-rdup a)))
1239 (setq b (cdr (calcFunc-rdup b)))
1240 (let ((vec (list 'vec)))
1241 (while (or a b)
1242 (if (and a
1243 (or (not b)
1244 (math-beforep (car a) (car b))))
1245 (setq vec (cons (car a) vec)
1246 a (cdr a))
1247 (if (and a (Math-equal (car a) (car b)))
1248 (setq a (cdr a))
1249 (setq vec (cons (car b) vec)))
1250 (setq b (cdr b))))
1251 (nreverse vec)))
1252 (let ((ca (calcFunc-vcompl a))
1253 (cb (calcFunc-vcompl b)))
1254 (calcFunc-vunion (calcFunc-vcompl (calcFunc-vunion ca b))
bf77c646 1255 (calcFunc-vcompl (calcFunc-vunion a cb))))))
136211a9
EZ
1256
1257(defun calcFunc-vcompl (a)
1258 (setq a (math-prepare-set a))
1259 (let ((vec (list 'vec))
1260 (prev '(neg (var inf var-inf)))
1261 (closed 2))
1262 (while (setq a (cdr a))
1263 (or (and (equal (nth 2 (car a)) '(neg (var inf var-inf)))
1264 (memq (nth 1 (car a)) '(2 3)))
1265 (setq vec (cons (list 'intv
1266 (+ closed
1267 (if (memq (nth 1 (car a)) '(0 1)) 1 0))
1268 prev
1269 (nth 2 (car a)))
1270 vec)))
1271 (setq prev (nth 3 (car a))
1272 closed (if (memq (nth 1 (car a)) '(0 2)) 2 0)))
1273 (or (and (equal prev '(var inf var-inf))
1274 (= closed 0))
1275 (setq vec (cons (list 'intv (+ closed 1)
1276 prev '(var inf var-inf))
1277 vec)))
bf77c646 1278 (math-clean-set (nreverse vec))))
136211a9
EZ
1279
1280(defun calcFunc-vspan (a)
1281 (setq a (math-prepare-set a))
1282 (if (cdr a)
1283 (let ((last (nth (1- (length a)) a)))
1284 (math-make-intv (+ (logand (nth 1 (nth 1 a)) 2)
1285 (logand (nth 1 last) 1))
1286 (nth 2 (nth 1 a))
1287 (nth 3 last)))
bf77c646 1288 '(intv 2 0 0)))
136211a9
EZ
1289
1290(defun calcFunc-vfloor (a &optional always-vec)
1291 (setq a (math-prepare-set a))
1292 (let ((vec (list 'vec)) (p a) (prev nil) b mask)
1293 (while (setq p (cdr p))
1294 (setq mask (nth 1 (car p))
1295 a (nth 2 (car p))
1296 b (nth 3 (car p)))
1297 (and (memq mask '(0 1))
1298 (not (math-infinitep a))
1299 (setq mask (logior mask 2))
1300 (math-num-integerp a)
1301 (setq a (math-add a 1)))
1302 (setq a (math-ceiling a))
1303 (and (memq mask '(0 2))
1304 (not (math-infinitep b))
1305 (setq mask (logior mask 1))
1306 (math-num-integerp b)
1307 (setq b (math-sub b 1)))
1308 (setq b (math-floor b))
1309 (if (and prev (Math-equal (math-sub a 1) (nth 3 prev)))
1310 (setcar (nthcdr 3 prev) b)
1311 (or (Math-lessp b a)
1312 (setq vec (cons (setq prev (list 'intv mask a b)) vec)))))
1313 (setq vec (nreverse vec))
bf77c646 1314 (math-clean-set vec always-vec)))
136211a9
EZ
1315
1316(defun calcFunc-vcard (a)
1317 (setq a (calcFunc-vfloor a t))
1318 (or (math-constp a) (math-reject-arg a "*Set must be finite"))
1319 (let ((count 0))
1320 (while (setq a (cdr a))
1321 (if (eq (car-safe (car a)) 'intv)
1322 (setq count (math-add count (math-sub (nth 3 (car a))
1323 (nth 2 (car a))))))
1324 (setq count (math-add count 1)))
bf77c646 1325 count))
136211a9
EZ
1326
1327(defun calcFunc-venum (a)
1328 (setq a (calcFunc-vfloor a t))
1329 (or (math-constp a) (math-reject-arg a "*Set must be finite"))
11041c99
JB
1330 (let* ((prev a) (this (cdr prev)) this-val next this-last)
1331 (while this
1332 (setq next (cdr this)
1333 this-val (car this))
1334 (if (eq (car-safe this-val) 'intv)
1335 (progn
1336 (setq this (cdr (calcFunc-index (math-add
1337 (math-sub (nth 3 this-val)
1338 (nth 2 this-val))
1339 1)
1340 (nth 2 this-val))))
1341 (setq this-last (last this))
1342 (setcdr this-last next)
1343 (setcdr prev this)
1344 (setq prev this-last))
1345 (setq prev this))
1346 (setq this next)))
1347 a)
136211a9
EZ
1348
1349(defun calcFunc-vpack (a)
1350 (setq a (calcFunc-vfloor a t))
1351 (if (and (cdr a)
1352 (math-negp (if (eq (car-safe (nth 1 a)) 'intv)
1353 (nth 2 (nth 1 a))
1354 (nth 1 a))))
1355 (math-reject-arg (nth 1 a) 'posp))
1356 (let ((accum 0))
1357 (while (setq a (cdr a))
1358 (if (eq (car-safe (car a)) 'intv)
1359 (if (equal (nth 3 (car a)) '(var inf var-inf))
1360 (setq accum (math-sub accum
1361 (math-power-of-2 (nth 2 (car a)))))
1362 (setq accum (math-add accum
1363 (math-sub
1364 (math-power-of-2 (1+ (nth 3 (car a))))
1365 (math-power-of-2 (nth 2 (car a)))))))
1366 (setq accum (math-add accum (math-power-of-2 (car a))))))
bf77c646 1367 accum))
136211a9
EZ
1368
1369(defun calcFunc-vunpack (a &optional w)
1370 (or (math-num-integerp a) (math-reject-arg a 'integerp))
1371 (if w (setq a (math-clip a w)))
1372 (if (math-messy-integerp a) (setq a (math-trunc a)))
1373 (let* ((calc-number-radix 2)
e6e9cfbd 1374 (calc-twos-complement-mode nil)
136211a9
EZ
1375 (neg (math-negp a))
1376 (aa (if neg (math-sub -1 a) a))
1377 (str (if (eq aa 0)
1378 ""
1379 (if (consp aa)
1380 (math-format-bignum-binary (cdr aa))
1381 (math-format-binary aa))))
1382 (zero (if neg ?1 ?0))
1383 (one (if neg ?0 ?1))
1384 (len (length str))
1385 (vec (list 'vec))
1386 (pos (1- len)) pos2)
1387 (while (>= pos 0)
1388 (if (eq (aref str pos) zero)
1389 (setq pos (1- pos))
1390 (setq pos2 pos)
1391 (while (and (>= pos 0) (eq (aref str pos) one))
1392 (setq pos (1- pos)))
1393 (setq vec (cons (if (= pos (1- pos2))
1394 (- len pos2 1)
1395 (list 'intv 3 (- len pos2 1) (- len pos 2)))
1396 vec))))
1397 (if neg
1398 (setq vec (cons (list 'intv 2 len '(var inf var-inf)) vec)))
bf77c646 1399 (math-clean-set (nreverse vec))))
136211a9
EZ
1400
1401(defun calcFunc-rdup (a)
1402 (if (math-simple-set a)
1403 (progn
1404 (and (Math-objectp a) (setq a (list 'vec a)))
1405 (or (math-vectorp a) (math-reject-arg a 'vectorp))
1406 (setq a (sort (copy-sequence (cdr a)) 'math-beforep))
1407 (let ((p a))
1408 (while (cdr p)
1409 (if (Math-equal (car p) (nth 1 p))
1410 (setcdr p (cdr (cdr p)))
1411 (setq p (cdr p)))))
1412 (cons 'vec a))
bf77c646 1413 (math-clean-set (math-prepare-set a))))
136211a9
EZ
1414
1415(defun math-prepare-set (a)
1416 (if (Math-objectp a)
1417 (setq a (list 'vec a))
1418 (or (math-vectorp a) (math-reject-arg a 'vectorp))
1419 (setq a (cons 'vec (sort (copy-sequence (cdr a)) 'math-beforep))))
1420 (let ((p a) res)
1421
1422 ;; Convert all elements to non-empty intervals.
1423 (while (cdr p)
1424 (if (eq (car-safe (nth 1 p)) 'intv)
1425 (if (math-intv-constp (nth 1 p))
1426 (if (and (memq (nth 1 (nth 1 p)) '(0 1 2))
1427 (Math-equal (nth 2 (nth 1 p)) (nth 3 (nth 1 p))))
1428 (setcdr p (cdr (cdr p)))
1429 (setq p (cdr p)))
1430 (math-reject-arg (nth 1 p) 'constp))
1431 (or (Math-anglep (nth 1 p))
1432 (eq (car (nth 1 p)) 'date)
1433 (equal (nth 1 p) '(var inf var-inf))
1434 (equal (nth 1 p) '(neg (var inf var-inf)))
1435 (math-reject-arg (nth 1 p) 'realp))
1436 (setcar (cdr p) (list 'intv 3 (nth 1 p) (nth 1 p)))
1437 (setq p (cdr p))))
1438
1439 ;; Combine redundant intervals.
1440 (setq p a)
1441 (while (cdr (cdr p))
1442 (if (or (memq (setq res (math-compare (nth 3 (nth 1 p))
1443 (nth 2 (nth 2 p))))
1444 '(-1 2))
1445 (and (eq res 0)
1446 (memq (nth 1 (nth 1 p)) '(0 2))
1447 (memq (nth 1 (nth 2 p)) '(0 1))))
1448 (setq p (cdr p))
1449 (setq res (math-compare (nth 3 (nth 1 p)) (nth 3 (nth 2 p))))
1450 (setcdr p (cons (list 'intv
1451 (+ (logand (logior (nth 1 (nth 1 p))
1452 (if (Math-equal
1453 (nth 2 (nth 1 p))
1454 (nth 2 (nth 2 p)))
1455 (nth 1 (nth 2 p))
1456 0))
1457 2)
1458 (logand (logior (if (memq res '(1 0 2))
1459 (nth 1 (nth 1 p)) 0)
1460 (if (memq res '(-1 0 2))
1461 (nth 1 (nth 2 p)) 0))
1462 1))
1463 (nth 2 (nth 1 p))
1464 (if (eq res 1)
1465 (nth 3 (nth 1 p))
1466 (nth 3 (nth 2 p))))
1467 (cdr (cdr (cdr p))))))))
bf77c646 1468 a)
136211a9
EZ
1469
1470(defun math-clean-set (a &optional always-vec)
1471 (let ((p a) res)
1472 (while (cdr p)
1473 (if (and (eq (car-safe (nth 1 p)) 'intv)
1474 (Math-equal (nth 2 (nth 1 p)) (nth 3 (nth 1 p))))
1475 (setcar (cdr p) (nth 2 (nth 1 p))))
1476 (setq p (cdr p)))
1477 (if (and (not (cdr (cdr a)))
1478 (eq (car-safe (nth 1 a)) 'intv)
1479 (not always-vec))
1480 (nth 1 a)
bf77c646 1481 a)))
136211a9
EZ
1482
1483(defun math-simple-set (a)
1484 (or (and (Math-objectp a)
1485 (not (eq (car-safe a) 'intv)))
1486 (and (Math-vectorp a)
1487 (progn
1488 (while (and (setq a (cdr a))
1489 (not (eq (car-safe (car a)) 'intv))))
bf77c646 1490 (null a)))))
136211a9
EZ
1491
1492
1493
1494
1495;;; Compute a right-handed vector cross product. [O O O] [Public]
1496(defun calcFunc-cross (a b)
1497 (if (and (eq (car-safe a) 'vec)
1498 (= (length a) 4))
1499 (if (and (eq (car-safe b) 'vec)
1500 (= (length b) 4))
1501 (list 'vec
1502 (math-sub (math-mul (nth 2 a) (nth 3 b))
1503 (math-mul (nth 3 a) (nth 2 b)))
1504 (math-sub (math-mul (nth 3 a) (nth 1 b))
1505 (math-mul (nth 1 a) (nth 3 b)))
1506 (math-sub (math-mul (nth 1 a) (nth 2 b))
1507 (math-mul (nth 2 a) (nth 1 b))))
1508 (math-reject-arg b "*Three-vector expected"))
bf77c646 1509 (math-reject-arg a "*Three-vector expected")))
136211a9
EZ
1510
1511
1aa484e3
JB
1512;;; Compute a Kronecker product
1513(defun calcFunc-kron (x y &optional nocheck)
1514 "The Kronecker product of objects X and Y.
1515The objects X and Y may be scalars, vectors or matrices.
1516The type of the result depends on the types of the operands;
1517the product of two scalars is a scalar,
1518of one scalar and a vector is a vector,
1519of two vectors is a vector.
1520of one vector and a matrix is a matrix,
1521of two matrices is a matrix."
1522 (unless nocheck
1523 (cond ((or (math-matrixp x)
1524 (math-matrixp y))
1525 (unless (math-matrixp x)
1526 (setq x (if (math-vectorp x)
1527 (list 'vec x)
1528 (list 'vec (list 'vec x)))))
1529 (unless (math-matrixp y)
1530 (setq y (if (math-vectorp y)
1531 (list 'vec y)
1532 (list 'vec (list 'vec y))))))
1533 ((or (math-vectorp x)
1534 (math-vectorp y))
1535 (unless (math-vectorp x)
1536 (setq x (list 'vec x)))
1537 (unless (math-vectorp y)
1538 (setq y (list 'vec y))))))
1539 (if (math-vectorp x)
1540 (let (ret)
1541 (dolist (v (cdr x))
1542 (dolist (w (cdr y))
1543 (setq ret (cons (calcFunc-kron v w t) ret))))
1544 (cons 'vec (nreverse ret)))
1545 (math-mul x y)))
1546
136211a9 1547
866ebaa9
JB
1548;; The variable math-rb-close is local to math-read-brackets, but
1549;; is used by math-read-vector, which is called (directly and
1550;; indirectly) by math-read-brackets.
1551(defvar math-rb-close)
136211a9 1552
388df0be
JB
1553;; The next few variables are local to math-read-exprs in calc-aent.el
1554;; and math-read-expr in calc-ext.el, but are set in functions they call.
1555(defvar math-exp-pos)
1556(defvar math-exp-str)
1557(defvar math-exp-old-pos)
1558(defvar math-exp-token)
1559(defvar math-exp-keep-spaces)
1560(defvar math-expr-data)
1561
866ebaa9 1562(defun math-read-brackets (space-sep math-rb-close)
136211a9
EZ
1563 (and space-sep (setq space-sep (not (math-check-for-commas))))
1564 (math-read-token)
411b1407 1565 (while (eq math-exp-token 'space)
136211a9 1566 (math-read-token))
866ebaa9 1567 (if (or (equal math-expr-data math-rb-close)
411b1407 1568 (eq math-exp-token 'end))
136211a9
EZ
1569 (progn
1570 (math-read-token)
1571 '(vec))
411b1407
JB
1572 (let ((save-exp-pos math-exp-pos)
1573 (save-exp-old-pos math-exp-old-pos)
1574 (save-exp-token math-exp-token)
5c8a5f96 1575 (save-exp-data math-expr-data)
411b1407 1576 (vals (let ((math-exp-keep-spaces space-sep))
5c8a5f96
JB
1577 (if (or (equal math-expr-data "\\dots")
1578 (equal math-expr-data "\\ldots"))
136211a9
EZ
1579 '(vec (neg (var inf var-inf)))
1580 (catch 'syntax (math-read-vector))))))
1581 (if (stringp vals)
1582 (if space-sep
411b1407
JB
1583 (let ((error-exp-pos math-exp-pos)
1584 (error-exp-old-pos math-exp-old-pos)
136211a9 1585 vals2)
411b1407
JB
1586 (setq math-exp-pos save-exp-pos
1587 math-exp-old-pos save-exp-old-pos
1588 math-exp-token save-exp-token
5c8a5f96 1589 math-expr-data save-exp-data)
411b1407 1590 (let ((math-exp-keep-spaces nil))
136211a9
EZ
1591 (setq vals2 (catch 'syntax (math-read-vector))))
1592 (if (and (not (stringp vals2))
5c8a5f96 1593 (or (assoc math-expr-data '(("\\ldots") ("\\dots") (";")))
866ebaa9 1594 (equal math-expr-data math-rb-close)
411b1407 1595 (eq math-exp-token 'end)))
136211a9
EZ
1596 (setq space-sep nil
1597 vals vals2)
411b1407
JB
1598 (setq math-exp-pos error-exp-pos
1599 math-exp-old-pos error-exp-old-pos)
136211a9
EZ
1600 (throw 'syntax vals)))
1601 (throw 'syntax vals)))
5c8a5f96
JB
1602 (if (or (equal math-expr-data "\\dots")
1603 (equal math-expr-data "\\ldots"))
136211a9
EZ
1604 (progn
1605 (math-read-token)
1606 (setq vals (if (> (length vals) 2)
1607 (cons 'calcFunc-mul (cdr vals)) (nth 1 vals)))
866ebaa9 1608 (let ((exp2 (if (or (equal math-expr-data math-rb-close)
5c8a5f96 1609 (equal math-expr-data ")")
411b1407 1610 (eq math-exp-token 'end))
136211a9
EZ
1611 '(var inf var-inf)
1612 (math-read-expr-level 0))))
1613 (setq vals
1614 (list 'intv
5c8a5f96 1615 (if (equal math-expr-data ")") 2 3)
136211a9
EZ
1616 vals
1617 exp2)))
866ebaa9 1618 (if (not (or (equal math-expr-data math-rb-close)
5c8a5f96 1619 (equal math-expr-data ")")
411b1407 1620 (eq math-exp-token 'end)))
136211a9 1621 (throw 'syntax "Expected `]'")))
5c8a5f96 1622 (if (equal math-expr-data ";")
411b1407 1623 (let ((math-exp-keep-spaces space-sep))
136211a9 1624 (setq vals (cons 'vec (math-read-matrix (list vals))))))
866ebaa9 1625 (if (not (or (equal math-expr-data math-rb-close)
411b1407 1626 (eq math-exp-token 'end)))
136211a9 1627 (throw 'syntax "Expected `]'")))
411b1407 1628 (or (eq math-exp-token 'end)
136211a9 1629 (math-read-token))
bf77c646 1630 vals)))
136211a9
EZ
1631
1632(defun math-check-for-commas (&optional balancing)
1633 (let ((count 0)
411b1407 1634 (pos (1- math-exp-pos)))
136211a9
EZ
1635 (while (and (>= count 0)
1636 (setq pos (string-match
1637 (if balancing "[],[{}()<>]" "[],[{}()]")
411b1407
JB
1638 math-exp-str (1+ pos)))
1639 (or (/= (aref math-exp-str pos) ?,) (> count 0) balancing))
1640 (cond ((memq (aref math-exp-str pos) '(?\[ ?\{ ?\( ?\<))
136211a9 1641 (setq count (1+ count)))
411b1407 1642 ((memq (aref math-exp-str pos) '(?\] ?\} ?\) ?\>))
136211a9
EZ
1643 (setq count (1- count)))))
1644 (if balancing
1645 pos
411b1407 1646 (and pos (= (aref math-exp-str pos) ?,)))))
136211a9
EZ
1647
1648(defun math-read-vector ()
1649 (let* ((val (list (math-read-expr-level 0)))
1650 (last val))
1651 (while (progn
411b1407 1652 (while (eq math-exp-token 'space)
136211a9 1653 (math-read-token))
411b1407 1654 (and (not (eq math-exp-token 'end))
5c8a5f96 1655 (not (equal math-expr-data ";"))
866ebaa9 1656 (not (equal math-expr-data math-rb-close))
5c8a5f96
JB
1657 (not (equal math-expr-data "\\dots"))
1658 (not (equal math-expr-data "\\ldots"))))
1659 (if (equal math-expr-data ",")
136211a9 1660 (math-read-token))
411b1407 1661 (while (eq math-exp-token 'space)
136211a9
EZ
1662 (math-read-token))
1663 (let ((rest (list (math-read-expr-level 0))))
1664 (setcdr last rest)
1665 (setq last rest)))
bf77c646 1666 (cons 'vec val)))
136211a9
EZ
1667
1668(defun math-read-matrix (mat)
5c8a5f96 1669 (while (equal math-expr-data ";")
136211a9 1670 (math-read-token)
411b1407 1671 (while (eq math-exp-token 'space)
136211a9
EZ
1672 (math-read-token))
1673 (setq mat (nconc mat (list (math-read-vector)))))
bf77c646 1674 mat)
136211a9 1675
429dae43
JB
1676(provide 'calc-vec)
1677
cbee283d 1678;; arch-tag: 7902a7af-ec69-440a-8635-ebb4db263402
bf77c646 1679;;; calc-vec.el ends here