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