Add arch taglines
[bpt/emacs.git] / lisp / calc / calc-stat.el
1 ;;; calc-stat.el --- statistical functions for Calc
2
3 ;; Copyright (C) 1990, 1991, 1992, 1993, 2001 Free Software Foundation, Inc.
4
5 ;; Author: David Gillespie <daveg@synaptics.com>
6 ;; Maintainers: D. Goel <deego@gnufans.org>
7 ;; Colin Walters <walters@debian.org>
8
9 ;; This file is part of GNU Emacs.
10
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.
17
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.
25
26 ;;; Commentary:
27
28 ;;; Code:
29
30 ;; This file is autoloaded from calc-ext.el.
31 (require 'calc-ext)
32
33 (require 'calc-macs)
34
35 (defun calc-Need-calc-stat () nil)
36
37
38 ;;; Statistical operations on vectors.
39
40 (defun calc-vector-count (arg)
41 (interactive "P")
42 (calc-slow-wrapper
43 (calc-vector-op "coun" 'calcFunc-vcount arg)))
44
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))))
51
52 (defun calc-vector-product (arg)
53 (interactive "P")
54 (calc-hyperbolic-func)
55 (calc-vector-sum arg))
56
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))))
63
64 (defun calc-vector-min (arg)
65 (interactive "P")
66 (calc-invert-func)
67 (calc-vector-max arg))
68
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)))))
79
80 (defun calc-vector-mean-error (arg)
81 (interactive "P")
82 (calc-invert-func)
83 (calc-vector-mean arg))
84
85 (defun calc-vector-median (arg)
86 (interactive "P")
87 (calc-hyperbolic-func)
88 (calc-vector-mean arg))
89
90 (defun calc-vector-harmonic-mean (arg)
91 (interactive "P")
92 (calc-invert-func)
93 (calc-hyperbolic-func)
94 (calc-vector-mean arg))
95
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))))
102
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)))))
113
114 (defun calc-vector-pop-sdev (arg)
115 (interactive "P")
116 (calc-invert-func)
117 (calc-vector-sdev arg))
118
119 (defun calc-vector-variance (arg)
120 (interactive "P")
121 (calc-hyperbolic-func)
122 (calc-vector-sdev arg))
123
124 (defun calc-vector-pop-variance (arg)
125 (interactive "P")
126 (calc-invert-func)
127 (calc-hyperbolic-func)
128 (calc-vector-sdev arg))
129
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))))))))
142
143 (defun calc-vector-pop-covariance (arg)
144 (interactive "P")
145 (calc-invert-func)
146 (calc-vector-covariance arg))
147
148 (defun calc-vector-correlation (arg)
149 (interactive "P")
150 (calc-hyperbolic-func)
151 (calc-vector-covariance arg))
152
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))))
159
160
161
162
163 ;;; Useful statistical functions
164
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.
169
170 (defun calcFunc-vsum (&rest vecs)
171 (math-reduce-many-vecs 'calcFunc-add 'calcFunc-vsum vecs 0))
172
173 (defun calcFunc-vprod (&rest vecs)
174 (math-reduce-many-vecs 'calcFunc-mul 'calcFunc-vprod vecs 1))
175
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))))))
183
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)))))
191
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)))
214 (t
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))))
224
225
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))
243
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))
251
252
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))
270
271 (defun calcFunc-vflat (&rest vecs)
272 (math-flatten-many-vecs vecs))
273
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))))))
300
301
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)))))))
326
327 (defun math-fix-int-intv (x)
328 (if (math-floatp x)
329 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)))))
333
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)))
368 2))
369 (math-mul len (1- len)))))))))))
370
371
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))))))
392
393
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))))))))
404
405
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))
413 (t
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)))))
423
424
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)))))))
434
435
436
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)))
446
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))))
457
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)))
466
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))))
477
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)))))
492
493 ;;; Compute the covariance and linear correlation coefficient.
494 (defun calcFunc-vcov (vec1 &optional vec2)
495 (math-covariance (list vec1) (list vec2) nil 1))
496
497 (defun calcFunc-vpcov (vec1 &optional vec2)
498 (math-covariance (list vec1) (list vec2) t 1))
499
500 (defun calcFunc-vcorr (vec1 &optional vec2)
501 (math-covariance (list vec1) (list vec2) nil 2))
502
503
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)
531 0)
532 (if wts2
533 (calcFunc-map '(var mul var-mul) wts2 wts2)
534 0))
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)))))))))
588
589 ;;; arch-tag: 423858e9-8513-489c-9f35-710cd9d9c307
590 ;;; calc-stat.el ends here