(setf (row-major-aref new-array i)
(row-major-aref array i)))
new-array))
+
+(declaim (inline displace-array))
+(defun displace-array (array &key (offset 0)
+ (dimensions (- (array-total-size array)
+ offset)))
+ "Return an array displaced to ARRAY with the given OFFSET and DIMENSIONS.
+Default arguments displace to a vector."
+ (make-array dimensions
+ :displaced-to array
+ :displaced-index-offset offset
+ :element-type (array-element-type array)))
interpolation coefficient V."
(+ a (* v (- b a))))
-(declaim (inline mean))
-(defun mean (sample)
- "Returns the mean of SAMPLE. SAMPLE must be a sequence of numbers."
- (/ (reduce #'+ sample) (length sample)))
-
-(declaim (inline median))
-(defun median (sample)
- "Returns median of SAMPLE. SAMPLE must be a sequence of real numbers."
- (let* ((vector (sort (copy-sequence 'vector sample) #'<))
+(defgeneric mean (object)
+ (:documentation "Returns the mean of OBJECT.
+Predefined methods work on sequences and arrays of numbers. Users can
+define new methods.")
+ (:method ((object list))
+ (let ((sum 0)
+ (count 0))
+ (declare (fixnum count))
+ (dolist (elt object)
+ (incf sum elt)
+ (incf count))
+ (/ sum count)))
+ (:method ((object vector))
+ ;; Need a separate method for vectors, since
+ ;; they could have fill-pointers which we need to respect.
+ (let ((n (length object)))
+ (/ (loop for index below n
+ summing (aref object index))
+ n)))
+ (:method ((object array))
+ (let ((n (array-total-size object)))
+ (/ (loop for index below n
+ summing (row-major-aref object index))
+ n)))
+ (:method ((object sequence))
+ ;; For implementations supporting custom sequence types.
+ (/ (reduce #'+ object) (length object))))
+
+(defun median-in-place (vector)
+ (declare (vector vector))
+ (let* ((vector (sort vector #'<))
(length (length vector))
(middle (truncate length 2)))
(if (oddp length)
(aref vector middle)
(/ (+ (aref vector middle) (aref vector (1- middle))) 2))))
+(defgeneric median (object)
+ (:documentation
+ "Returns median of OBJECT.
+Predefined methods work on sequences and arrays of numbers. Users can
+define new methods.")
+ (:method ((object list))
+ (median-in-place (copy-sequence 'vector object)))
+ (:method ((object array))
+ (median-in-place (copy-sequence 'vector (if (vectorp object)
+ object
+ (displace-array object)))))
+ (:method ((object sequence))
+ ;; For implementations supporting custom sequence types.
+ (median-in-place (copy-sequence 'vector object))))
+
(declaim (inline variance))
(defun variance (sample &key (biased t))
"Variance of SAMPLE. Returns the biased variance if BIASED is true (the default),
(typep copy 'simple-array)))
t)
+(deftest displace-array.1
+ (displace-array #2A((1 2)
+ (3 4)))
+ #(1 2 3 4))
+
+(deftest displace-array.2
+ (displace-array #2A((1 2)
+ (3 4))
+ :offset 1)
+ #(2 3 4))
+
+(deftest displace-array.3
+ (displace-array #2A((1 2)
+ (3 4))
+ :offset 1
+ :dimensions '(3 1))
+ #2A((2) (3) (4)))
+
(deftest array-index.1
(typep 0 'array-index)
t)
(mean '(1 2 10))
13/3)
+(deftest mean.4
+ (mean #2A((1 2 3)
+ (4 5 6)
+ (7 8 9)))
+ 5)
+
(deftest median.1
(median '(100 0 99 1 98 2 97))
97)
(median '(100 0 99 1 98 2 97 96))
193/2)
+(deftest median.3
+ (median #2A((100 0 99 1)
+ (98 2 97 96)))
+ 193/2)
+
(deftest variance.1
(variance (list 1 2 3))
2/3)