lsbasics has some numerical processing, essential structure for XLS.
[CommonLispStat.git] / src / basics / lsbasics.lsp
blob9d62e7b62de6ac5f0e3e361d34089f9c6b46d7f6
1 ;;; -*- mode: lisp -*-
2 ;;; Copyright (c) 2005--2008, by A.J. Rossini <blindglobe@gmail.com>
3 ;;; See COPYRIGHT file for any additional restrictions (BSD license).
4 ;;; Since 1991, ANSI was finally finished. Edited for ANSI Common Lisp.
6 ;;;; lsbasics -- Low level Lisp-Stat functions
7 ;;;;
8 ;;;; Copyright (c) 1991, by Luke Tierney. Permission is granted for
9 ;;;; unrestricted use.
11 ;;; Package Setup
13 (in-package :cl-user)
15 (defpackage :lisp-stat-basics
16 (:use :common-lisp
17 :lisp-stat-object-system
18 :lisp-stat-types
19 :lisp-stat-float
20 :lisp-stat-macros
21 :lisp-stat-compound-data)
22 (:shadowing-import-from :lisp-stat-object-system
23 slot-value call-method call-next-method)
24 (:export permute-array sum prod count-elements mean
25 if-else sample))
27 (in-package :lisp-stat-basics)
29 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 ;;;;
31 ;;;; Array Permutation Functions
32 ;;;;
33 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 (defun permute-indices (x y perm check)
36 "Args: (x y perm check).
37 permute x into y using perm; all should be vectors; If check is TRUE
38 the routine will check to make sure no indices are reused, but x
39 will be destroyed."
40 (let ((rank (length x)))
41 (declare (fixnum rank))
42 (dotimes (i rank)
43 (declare (fixnum i))
44 (let ((k (aref perm i)))
45 (if (not (fixnump k)) (error "bad permutation sequence - ~a" perm))
46 (if (or (< k 0) (>= k rank))
47 (error "bad permutation sequence - ~a" perm))
48 (setf (aref y i) (aref x k))
49 ;; to insure dimensions are not re-used
50 (if check (setf (aref x k) NIL))))))
52 (defun indices-from-rowmajor (a k result)
53 "Args: (a k result).
54 Compute indices in a from rowmajor index k, put in vector result."
55 (declare (fixnum k))
57 (if (not (arrayp a)) (error "not an array - ~a" a))
58 (if (or (> 0 k) (>= k (array-total-size a))) (error "index out of range"))
60 (let ((face 1)
61 (rank (array-rank a))
62 (dim (array-dimensions a)))
63 (declare (fixnum face rank))
64 (let ((cdim (make-next-element dim)))
65 (dotimes (i rank)
66 (declare (fixnum i))
67 (setf face (* face (get-next-element cdim i)))))
68 (let ((cdim (make-next-element dim)))
69 (dotimes (i rank)
70 (setf face (/ face (get-next-element cdim i)))
71 (setf (aref result i) (floor (/ k face)))
72 (setf k (rem k face))))))
74 (defun translate-index (i result x perm indices oldindices ilist)
75 "Args: (i result x perm indices oldindices ilist).
76 Translate row major index in original array to row major index in new
77 array. Use indices vectors and ilist for temporary storage."
78 (declare (fixnum i))
79 (let ((rank (array-rank x)))
80 (declare (fixnum rank))
81 (indices-from-rowmajor x i oldindices)
82 (permute-indices oldindices indices perm nil)
83 (do ((next ilist (rest next))
84 (k 0 (+ k 1)))
85 ((not (and (< k rank) (consp next))))
86 (setf (first next) (aref indices k)))
87 (apply #'array-row-major-index result ilist)))
89 (defun permute-array (x perm)
90 "Args: (a p)
91 Returns a copy of the array A permuted according to the permutation P."
92 (if (not (arrayp x)) (error "not an array - ~a" x))
93 (check-sequence perm)
94 (if (/= (length perm) (array-rank x))
95 (error "bad permutation sequence - ~a" perm))
96 (let* ((perm (coerce perm 'vector))
97 (rank (array-rank x))
98 (dim (make-array rank))
99 (olddim (coerce (array-dimensions x) 'vector)))
100 (declare (fixnum rank))
101 ;; construct new dimension vector
102 (permute-indices olddim dim perm t)
103 ;; make result array and the index vectors and lists */
104 (let* ((result (make-array (coerce dim 'list)))
105 (indices (make-array rank))
106 (oldindices (make-array rank))
107 (ilist (make-list rank))
108 (data (compound-data-seq x))
109 (result_data (compound-data-seq result))
110 (n (length data)))
111 (declare (fixnum n))
112 (dotimes (i rank)
113 (declare (fixnum i))
114 (setf (aref oldindices i) (list nil)))
115 ;; fill in the result
116 (if (/= n (length result_data)) (error "bad data"))
117 (dotimes (i n result)
118 (declare (fixnum i))
119 (let ((k (translate-index i result x perm indices oldindices ilist)))
120 (declare (fixnum k))
121 (setf (aref result_data k) (aref data i)))))))
123 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
124 ;;;;
125 ;;;; SUM, PROD, COUNT-ELEMENTS, and MEAN Functions
126 ;;;;
127 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 (defun sum-1 (x)
130 (if (numberp x)
132 (let ((seq (compound-data-seq x))
133 (sum 0))
134 (if (consp seq)
135 (dolist (x seq sum)
136 (setf sum (+ sum (if (numberp x) x (sum-1 x)))))
137 (let ((n (length seq)))
138 (declare (fixnum n))
139 (dotimes (i n sum)
140 (declare (fixnum i))
141 (let ((x (aref seq i)))
142 (setf sum (+ sum (if (numberp x) x (sum-1 x)))))))))))
144 (defun sum (&rest args)
145 "Args: (&rest number-data)
146 Returns the sum of all the elements of its arguments. Returns 0 if there
147 are no arguments. Vector reducing."
148 (if args
149 (sum-1 (if (rest args) args (first args)))
154 (defun prod-1 (x)
155 (if (numberp x)
157 (let ((seq (compound-data-seq x))
158 (prod 1))
159 (if (consp seq)
160 (dolist (x seq prod)
161 (setf prod (* prod (if (numberp x) x (prod-1 x)))))
162 (let ((n (length seq)))
163 (declare (fixnum n))
164 (dotimes (i n prod)
165 (declare (fixnum i))
166 (let ((x (aref seq i)))
167 (setf prod (* prod (if (numberp x) x (prod-1 x)))))))))))
169 (defun prod (&rest args)
170 "Args: (&rest number-data)
171 Returns the product of all the elements of its arguments. Returns 1 if there
172 are no arguments. Vector reducing."
173 (if args
174 (prod-1 (if (rest args) args (first args)))
177 (defun count-elements (x)
178 "Args: (number &rest more-numbers)
179 Returns the number of its arguments. Vector reducing"
180 (if (compound-data-p x)
181 (let ((seq (compound-data-seq x))
182 (count 0))
183 (if (consp seq)
184 (dolist (x seq count)
185 (incf count (if (compound-data-p x) (count-elements x) 1)))
186 (let ((n (length seq)))
187 (declare (fixnum n))
188 (dotimes (i n count)
189 (declare (fixnum i))
190 (let ((x (aref seq i)))
191 (incf count (if (compound-data-p x) (count-elements x) 1)))))))
195 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
196 ;;;;
197 ;;;; IF-ELSE Functions
198 ;;;;
199 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
201 (defun if-else (a x y)
202 "Args: (first x y)
203 Takes simple or compound data items FIRST, X and Y and returns result
204 of elementswise selecting from X if FIRST is not NIL and from Y
205 otherwise."
206 (flet ((base-if-else (a x y) (if a x y)))
207 (recursive-map-elements #'base-if-else #'if-else a x y)))