Add emacs-xtra.
[emacs.git] / lisp / calc / calc-stat.el
blob42d58776a477a073e805674db93e422f1ff38c36
1 ;;; calc-stat.el --- statistical functions for Calc
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainers: D. Goel <deego@gnufans.org>
7 ;; Colin Walters <walters@debian.org>
9 ;; This file is part of GNU Emacs.
11 ;; GNU Emacs is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY. No author or distributor
13 ;; accepts responsibility to anyone for the consequences of using it
14 ;; or for whether it serves any particular purpose or works at all,
15 ;; unless he says so in writing. Refer to the GNU Emacs General Public
16 ;; License for full details.
18 ;; Everyone is granted permission to copy, modify and redistribute
19 ;; GNU Emacs, but only under the conditions described in the
20 ;; GNU Emacs General Public License. A copy of this license is
21 ;; supposed to have been given to you along with GNU Emacs so you
22 ;; can know your rights and responsibilities. It should be in a
23 ;; file named COPYING. Among other things, the copyright notice
24 ;; and this notice must be preserved on all copies.
26 ;;; Commentary:
28 ;;; Code:
30 ;; This file is autoloaded from calc-ext.el.
31 (require 'calc-ext)
33 (require 'calc-macs)
35 (defun calc-Need-calc-stat () nil)
38 ;;; Statistical operations on vectors.
40 (defun calc-vector-count (arg)
41 (interactive "P")
42 (calc-slow-wrapper
43 (calc-vector-op "coun" 'calcFunc-vcount arg)))
45 (defun calc-vector-sum (arg)
46 (interactive "P")
47 (calc-slow-wrapper
48 (if (calc-is-hyperbolic)
49 (calc-vector-op "vprd" 'calcFunc-vprod arg)
50 (calc-vector-op "vsum" 'calcFunc-vsum arg))))
52 (defun calc-vector-product (arg)
53 (interactive "P")
54 (calc-hyperbolic-func)
55 (calc-vector-sum arg))
57 (defun calc-vector-max (arg)
58 (interactive "P")
59 (calc-slow-wrapper
60 (if (calc-is-inverse)
61 (calc-vector-op "vmin" 'calcFunc-vmin arg)
62 (calc-vector-op "vmax" 'calcFunc-vmax arg))))
64 (defun calc-vector-min (arg)
65 (interactive "P")
66 (calc-invert-func)
67 (calc-vector-max arg))
69 (defun calc-vector-mean (arg)
70 (interactive "P")
71 (calc-slow-wrapper
72 (if (calc-is-hyperbolic)
73 (if (calc-is-inverse)
74 (calc-vector-op "harm" 'calcFunc-vhmean arg)
75 (calc-vector-op "medn" 'calcFunc-vmedian arg))
76 (if (calc-is-inverse)
77 (calc-vector-op "meae" 'calcFunc-vmeane arg)
78 (calc-vector-op "mean" 'calcFunc-vmean arg)))))
80 (defun calc-vector-mean-error (arg)
81 (interactive "P")
82 (calc-invert-func)
83 (calc-vector-mean arg))
85 (defun calc-vector-median (arg)
86 (interactive "P")
87 (calc-hyperbolic-func)
88 (calc-vector-mean arg))
90 (defun calc-vector-harmonic-mean (arg)
91 (interactive "P")
92 (calc-invert-func)
93 (calc-hyperbolic-func)
94 (calc-vector-mean arg))
96 (defun calc-vector-geometric-mean (arg)
97 (interactive "P")
98 (calc-slow-wrapper
99 (if (calc-is-hyperbolic)
100 (calc-binary-op "geom" 'calcFunc-agmean arg)
101 (calc-vector-op "geom" 'calcFunc-vgmean arg))))
103 (defun calc-vector-sdev (arg)
104 (interactive "P")
105 (calc-slow-wrapper
106 (if (calc-is-hyperbolic)
107 (if (calc-is-inverse)
108 (calc-vector-op "pvar" 'calcFunc-vpvar arg)
109 (calc-vector-op "var" 'calcFunc-vvar arg))
110 (if (calc-is-inverse)
111 (calc-vector-op "psdv" 'calcFunc-vpsdev arg)
112 (calc-vector-op "sdev" 'calcFunc-vsdev arg)))))
114 (defun calc-vector-pop-sdev (arg)
115 (interactive "P")
116 (calc-invert-func)
117 (calc-vector-sdev arg))
119 (defun calc-vector-variance (arg)
120 (interactive "P")
121 (calc-hyperbolic-func)
122 (calc-vector-sdev arg))
124 (defun calc-vector-pop-variance (arg)
125 (interactive "P")
126 (calc-invert-func)
127 (calc-hyperbolic-func)
128 (calc-vector-sdev arg))
130 (defun calc-vector-covariance (arg)
131 (interactive "P")
132 (calc-slow-wrapper
133 (let ((n (if (eq arg 1) 1 2)))
134 (if (calc-is-hyperbolic)
135 (calc-enter-result n "corr" (cons 'calcFunc-vcorr
136 (calc-top-list-n n)))
137 (if (calc-is-inverse)
138 (calc-enter-result n "pcov" (cons 'calcFunc-vpcov
139 (calc-top-list-n n)))
140 (calc-enter-result n "cov" (cons 'calcFunc-vcov
141 (calc-top-list-n n))))))))
143 (defun calc-vector-pop-covariance (arg)
144 (interactive "P")
145 (calc-invert-func)
146 (calc-vector-covariance arg))
148 (defun calc-vector-correlation (arg)
149 (interactive "P")
150 (calc-hyperbolic-func)
151 (calc-vector-covariance arg))
153 (defun calc-vector-op (name func arg)
154 (setq calc-aborted-prefix name
155 arg (prefix-numeric-value arg))
156 (if (< arg 0)
157 (error "Negative arguments not allowed"))
158 (calc-enter-result arg name (cons func (calc-top-list-n arg))))
163 ;;; Useful statistical functions
165 ;;; Sum, product, etc., of one or more values or vectors.
166 ;;; Each argument must be either a number or a vector. Vectors
167 ;;; are flattened, but variables inside are assumed to represent
168 ;;; non-vectors.
170 (defun calcFunc-vsum (&rest vecs)
171 (math-reduce-many-vecs 'calcFunc-add 'calcFunc-vsum vecs 0))
173 (defun calcFunc-vprod (&rest vecs)
174 (math-reduce-many-vecs 'calcFunc-mul 'calcFunc-vprod vecs 1))
176 (defun calcFunc-vmax (&rest vecs)
177 (if (eq (car-safe (car vecs)) 'sdev)
178 '(var inf var-inf)
179 (if (eq (car-safe (car vecs)) 'intv)
180 (nth 3 (math-fix-int-intv (car vecs)))
181 (math-reduce-many-vecs 'calcFunc-max 'calcFunc-vmax vecs
182 '(neg (var inf var-inf))))))
184 (defun calcFunc-vmin (&rest vecs)
185 (if (eq (car-safe (car vecs)) 'sdev)
186 '(neg (var inf var-inf))
187 (if (eq (car-safe (car vecs)) 'intv)
188 (nth 2 (math-fix-int-intv (car vecs)))
189 (math-reduce-many-vecs 'calcFunc-min 'calcFunc-vmin vecs
190 '(var inf var-inf)))))
192 (defun math-reduce-many-vecs (func whole-func vecs ident)
193 (let ((const-part nil)
194 (symb-part nil)
195 val vec)
196 (let ((calc-internal-prec (+ calc-internal-prec 2)))
197 (while vecs
198 (setq val (car vecs))
199 (and (eq (car-safe val) 'var)
200 (eq (car-safe (calc-var-value (nth 2 val))) 'vec)
201 (setq val (symbol-value (nth 2 val))))
202 (cond ((Math-vectorp val)
203 (setq vec (append (and const-part (list const-part))
204 (math-flatten-vector val)))
205 (setq const-part (if vec
206 (calcFunc-reducer
207 (math-calcFunc-to-var func)
208 (cons 'vec vec))
209 ident)))
210 ((or (Math-objectp val) (math-infinitep val))
211 (setq const-part (if const-part
212 (funcall func const-part val)
213 val)))
215 (setq symb-part (nconc symb-part (list val)))))
216 (setq vecs (cdr vecs))))
217 (if const-part
218 (progn
219 (setq const-part (math-normalize const-part))
220 (if symb-part
221 (funcall func const-part (cons whole-func symb-part))
222 const-part))
223 (if symb-part (cons whole-func symb-part) ident))))
226 ;;; Return the number of data elements among the arguments.
227 (defun calcFunc-vcount (&rest vecs)
228 (let ((count 0))
229 (while vecs
230 (setq count (if (Math-vectorp (car vecs))
231 (+ count (math-count-elements (car vecs)))
232 (if (Math-objectp (car vecs))
233 (1+ count)
234 (if (and (eq (car-safe (car vecs)) 'var)
235 (eq (car-safe (calc-var-value
236 (nth 2 (car vecs))))
237 'vec))
238 (+ count (math-count-elements
239 (symbol-value (nth 2 (car vecs)))))
240 (math-reject-arg (car vecs) 'numvecp))))
241 vecs (cdr vecs)))
242 count))
244 (defun math-count-elements (vec)
245 (let ((count 0))
246 (while (setq vec (cdr vec))
247 (setq count (if (Math-vectorp (car vec))
248 (+ count (math-count-elements (car vec)))
249 (1+ count))))
250 count))
253 (defun math-flatten-many-vecs (vecs)
254 (let ((p vecs)
255 (vec (list 'vec)))
256 (while p
257 (setq vec (nconc vec
258 (if (Math-vectorp (car p))
259 (math-flatten-vector (car p))
260 (if (Math-objectp (car p))
261 (list (car p))
262 (if (and (eq (car-safe (car p)) 'var)
263 (eq (car-safe (calc-var-value
264 (nth 2 (car p)))) 'vec))
265 (math-flatten-vector (symbol-value
266 (nth 2 (car p))))
267 (math-reject-arg (car p) 'numvecp)))))
268 p (cdr p)))
269 vec))
271 (defun calcFunc-vflat (&rest vecs)
272 (math-flatten-many-vecs vecs))
274 (defun math-split-sdev-vec (vec zero-ok)
275 (let ((means (list 'vec))
276 (wts (list 'vec))
277 (exact nil)
278 (p vec))
279 (while (and (setq p (cdr p))
280 (not (and (consp (car p))
281 (eq (car (car p)) 'sdev)))))
282 (if (null p)
283 (list vec nil)
284 (while (setq vec (cdr vec))
285 (if (and (consp (setq p (car vec)))
286 (eq (car p) 'sdev))
287 (or exact
288 (setq means (cons (nth 1 p) means)
289 wts (cons (nth 2 p) wts)))
290 (if zero-ok
291 (setq means (cons (nth 1 p) means)
292 wts (cons 0 wts))
293 (or exact
294 (setq means (list 'vec)
295 wts nil
296 exact t))
297 (setq means (cons p means)))))
298 (list (nreverse means)
299 (and wts (nreverse wts))))))
302 ;;; Return the arithmetic mean of the argument numbers or vectors.
303 ;;; (If numbers are error forms, computes the weighted mean.)
304 (defun calcFunc-vmean (&rest vecs)
305 (let* ((split (math-split-sdev-vec (math-flatten-many-vecs vecs) nil))
306 (means (car split))
307 (wts (nth 1 split))
308 (len (1- (length means))))
309 (if (= len 0)
310 (math-reject-arg nil "*Must be at least 1 argument")
311 (if (and (= len 1) (eq (car-safe (nth 1 means)) 'intv))
312 (let ((x (math-fix-int-intv (nth 1 means))))
313 (calcFunc-vmean (nth 2 x) (nth 3 x)))
314 (math-with-extra-prec 2
315 (if (and wts (> len 1))
316 (let* ((sqrwts (calcFunc-map '(var mul var-mul) wts wts))
317 (suminvsqrwts (calcFunc-reduce
318 '(var add var-add)
319 (calcFunc-map '(var div var-div)
320 1 sqrwts))))
321 (math-div (calcFunc-reduce '(var add var-add)
322 (calcFunc-map '(var div var-div)
323 means sqrwts))
324 suminvsqrwts))
325 (math-div (calcFunc-reduce '(var add var-add) means) len)))))))
327 (defun math-fix-int-intv (x)
328 (if (math-floatp x)
330 (list 'intv 3
331 (if (memq (nth 1 x) '(2 3)) (nth 2 x) (math-add (nth 2 x) 1))
332 (if (memq (nth 1 x) '(1 3)) (nth 3 x) (math-sub (nth 3 x) 1)))))
334 ;;; Compute the mean with an error estimate.
335 (defun calcFunc-vmeane (&rest vecs)
336 (let* ((split (math-split-sdev-vec (math-flatten-many-vecs vecs) nil))
337 (means (car split))
338 (wts (nth 1 split))
339 (len (1- (length means))))
340 (if (= len 0)
341 (math-reject-arg nil "*Must be at least 1 argument")
342 (math-with-extra-prec 2
343 (if wts
344 (let* ((sqrwts (calcFunc-map '(var mul var-mul) wts wts))
345 (suminvsqrwts (calcFunc-reduce
346 '(var add var-add)
347 (calcFunc-map '(var div var-div)
348 1 sqrwts))))
349 (math-make-sdev
350 (math-div (calcFunc-reduce '(var add var-add)
351 (calcFunc-map '(var div var-div)
352 means sqrwts))
353 suminvsqrwts)
354 (list 'calcFunc-sqrt (math-div 1 suminvsqrwts))))
355 (let ((mean (math-div (calcFunc-reduce '(var add var-add) means)
356 len)))
357 (math-make-sdev
358 mean
359 (list 'calcFunc-sqrt
360 (math-div (calcFunc-reducer
361 '(var add var-add)
362 (calcFunc-map '(var pow var-pow)
363 (calcFunc-map '(var abs var-abs)
364 (calcFunc-map
365 '(var add var-add)
366 means
367 (math-neg mean)))
369 (math-mul len (1- len)))))))))))
372 ;;; Compute the median of a list of values.
373 (defun calcFunc-vmedian (&rest vecs)
374 (let* ((flat (copy-sequence (cdr (math-flatten-many-vecs vecs))))
375 (p flat)
376 (len (length flat))
377 (hlen (/ len 2)))
378 (if (= len 0)
379 (math-reject-arg nil "*Must be at least 1 argument")
380 (if (and (= len 1) (memq (car-safe (car flat)) '(sdev intv)))
381 (calcFunc-vmean (car flat))
382 (while p
383 (if (eq (car-safe (car p)) 'sdev)
384 (setcar p (nth 1 (car p))))
385 (or (Math-anglep (car p))
386 (math-reject-arg (car p) 'anglep))
387 (setq p (cdr p)))
388 (setq flat (sort flat 'math-lessp))
389 (if (= (% len 2) 0)
390 (math-div (math-add (nth (1- hlen) flat) (nth hlen flat)) 2)
391 (nth hlen flat))))))
394 (defun calcFunc-vgmean (&rest vecs)
395 (let* ((flat (math-flatten-many-vecs vecs))
396 (len (1- (length flat))))
397 (if (= len 0)
398 (math-reject-arg nil "*Must be at least 1 argument")
399 (math-with-extra-prec 2
400 (let ((x (calcFunc-reduce '(var mul math-mul) flat)))
401 (if (= len 2)
402 (math-sqrt x)
403 (math-pow x (list 'frac 1 len))))))))
406 (defun calcFunc-agmean (a b)
407 (cond ((Math-equal a b) a)
408 ((math-zerop a) a)
409 ((math-zerop b) b)
410 (calc-symbolic-mode (math-inexact-result))
411 ((not (Math-realp a)) (math-reject-arg a 'realp))
412 ((not (Math-realp b)) (math-reject-arg b 'realp))
414 (math-with-extra-prec 2
415 (setq a (math-float (math-abs a))
416 b (math-float (math-abs b)))
417 (let (mean)
418 (while (not (math-nearly-equal-float a b))
419 (setq mean (math-mul-float (math-add-float a b) '(float 5 -1))
420 b (math-sqrt-float (math-mul-float a b))
421 a mean))
422 a)))))
425 (defun calcFunc-vhmean (&rest vecs)
426 (let* ((flat (math-flatten-many-vecs vecs))
427 (len (1- (length flat))))
428 (if (= len 0)
429 (math-reject-arg nil "*Must be at least 1 argument")
430 (math-with-extra-prec 2
431 (math-div len
432 (calcFunc-reduce '(var add math-add)
433 (calcFunc-map '(var inv var-inv) flat)))))))
437 ;;; Compute the sample variance or standard deviation of numbers or vectors.
438 ;;; (If the numbers are error forms, only the mean part of them is used.)
439 (defun calcFunc-vvar (&rest vecs)
440 (if (and (= (length vecs) 1)
441 (memq (car-safe (car vecs)) '(sdev intv)))
442 (if (eq (car-safe (car vecs)) 'intv)
443 (math-intv-variance (car vecs) nil)
444 (math-sqr (nth 2 (car vecs))))
445 (math-covariance vecs nil nil 0)))
447 (defun calcFunc-vsdev (&rest vecs)
448 (if (and (= (length vecs) 1)
449 (memq (car-safe (car vecs)) '(sdev intv)))
450 (if (eq (car-safe (car vecs)) 'intv)
451 (if (math-floatp (car vecs))
452 (math-div (math-sub (nth 3 (car vecs)) (nth 2 (car vecs)))
453 (math-sqrt-12))
454 (math-sqrt (calcFunc-vvar (car vecs))))
455 (nth 2 (car vecs)))
456 (math-sqrt (math-covariance vecs nil nil 0))))
458 ;;; Compute the population variance or std deviation of numbers or vectors.
459 (defun calcFunc-vpvar (&rest vecs)
460 (if (and (= (length vecs) 1)
461 (memq (car-safe (car vecs)) '(sdev intv)))
462 (if (eq (car-safe (car vecs)) 'intv)
463 (math-intv-variance (car vecs) t)
464 (math-sqr (nth 2 (car vecs))))
465 (math-covariance vecs nil t 0)))
467 (defun calcFunc-vpsdev (&rest vecs)
468 (if (and (= (length vecs) 1)
469 (memq (car-safe (car vecs)) '(sdev intv)))
470 (if (eq (car-safe (car vecs)) 'intv)
471 (if (math-floatp (car vecs))
472 (math-div (math-sub (nth 3 (car vecs)) (nth 2 (car vecs)))
473 (math-sqrt-12))
474 (math-sqrt (calcFunc-vpvar (car vecs))))
475 (nth 2 (car vecs)))
476 (math-sqrt (math-covariance vecs nil t 0))))
478 (defun math-intv-variance (x pop)
479 (or (math-constp x) (math-reject-arg x 'constp))
480 (if (math-floatp x)
481 (math-div (math-sqr (math-sub (nth 3 x) (nth 2 x))) 12)
482 (let* ((x (math-fix-int-intv x))
483 (len (math-sub (nth 3 x) (nth 2 x)))
484 (hlen (math-quotient len 2)))
485 (math-div (if (math-evenp len)
486 (calcFunc-sum '(^ (var X var-X) 2) '(var X var-X)
487 (math-neg hlen) hlen)
488 (calcFunc-sum '(^ (- (var X var-X) (/ 1 2)) 2)
489 '(var X var-X)
490 (math-neg hlen) (math-add hlen 1)))
491 (if pop (math-add len 1) len)))))
493 ;;; Compute the covariance and linear correlation coefficient.
494 (defun calcFunc-vcov (vec1 &optional vec2)
495 (math-covariance (list vec1) (list vec2) nil 1))
497 (defun calcFunc-vpcov (vec1 &optional vec2)
498 (math-covariance (list vec1) (list vec2) t 1))
500 (defun calcFunc-vcorr (vec1 &optional vec2)
501 (math-covariance (list vec1) (list vec2) nil 2))
504 (defun math-covariance (vec1 vec2 pop mode)
505 (or (car vec2) (= mode 0)
506 (progn
507 (if (and (eq (car-safe (car vec1)) 'var)
508 (eq (car-safe (calc-var-value (nth 2 (car vec1)))) 'vec))
509 (setq vec1 (symbol-value (nth 2 (car vec1))))
510 (setq vec1 (car vec1)))
511 (or (math-matrixp vec1) (math-dimension-error))
512 (or (= (length (nth 1 vec1)) 3) (math-dimension-error))
513 (setq vec2 (list (math-mat-col vec1 2))
514 vec1 (list (math-mat-col vec1 1)))))
515 (math-with-extra-prec 2
516 (let* ((split1 (math-split-sdev-vec (math-flatten-many-vecs vec1) nil))
517 (means1 (car split1))
518 (wts1 (nth 1 split1))
519 split2 means2 (wts2 nil)
520 (sqrwts nil)
521 suminvsqrwts
522 (len (1- (length means1))))
523 (if (< len (if pop 1 2))
524 (math-reject-arg nil (if pop
525 "*Must be at least 1 argument"
526 "*Must be at least 2 arguments")))
527 (if (or wts1 wts2)
528 (setq sqrwts (math-add
529 (if wts1
530 (calcFunc-map '(var mul var-mul) wts1 wts1)
532 (if wts2
533 (calcFunc-map '(var mul var-mul) wts2 wts2)
535 suminvsqrwts (calcFunc-reduce
536 '(var add var-add)
537 (calcFunc-map '(var div var-div) 1 sqrwts))))
538 (or (= mode 0)
539 (progn
540 (setq split2 (math-split-sdev-vec (math-flatten-many-vecs vec2)
541 nil)
542 means2 (car split2)
543 wts2 (nth 2 split1))
544 (or (= len (1- (length means2))) (math-dimension-error))))
545 (let* ((diff1 (calcFunc-map
546 '(var add var-add)
547 means1
548 (if sqrwts
549 (math-div (calcFunc-reduce
550 '(var add var-add)
551 (calcFunc-map '(var div var-div)
552 means1 sqrwts))
553 (math-neg suminvsqrwts))
554 (math-div (calcFunc-reducer '(var add var-add) means1)
555 (- len)))))
556 (diff2 (if (= mode 0)
557 diff1
558 (calcFunc-map
559 '(var add var-add)
560 means2
561 (if sqrwts
562 (math-div (calcFunc-reduce
563 '(var add var-add)
564 (calcFunc-map '(var div var-div)
565 means2 sqrwts))
566 (math-neg suminvsqrwts))
567 (math-div (calcFunc-reducer '(var add var-add) means2)
568 (- len))))))
569 (covar (calcFunc-map '(var mul var-mul) diff1 diff2)))
570 (if sqrwts
571 (setq covar (calcFunc-map '(var div var-div) covar sqrwts)))
572 (math-div
573 (calcFunc-reducer '(var add var-add) covar)
574 (if (= mode 2)
575 (let ((var1 (calcFunc-map '(var mul var-mul) diff1 diff1))
576 (var2 (calcFunc-map '(var mul var-mul) diff2 diff2)))
577 (if sqrwts
578 (setq var1 (calcFunc-map '(var div var-div) var1 sqrwts)
579 var2 (calcFunc-map '(var div var-div) var2 sqrwts)))
580 (math-sqrt
581 (math-mul (calcFunc-reducer '(var add var-add) var1)
582 (calcFunc-reducer '(var add var-add) var2))))
583 (if sqrwts
584 (if pop
585 suminvsqrwts
586 (math-div (math-mul suminvsqrwts (1- len)) len))
587 (if pop len (1- len)))))))))
589 ;;; arch-tag: 423858e9-8513-489c-9f35-710cd9d9c307
590 ;;; calc-stat.el ends here