[common-math-cvs] r1 - in trunk: . common-math common-math/numerics common-math/numerics/linear-algebra

mantoniotti at common-lisp.net mantoniotti at common-lisp.net
Wed Aug 16 21:07:42 UTC 2006


Author: mantoniotti
Date: Wed Aug 16 17:07:41 2006
New Revision: 1

Added:
   trunk/
   trunk/common-math/
   trunk/common-math/common-math-pkg.lisp
   trunk/common-math/common-math-user-pkg.lisp
   trunk/common-math/common-math.lisp
   trunk/common-math/common-math.system
   trunk/common-math/numerics/
   trunk/common-math/numerics/linear-algebra/
   trunk/common-math/numerics/linear-algebra/common-math-extra.lisp
   trunk/common-math/numerics/linear-algebra/linear-algebra-pkg.lisp
   trunk/common-math/numerics/linear-algebra/linear-algebra.system
   trunk/common-math/numerics/linear-algebra/lu-decomposition.lisp
   trunk/common-math/numerics/linear-algebra/matrix-pkg.lisp
   trunk/common-math/numerics/linear-algebra/matrix.lisp
   trunk/common-math/numerics/linear-algebra/vector-matrix-conditions.lisp
   trunk/common-math/numerics/linear-algebra/vector-matrix.lisp
   trunk/common-math/numerics/linear-algebra/vector.lisp
   trunk/common-math/numerics/numerics.system
Log:
Initial import.

Added: trunk/common-math/common-math-pkg.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/common-math-pkg.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,47 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; common-math-pkg.lisp --
+
+(defpackage "COMMON-MATH" (:use "COMMON-LISP")
+  (:documentation "The COMMON MATH Package.
+This package contains `top level' definitions of a `generic math'
+package which can be used as a drop in replacement for the standard
+CL mathematics routines.  Note however, that this will of course
+come at a price.
+
+The COMMON-MATH package addresses the problem of having a generic and
+as complete as possible mathematics interface layer over a number of
+different algorithms and representations.  In this sense it aspires
+to bring to CL the flexibility of generic math operations, while
+preserving the low level hooks that could be used for (relative) efficiency.")
+
+  (:nicknames "CL.MATH" "CL.MATHEMATICS")
+  
+  (:shadow "=" "+" "-" "*" "/" ">" "<" ">=" "<=")
+  (:shadow "ZEROP" "EXPT" "GCD")
+  
+  (:export "=" "+" "-" "*" "/" ">" "<" ">=" "<=")
+  (:export "ZEROP" "EXPT" "GCD")
+
+  (:export "+POSITIVE-INFINITY+" "+NEGATIVE-INFINITY+")
+
+  (:export "INCREASING" "DECREASING")
+
+  (:export
+   "+%1" "+%2"
+   "*%1" "*%2"
+   "-%1" "-%2"
+   "/%1" "/%2"
+   "=%1" "=%2"
+   "<%2"
+   ">%2"
+   "<=%2"
+   ">=%2"
+   )
+
+  ;; Conditions
+  (:export "UNDEFINED-OPERATION")
+  
+  )
+
+;;;; end of file -- common-math-pkg.lisp --

Added: trunk/common-math/common-math-user-pkg.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/common-math-user-pkg.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,12 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; common-math-user-pkg.lisp --
+;;;; The COMMON-MATH-USER package.
+
+(defpackage "COMMON-MATH-USER" (:use "COMMON-MATH" "CL" #| "LINALG" |# )
+  (:shadowing-import-from "COMMON-MATH" "+" "-" "*" "/")
+  (:shadowing-import-from "COMMON-MATH" "<" ">" "<=" ">=" "=")
+  (:shadowing-import-from "COMMON-MATH" "ZEROP" "EXPT" "GCD")
+  )
+
+;;;; end of file -- common-math-user-pkg.lisp --
\ No newline at end of file

Added: trunk/common-math/common-math.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/common-math.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,603 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; common-math.lisp --
+
+(in-package "CL.MATHEMATICS")
+
+;;; undefined-operation --
+
+(define-condition undefined-operation (error)
+  ((operator :reader undefined-operation-operator
+	     :initarg :operator)
+   (arguments :reader undefined-operation-arguments
+	      :initarg :arguments)
+   )
+  (:documentation "The Undefined Operation Condition.")
+  (:report (lambda (uoc stream)
+	     (format stream "Undefined operation ~S called with ~S."
+		     (undefined-operation-operator uoc)
+		     (undefined-operation-arguments uoc))))
+  (:default-initargs :arguments () :operator nil))
+
+
+;;;---------------------------------------------------------------------------
+;;; Constants and parameters.
+
+(defconstant +negative-infinity+ '+negative-infinity+
+  "The symbolic +NEGATIVE-INFINITY+ constant.
+A representation of negative infinity.")
+(defconstant +positive-infinity+ '+positive-infinity+
+  "The symbolic +POSITIVE-INFINITY+ constant.
+A representation of positive infinity.")
+
+(defparameter *ignore-comparison-errors-p* nil)
+
+
+;;; (defconstant +negative-infinity+ most-negative-fixnum)
+;;; (defconstant +positive-infinity+ most-positive-fixnum)
+
+
+;;;---------------------------------------------------------------------------
+;;; Generic functions.
+;;; Note that the generic functions corresponding to traditional math
+;;; operators are named using a special notation to indicate their
+;;; arity.  Such 'operator' generic function are named as
+;;;
+;;;	<op>%<arity>
+;;;
+;;; The #\% character in the name is used to suggest "low level" as
+;;; usual. The Prolog-like #\/ could have been used instead but the
+;;; #\% has more tradition in CL circles.  The #\@ would have made
+;;; more sense, but some CL implementations already use it for other
+;;; purposes and setting up a separate readtable seems a little bit
+;;; too much for the time being.
+
+(defgeneric <%2 (x y)
+  (:documentation "The <%2 generic function.
+The binary LESS generic function which is specialized for various
+combinations of argument types.
+
+At a minimum there is a guarantee that the method on two NUMBER
+arguments dispatching on CL:< is defined.")
+  (:method ((x number) (y number))
+   (cl:< x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)))
+   nil)
+
+  (:method ((y (eql +negative-infinity+)) (x number))
+   T)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+)))
+   T)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)))
+   nil)
+
+  (:method ((x number) (y (eql +positive-infinity+)))
+   T)
+
+  (:method ((y (eql +positive-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+  )
+
+
+(defgeneric >%2 (x y)
+  (:method ((x number) (y number))
+   (cl:> x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)))
+   T)
+
+  (:method ((y (eql +negative-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)))
+   T)
+
+  (:method ((x number) (y (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x number))
+   T)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+  )
+
+
+(defmethod <%2 ((x symbol) (y symbol))
+  (string< x y))
+
+
+(defmethod >%2 ((x symbol) (y symbol))
+  (string> y x))
+
+
+(defgeneric <=%2 (x y)
+  (:method ((x number) (y number))
+   (cl:<= x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)))
+   nil)
+
+  (:method ((y (eql +negative-infinity+)) (x number))
+   T)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+)))
+   T)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)))
+   nil)
+
+  (:method ((x number) (y (eql +positive-infinity+)))
+   T)
+
+  (:method ((y (eql +positive-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+  )
+
+
+(defgeneric >=%2 (x y)
+  (:method ((x number) (y number))
+   (cl:>= x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)))
+   T)
+
+  (:method ((y (eql +negative-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)))
+   T)
+
+  (:method ((x number) (y (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x number))
+   T)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator 'lessp%2)))
+  )
+
+
+(defgeneric +%2 (x y &optional r)
+  (:method ((x number) (y number) &optional r)
+   (declare (ignore r))
+   (cl:+ x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((y (eql +negative-infinity+)) (x number) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   (error 'undefined-operation :operator '+%2))
+
+  (:method ((x number) (y (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((y (eql +positive-infinity+)) (x number) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   (error 'undefined-operation :operator '+%2))
+  )
+
+
+(defgeneric *%2 (x y &optional r)
+  (:method ((x number) (y number) &optional r)
+   (declare (ignore r))
+   (cl:* x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   (cond ((zerop x) (error 'undefined-operation :operator '*%2))
+	 ((plusp x) +negative-infinity+)
+	 (t +positive-infinity+)))
+
+  (:method ((y (eql +negative-infinity+)) (x number) &optional r)
+   (declare (ignore r))
+   (cond ((zerop x) (error 'undefined-operation :operator '*%2))
+	 ((plusp x) +negative-infinity+)
+	 (t +positive-infinity+)))
+
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((x number) (y (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   (cond ((zerop x) (error 'undefined-operation :operator '*%2))
+	 ((plusp x) +positive-infinity+)
+	 (t +negative-infinity+)))
+
+  (:method ((y (eql +positive-infinity+)) (x number) &optional r)
+   (declare (ignore r))
+   (cond ((zerop x) (error 'undefined-operation :operator '*%2))
+	 ((plusp x) +positive-infinity+)
+	 (t +negative-infinity+)))
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+))
+	    &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+  )
+
+
+(defgeneric -%2 (x y &optional r)
+  (:method ((x t) (y t) &optional r)
+   (declare (ignore r))
+   (+%2 x (-%1 y))))
+
+
+(defgeneric /%2 (x y &optional r)
+  (:method ((x number) (y number) &optional r)
+	   (declare (ignore r))
+	   (cl:/ x y))
+
+  (:method ((x t) (y t) &optional r)
+	   (declare (ignore r))
+	   (*%2 x (/%1 y))))
+
+
+(defgeneric +%1 (x &optional r)
+  (:method ((x number) &optional r)
+   (declare (ignore r))
+   (cl:+ x))
+
+  (:method ((x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  )
+
+(defgeneric *%1 (x &optional r)
+  (:method ((x number) &optional r)
+   (declare (ignore r))
+   (cl:* x))
+
+  (:method ((x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+   )
+
+(defgeneric -%1 (x &optional r)
+  (:method ((x number) &optional r)
+   (declare (ignore r))
+   (cl:- x))
+
+  (:method ((x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+   )
+
+(defgeneric /%1 (x &optional r)
+  (:method ((x number) &optional r)
+   (declare (ignore r))
+   (cl:/ x))
+
+  (:method ((x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   0)
+
+  (:method ((x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   0)
+   )
+
+
+(defgeneric =%2 (x y)
+  (:method ((x number) (y number)) (cl:= x y))
+
+  (:method ((x number) (y (eql +negative-infinity+)))
+   nil)
+
+  (:method ((y (eql +negative-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator '=%2)))
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)))
+   nil)
+
+  (:method ((x number) (y (eql +positive-infinity+)))
+   nil)
+
+  (:method ((y (eql +positive-infinity+)) (x number))
+   nil)
+   
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)))
+   (unless *ignore-comparison-errors-p*
+     (error 'undefined-operation :operator '=%2)))
+  )
+
+
+(defgeneric =%1 (x)
+  (:method ((x t)) T)
+  )
+
+
+(defgeneric gcd%2 (x y)
+  (:method ((x integer) (y integer))
+   (cl:gcd x y)))
+
+
+;;;---------------------------------------------------------------------------
+;;; Redefined Common Lisp operators.
+
+(defun + (&rest args)
+  (if (null args)
+      (cl:+)
+      (let ((n-args (list-length args)))
+        (cond ((cl:= n-args 1)
+               (+%1 (first args)))
+              ((cl:= n-args 2)
+               (+%2 (first args) (second args)))
+              (t (+%2 (first args) (apply #'+ (rest args))))
+              ))))
+
+
+(defun - (arg1 &rest args)
+  (if (null args)
+      (-%1 arg1)
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (-%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of summation.
+            (loop for arg in args
+                  for minuend =(-%2 arg1 arg) then (-%2 minuend arg)
+                  finally (return minuend))))
+      ))
+
+
+(defun * (&rest args)
+  (if (null args)
+      (cl:*)
+      (let ((n-args (list-length args)))
+        (cond ((cl:= n-args 1)
+               (*%1 (first args)))
+              ((cl:= n-args 2)
+               (*%2 (first args) (second args)))
+              (t (*%2 (first args) (apply #'* (rest args))))
+              ))))
+
+
+(defun / (arg1 &rest args)
+  (if (null args)
+      (/%1 arg1)
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (/%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of divisions.
+            (loop for arg in args
+                  for dividend = (/%2 arg1 arg) then (/%2 dividend arg)
+                  finally (return dividend))))
+      ))
+
+
+(defun = (arg1 &rest args)
+  (if (null args)
+      (=%1 arg1)
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (=%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of the equality test.
+            (loop for arg in args
+                  always (=%2 arg1 arg))))
+      ))
+
+
+(defun < (arg1 &rest args)
+  (if (null args)
+      ;; (<%1 arg1)
+      t
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (<%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of the equality test.
+            (loop for a1 = arg1 then a2
+                  for a2 in args
+		  always (<%2 a1 a2))))
+      ))
+
+
+(defun > (arg1 &rest args)
+  (if (null args)
+      t
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (>%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of the equality test.
+            (loop for a1 = arg1 then a2
+                  for a2 in args
+		  always (>%2 a1 a2))))
+      ))
+
+
+(defun <= (arg1 &rest args)
+  (if (null args)
+      t
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (<=%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of the equality test.
+            (loop for a1 = arg1 then a2
+                  for a2 in args
+		  always (<=%2 a1 a2))))
+      ))
+
+
+(defun >= (arg1 &rest args)
+  (if (null args)
+      t
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (>=%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of the equality test.
+            (loop for a1 = arg1 then a2
+                  for a2 in args
+		  always (>=%2 a1 a2))))
+      ))
+
+
+(defun gcd (&rest args)
+  (if (null args)
+      (cl:gcd)
+      (let ((n-args (list-length args)))
+        (cond ((cl:= n-args 1)
+               (gcd%2 (first args) (first args)))
+              ((cl:= n-args 1)
+               (gcd%2 (first args) (second args)))
+              (t
+               (apply #'gcd
+                      (gcd%2 (first args) (second args))
+                      (cddr args)))
+              ))))
+
+
+(defgeneric expt (base power)
+  (:method ((base number) (power number))
+   (cl:expt base power)))
+
+
+(defgeneric zerop (n)
+  (:method ((n number))
+   (cl:zerop n))
+
+  (:method ((x (eql +positive-infinity+)))
+   nil)
+
+  (:method ((x (eql +negative-infinity+)))
+   nil)
+  )
+
+
+
+;;;---------------------------------------------------------------------------
+;;; Other functions.
+
+
+(defun increasing (x)
+  (declare (type sequence x))
+  (loop for i from 0 below (1- (length x))
+	for a1 = (elt x 0) then a2
+	for a2 = (elt x (1+ i))
+	always (<=%2 a1 a2)))
+
+
+(defun decreasing (x)
+  (declare (type sequence x))
+  (loop for i from 0 below (1- (length x))
+	for a1 = (elt x 0) then a2
+	for a2 = (elt x (1+ i))
+	always (>=%2 a1 a2)))
+
+
+
+(defun strictly-increasing (x)
+  (declare (type sequence x))
+  (loop for i from 0 below (1- (length x))
+	for a1 = (elt x 0) then a2
+	for a2 = (elt x (1+ i))
+	always (<%2 a1 a2)))
+
+
+(defun strictly-decreasing (x)
+  (declare (type sequence x))
+  (loop for i from 0 below (1- (length x))
+	for a1 = (elt x 0) then a2
+	for a2 = (elt x (1+ i))
+	always (>%2 a1 a2)))
+
+;;; end of file -- common-math.lisp --

Added: trunk/common-math/common-math.system
==============================================================================
--- (empty file)
+++ trunk/common-math/common-math.system	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,24 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; common-math.system --
+
+(eval-when (:load-toplevel :execute)
+  (mk:add-registry-location (make-pathname :name nil
+					   :type nil
+					   :defaults *load-truename*))
+  )
+
+
+(mk:defsystem "common-math"
+  :components ((:file "common-math-pkg")
+	       (:file "common-math"
+		      :depends-on ("common-math-pkg"))
+	       (:system "numerics")
+               ;; (:system "polynomials")
+               ;; (:system "formulas")
+	       (:file "common-math-user-pkg"
+		      :depends-on ("numerics"))
+	       )
+  )
+
+;;;; end of file -- common-math.system --

Added: trunk/common-math/numerics/linear-algebra/common-math-extra.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/common-math-extra.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,98 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; common-math-extra.lisp --
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+;;;---------------------------------------------------------------------------
+;;; More functions.  Essentially the top level element-wise array operations.
+
+(defgeneric .*%2 (x y &optional r)
+  (:method ((x number) (y number) &optional r)
+   (declare (ignore r))
+   (*%2 x y))
+
+  (:method ((x (eql +negative-infinity+)) (y number) &optional r)
+   (declare (ignore r))
+   (*%2 x y))
+
+  (:method ((x (eql +positive-infinity+)) (y number) &optional r)
+   (declare (ignore r))
+   (*%2 x y))
+
+
+  (:method ((y number) (x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   (*%2 x y))
+
+
+  (:method ((y number) (x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   (*%2 x y))
+
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((y (eql +negative-infinity+)) (x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((y (eql +positive-infinity+)) (x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+
+  (:method ((x (eql +negative-infinity+)) (y (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+  )
+
+
+(defgeneric .*%1 (x &optional r)
+  (:method ((x number) &optional r)
+   (declare (ignore r))
+   (*%1 x))
+
+  (:method ((x (eql +positive-infinity+)) &optional r)
+   (declare (ignore r))
+   +positive-infinity+)
+
+  (:method ((x (eql +negative-infinity+)) &optional r)
+   (declare (ignore r))
+   +negative-infinity+)
+  )
+
+
+(defgeneric ./%2 (x y &optional r))
+
+(defgeneric ./%1 (x &optional r))
+
+
+;;;---------------------------------------------------------------------------
+;;; The generic top-level functions.
+
+(defun .* (&rest args)
+  (if (null args)
+      (cl:*)
+      (let ((n-args (list-length args)))
+        (cond ((cl:= n-args 1) (.*%1 (first args)))
+              ((cl:= n-args 2) (.*%2 (first args) (second args)))
+              (t (.*%2 (first args) (apply #'.* (rest args))))
+              ))))
+
+
+(defun ./ (arg1 &rest args)
+ (if (null args)
+      (./%1 arg1)
+      (let ((n-args (list-length args)))
+        (if (cl:= n-args 1)
+            (./%2 arg1 (first args))
+            ;; The loop is done in order not to assume anything about
+            ;; the nature of divisions.
+            (loop for arg in args
+                  for dividend = (./%2 arg1 arg) then (./%2 dividend arg)
+                  finally (return dividend))))
+      ))
+
+;;;; end of file -- common-math-extra.lisp --

Added: trunk/common-math/numerics/linear-algebra/linear-algebra-pkg.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/linear-algebra-pkg.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,19 @@
+;;; -*- Mode: Lisp -*-
+
+(defpackage "CL.MATH.LINEAR-ALGEBRA" (:use "CL.MATH" "COMMON-LISP")
+  (:nicknames "CL-MATH-LINALG" "LINALG")
+  
+  (:shadow cl:zerop cl:expt cl:gcd)
+
+  (:shadowing-import-from "CL.MATH" "+" "-" "*" "/" "=" ">" "<" ">=" "<=")
+  
+  (:export "=" "+" "-" "*" "/" ">" "<" ">=" "<=")
+  (:export "ZEROP" "EXPT" "GCD")
+
+  (:export ".*" "./" "EXPT*")
+
+  (:export ".*%2" ".*%1" "./%2" "./%1")
+  
+  )
+
+;;; end of file -- linear-algebra-pkg.lisp --

Added: trunk/common-math/numerics/linear-algebra/linear-algebra.system
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/linear-algebra.system	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,13 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; linear-algebra.system --
+
+(mk:defsystem "linear-algebra"
+  :components ("linear-algebra-pkg"
+               "vector-matrix-conditions"
+               "common-math-extra"
+               "vector"
+               "matrix"
+               "lu-decomposition"))
+
+;;;; end of file -- linear-algebra.system --

Added: trunk/common-math/numerics/linear-algebra/lu-decomposition.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/lu-decomposition.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,326 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; lu-decomposition.lisp --
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+(define-condition singular-matrix-in-operation (arithmetic-error)
+  ()
+  (:report (lambda (cnd stream)
+             (format stream "Singular matrix passed to operation ~S."
+                     (arithmetic-error-operation cnd)))))
+
+
+(defparameter *epsilon* 1.0e-20) ; Change this to CL constant.
+
+
+(defgeneric square-matrix-p (m)
+  (:method ((m array))
+   (and (matrix-array-p m)
+        (cl:= (array-dimension m 0) (array-dimension m 1))))
+  (:method ((m matrix))
+   (cl:= (matrix-row-number m) (matrix-column-number m))))
+
+
+
+;;; Different base type.
+;;; Probably a macrolet is in order.
+
+(defun lu-decompose (m &optional
+                       (lu (make-array (array-dimensions m)
+                                       :element-type (array-element-type m)
+                                       :initial-element (coerce 0 (array-element-type m))))
+                       (permutations (make-array (array-dimension m 0)
+                                                 :initial-element 0
+                                                 :element-type 'fixnum)))
+  (declare (type (array number (cl:* cl:*)) m lu)
+           (type (vector fixnum) permutations))
+
+  (assert (square-matrix-p m))
+  (assert (square-matrix-p lu))
+  (assert (cl:= (length permutations) (array-dimension m 0)))
+
+  (let* ((n (array-dimension m 0))
+         (row-scaling-vector (make-array n
+                                         :initial-element (coerce 0 (array-element-type m))
+                                         :element-type (array-element-type m)))
+         (parity 1)
+         (imax 0)
+         )
+    (declare (dynamic-extent row-scaling-vector)
+             (type fixnum imax n)
+             (type (member -1 1) parity)
+             (type (simple-array number (cl:*)) row-scaling-vector))
+
+    ;; Copy M into LU and then just operate the in-place algorithm on LU.
+    ;; If M is EQ to LU, that means that the argumen was supplied and
+    ;; that the user actually wants a destructive operation.  Copying
+    ;; can be avoided in this case.
+    (unless (eq m lu)
+      (dotimes (i n)
+        (dotimes (j n)
+          (setf (aref lu i j) (aref m i j)))))
+
+
+    ;; Loop over rows to get the implicit scaling information.
+    ;; Meanwhile check that the matrix is non-singular.
+    (dotimes (i n)
+      (loop for k of-type fixnum from 0 below n
+            maximize (abs (aref lu i k)) into big ;; of-type (number) ; not CL.
+            finally
+            (when (cl:zerop big)
+              (error 'singular-matrix-in-operation
+                     :operation 'lu-decompose
+                     :operands (list m)))
+            (setf (aref row-scaling-vector i) (/ big))))
+
+    ;; Loop over the columns of Crout's method.
+    (dotimes (j n)
+      (block operate-on-column
+        ;; (format t "Column ~D IMAX = ~D~%" j imax)
+        (dotimes (i j)
+          (let ((sum (aref lu i j)))
+            (declare (type number sum))
+            (dotimes (k i)
+              (decf sum (* (aref lu i k) (aref lu k j))))
+            (setf (aref lu i j) sum)))
+
+        ;; Initialize the search for the largest pivot.
+        (loop with big of-type number = 0.0
+              for i from j below n
+              do (let ((sum (aref lu i j)))
+                   (declare (type number sum))
+                   (dotimes (k j)
+                     (decf sum (* (aref lu i k) (aref lu k j))))
+                   (setf (aref lu i j) sum)
+                   (let ((temp (* (aref row-scaling-vector i) (abs sum))))
+                     (declare (type number temp))
+                     (when (>= temp big)
+                       (setf big temp
+                             imax i)))
+                   ))
+
+        ;; (format t "Now IMAX = ~D~%" imax)
+        (when (/= imax j)
+          ;; We need to interchange rows.
+          (dotimes (k n)
+            (rotatef (aref lu imax k) (aref lu j k)))
+          (setf parity (- parity))
+          (setf (aref row-scaling-vector imax)
+                (aref row-scaling-vector j)))
+        (setf (aref permutations j) imax)
+        ;; (format t "Now J = ~D IMAX = ~D~2%" j imax)
+        (when (cl:zerop (aref lu j j))
+          (setf (aref lu j j) *epsilon*))
+
+        (when (/= j (1- n))
+          (loop with pivot of-type number = (/ (aref lu j j))
+                for i from (1+ j) below n
+                do (setf (aref lu i j) (* pivot (aref lu i j)))))
+
+        ))
+    (values lu permutations parity)
+    ))
+
+
+(defun lu-decompose/double-float (m &optional
+                                    (lu (make-array (array-dimensions m)
+                                                    :element-type 'double-float
+                                                    :initial-element 0.0d0))
+                                    (permutations (make-array (array-dimension m 0)
+                                                              :initial-element 0
+                                                              :element-type 'fixnum)))
+  (declare (type (array double-float (cl:* cl:*)) m lu)
+           (type (vector fixnum) permutations))
+
+  (assert (square-matrix-p m))
+  (assert (square-matrix-p lu))
+  (assert (cl:= (length permutations) (array-dimension m 0)))
+
+  (let* ((n (array-dimension m 0))
+         (row-scaling-vector (make-array n
+                                         :initial-element (coerce 0 (array-element-type m))
+                                         :element-type (array-element-type m)))
+         (parity 1.0d0)
+         (imax 0)
+         )
+    (declare (dynamic-extent row-scaling-vector)
+             (type fixnum n imax)
+             (type (double-float -1.01d0 1.01d0) parity)
+             (type (simple-array double-float (cl:*)) row-scaling-vector))
+
+    ;; Copy M into LU and then just operate the in-place algorithm on LU.
+    ;; If M is EQ to LU, that means that the argumen was supplied and
+    ;; that the user actually wants a destructive operation.  Copying
+    ;; can be avoided in this case.
+    (unless (eq m lu)
+      (dotimes (i n)
+        (dotimes (j n)
+          (setf (aref lu i j) (aref m i j)))))
+
+
+    ;; Loop over rows to get the implicit scaling information.
+    ;; Meanwhile check that the matrix is non-singular.
+    (dotimes (i n)
+      (loop for k of-type fixnum from 0 below n
+            maximize (abs (aref lu i k)) into big of-type double-float
+            finally
+            (when (cl:zerop big)
+              (error 'singular-matrix-in-operation
+                     :operation 'lu-decompose
+                     :operands (list m)))
+            (setf (aref row-scaling-vector i) (/ big))))
+
+    ;; Loop over the columns of Crout's method.
+    (dotimes (j n)
+      (block operate-on-column
+        ;; (format t "Column ~D IMAX = ~D~%" j imax)
+        (dotimes (i j)
+          (let ((sum (aref lu i j)))
+            (declare (type double-float sum))
+            (dotimes (k i)
+              (decf sum (* (aref lu i k) (aref lu k j))))
+            (setf (aref lu i j) sum)))
+
+        ;; Initialize the search for the largest pivot.
+        (loop with big of-type double-float = 0.0d0
+              for i of-type fixnum from j below n
+              do (let ((sum (aref lu i j)))
+                   (declare (type double-float sum))
+                   (dotimes (k j)
+                     (decf sum (* (aref lu i k) (aref lu k j))))
+                   (setf (aref lu i j) sum)
+                   (let ((temp (* (aref row-scaling-vector i) (abs sum))))
+                     (declare (type double-float temp))
+                     (when (>= temp big)
+                       (setf big temp
+                             imax i)))
+                   ))
+
+        ;; (format t "Now IMAX = ~D~%" imax)
+        (when (/= imax j)
+          ;; We need to interchange rows.
+          (dotimes (k n)
+            (rotatef (aref lu imax k) (aref lu j k)))
+          (setf parity (- parity))
+          (setf (aref row-scaling-vector imax)
+                (aref row-scaling-vector j)))
+        (setf (aref permutations j) imax)
+        ;; (format t "Now J = ~D IMAX = ~D~2%" j imax)
+        (when (cl:zerop (aref lu j j))
+          (setf (aref lu j j) *epsilon*))
+
+        (when (/= j (1- n))
+          (loop with pivot of-type double-float = (/ (aref lu j j))
+                for i from (1+ j) below n
+                do (setf (aref lu i j) (* pivot (aref lu i j)))))
+
+        ))
+    (values lu permutations parity)
+    ))
+
+
+(defun split-lu-matrix (lu)
+  (let ((l (make-array (array-dimensions lu) :initial-element 0))
+        (u (make-array (array-dimensions lu) :initial-element 0))
+        (n (array-dimension lu 0))
+        )
+    (dotimes (i n)
+      (dotimes (j i)
+        (setf (aref l i j) (aref lu i j)))
+      (setf (aref l i i) 1))
+
+    (dotimes (i n)
+      (loop for j from i below n
+            do (setf (aref u i j) (aref lu i j))))
+
+    (values l u)))
+
+
+;;;---------------------------------------------------------------------------
+;;; lu-back-substitution
+
+(defun lu-back-substitution (lu permutations b)
+  (let ((n (array-dimension lu 0)))
+    (loop with ii of-type fixnum = 0
+          for i of-type fixnum from 0 below n
+          for ip of-type number = (aref permutations i)
+          for sum of-type number = (aref b ip)
+          do (setf (aref b ip) (aref b i))
+          do (cond ((not (cl:zerop ii))
+                    (loop for j of-type fixnum from ii below (1- i)
+                          do (decf sum (* (aref lu i j) (aref b i)))))
+                   ((not (cl:zerop sum))
+                    (setf (aref b i) sum)))
+          )
+    (loop for i of-type fixnum from (1- n) downto 0
+          for sum of-type number = (aref b i)
+          do (loop for j of-type fixnum from (1+ i) below n
+                   do (decf sum (* (aref lu i j) (aref b i))))
+          do (setf (aref b i) (/ sum (aref lu i i))))
+    )
+  b)
+
+
+;;;---------------------------------------------------------------------------
+;;; solve
+
+(defmethod solve ((a array) (b vector) &optional (result (copy-seq b)))
+  (multiple-value-bind (lu permutations)
+      (lu-decompose a)
+    (lu-back-substitution lu permutations result)))
+
+(defmethod solve ((a matrix) (b vector) &optional (result (copy-seq b)))
+  (solve (matrix-data a) b result))
+
+
+(defmethod solve/double-float ((a array) (b vector) &optional (result (copy-seq b)))
+  (multiple-value-bind (lu permutations)
+      (lu-decompose/double-float a)
+    (lu-back-substitution lu permutations result)))
+
+(defmethod solve/double-float ((a matrix) (b vector) &optional (result (copy-seq b)))
+  (solve/double-float (matrix-data a) b result))
+
+
+;;;---------------------------------------------------------------------------
+;;; det
+
+(defmethod det ((a array))
+  (assert (square-matrix-p a))
+  (multiple-value-bind (lu permutations parity)
+      (lu-decompose a)
+    (declare (ignore permutations))
+    (dotimes (i (array-dimension lu 0) parity)
+      (setf parity (* parity (aref lu i i))))))
+
+(defmethod det ((a matrix))
+  (det (matrix-data a)))
+
+
+(defmethod det/double-float ((a array))
+  (assert (square-matrix-p a))
+  (multiple-value-bind (lu permutations parity)
+      (lu-decompose a)
+    (declare (type (array double-float (cl:* cl:*)) lu)
+             (ignore permutations)
+             (type double-float parity))
+    (dotimes (i (array-dimension lu 0) parity)
+      (setf parity (* parity (aref lu i i))))))
+
+(defmethod det/double-float ((a matrix))
+  (det/double-float (matrix-data a)))
+
+
+;;;===========================================================================
+;;; Test
+
+(defvar A #2A((1 2 3)
+              (2 -1 1)
+              (3 4 -1)))
+
+(defvar LU-A #2A((1 2 3)
+                 (2 -5 -5)
+                 (3 0.4 -8)))
+
+;;; end of file -- lu-decomposition.lisp --

Added: trunk/common-math/numerics/linear-algebra/matrix-pkg.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/matrix-pkg.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,19 @@
+;;; -*- Mode: Lisp -*-
+
+(defpackage "CL.MATH.POLYNOMIALS" (:use "CL.MATH" "COMMON-LISP")
+  (:nicknames "POLY")
+  
+  (:shadow cl:zerop cl:expt cl:gcd)
+
+  (:shadowing-import-from "CL.MATH" "+" "-" "*" "/" "=" ">" "<" ">=" "<=")
+  
+  (:export "=" "+" "-" "*" "/" ">" "<" ">=" "<=")
+  (:export "ZEROP" "EXPT" "GCD")
+  
+  (:export "MAKE-POLYNOMIAL"
+   "POLYNOMIAL"
+   "UNIVARIATE-POLYNOMIAL"
+   )
+  )
+
+;;; end of file -- polymonials-pkg.lisp --

Added: trunk/common-math/numerics/linear-algebra/matrix.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/matrix.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,950 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; matrix.lisp --
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+(deftype matrix-array (&optional (type 'number) (m 'cl:*) (n 'cl:*))
+  `(array ,type (,m ,n)))
+
+
+(defparameter *default-matrix-element-type* 'double-float)
+
+(defclass matrix ()
+  ((data :reader matrix-data :initarg :data))
+  (:default-initargs :data (make-array '(0 0) :element-type 'number)))
+
+(defgeneric matrix-p (x
+                      #|&optional
+                      (element-type *default-matrix-element-type*)
+                      |#
+                      )
+  (:method ((x matrix)) t)
+  (:method ((x t)) nil)
+  (:method ((x vector)) t) ; Note that this is technically correct, but
+                           ; it may cause problems.
+  (:method ((x array)) (cl:<= (array-rank x) 2)) ; Same here.
+  )
+
+
+(defvar *check-element-type* nil)
+
+
+;;;---------------------------------------------------------------------------
+;;; Protocol.
+
+(defgeneric matrix-array-p (x &key check-element-type)
+  (:method ((x array) &key (check-element-type *check-element-type*))
+   (and (cl:<= (array-rank x) 2)
+        (or (not check-element-type)
+            (nth-value 0 (subtypep (array-element-type x) 'number)))))
+  
+  (:method ((x t) &key check-element-type)
+   (declare (ignore check-element-type))
+   nil))
+
+
+
+(defgeneric matrix-element-type (m))
+
+(defgeneric matrix-row-number (m)
+  (:method ((x matrix)) (array-dimension (matrix-data x) 0))
+  (:method ((x vector)) 1)
+  (:method ((x array))
+   (assert (matrix-array-p x))
+   (array-dimension x 0)))
+
+
+(defgeneric matrix-column-number (m)
+  (:method ((x matrix)) (array-dimension (matrix-data x) 1))
+  (:method ((x vector)) (length x))
+  (:method ((x array))
+   (assert (matrix-array-p x))
+   (array-dimension x 1)))
+
+
+(defgeneric matrix-dimensions (m)
+  (:method ((x matrix)) (array-dimensions (matrix-data x)))
+  (:method ((x array))
+   (assert (matrix-array-p x))
+   (array-dimensions x)))
+
+
+(defgeneric matrix-dimension (m axis)
+  (:method ((m matrix) axis)
+   (declare (type fixnum axis))
+   (array-dimension (matrix-data m) axis))
+  (:method ((m array) axis)
+   (declare (type fixnum axis))
+   (array-dimension m axis)))
+
+
+(defmethod matrix-dimension :before ((m array) axis)
+  (assert (matrix-array-p m)))
+  
+
+
+(defmethod matrix-element-type ((m matrix)) (array-element-type (matrix-data m)))
+
+(defmethod matrix-element-type ((m array)) (array-element-type m))
+
+(defmethod matrix-element-type :before ((m array))
+  (assert (matrix-array-p m)))
+
+
+(defgeneric shape-equal-p (m1 m2)
+  (:documentation "Returns non-NIL when M1 and M2 have the same `shape'."))
+
+
+(defmethod shape-equal-p ((m1 matrix) (m2 matrix))
+  (with-slots ((m1d data))
+      m1
+    (with-slots ((m2d data))
+        m2
+      (and (cl:= (array-dimension m1d 0)
+                 (array-dimension m2d 0))
+           (cl:= (array-dimension m1d 1)
+                 (array-dimension m2d 1))))))
+
+
+(defmethod shape-equal-p ((m1 array) (m2 matrix))
+  (assert (matrix-array-p m1 :check-element-type nil))
+  (let ((m1d m1))
+    (with-slots ((m2d data))
+        m2
+      (and (cl:= (array-dimension m1d 0)
+                 (array-dimension m2d 0))
+           (cl:= (array-dimension m1d 1)
+                 (array-dimension m2d 1))))))
+
+
+(defmethod shape-equal-p ((m2 matrix) (m1 array))
+  (shape-equal-p m1 m2))
+
+
+(defmethod shape-equal-p ((m1 array) (m2 array))
+  (assert (matrix-array-p m1 :check-element-type nil))
+  (assert (matrix-array-p m2 :check-element-type nil))
+  (let ((m1d m1)
+        (m2d m2)
+        )
+    (and (cl:= (array-dimension m1d 0)
+               (array-dimension m2d 0))
+         (cl:= (array-dimension m1d 1)
+               (array-dimension m2d 1)))))
+
+
+(defmethod shape-equal-p ((m1 vector) (m2 vector))
+  (cl:= (cl:length m1) (cl:length m2)))
+
+
+(defmethod shape-equal-p ((m1 column) (m2 vector))
+  (cl:= 1 (vector-length m1) (cl:length m2)))
+
+
+(defmethod shape-equal-p ((m2 vector) (m1 column))
+  (shape-equal-p m1 m2))
+
+
+;;;---------------------------------------------------------------------------
+;;; Creation.
+
+(defun make-matrix (n m
+                      &rest array-keys
+                      &key
+                      (element-type *default-matrix-element-type*)
+                      (initial-element (coerce 0 element-type) ie-supplied-p)
+                      (initial-contents () ic-supplied-p)
+                      &allow-other-keys)
+  (when (and ie-supplied-p ic-supplied-p)
+    (error "The MAKE-MATRIX :INITIAL-ELEMENT and :INITIAL-CONTENTS keywords may not be simultaneously supplied."))
+
+  (let ((data (cond ((and ic-supplied-p
+                          (matrix-array-p initial-contents))
+                     initial-contents)
+                    (ic-supplied-p
+                     (apply #'make-array (list n m)
+                            (append array-keys
+                                    (list :element-type element-type))))
+                    (t
+                     (apply #'make-array (list n m)
+                            (append array-keys
+                                    (list :element-type element-type
+                                          :initial-element initial-element)))
+                     )))
+        )
+    (make-instance 'matrix :data data)))
+
+
+(defun make-identity-matrix (n &rest array-keys &key &allow-other-keys)
+  (when (getf array-keys :initial-contents)
+    (warn "MAKE-IDENTITY-MATRIX passed an :INITIAL-CONTENTS argument.")
+    (remf array-keys :initial-contents))
+  (when (getf array-keys :initial-element)
+    (warn "MAKE-IDENTITY-MATRIX passed an :INITIAL-ELEMENT argument.")
+    (remf array-keys :initial-element))
+  (let* ((id (apply #'make-matrix n n array-keys))
+         (data (matrix-data id))
+         (one (coerce 1 (array-element-type data)))
+         )
+    (dotimes (i n id)
+      (setf (aref data i i) one))))
+
+
+(defun eye (n &rest array-keys &key &allow-other-keys)
+  (apply #'make-identity-matrix n array-keys))
+
+
+(defun make-zero-matrix (n m
+                           &rest array-keys
+                           &key (element-type *default-matrix-element-type*)
+                           &allow-other-keys)
+  (when (getf array-keys :initial-element)
+    (warn "MAKE-ZERO-MATRIX passed and :INITIAL-ELEMENT argument.")
+    (remf array-keys :initial-element))
+  (apply #'make-matrix n m (append array-keys
+                                   (list :initial-element (coerce 0 element-type)
+                                         :element-type element-type))))
+
+
+(defun zeros (n m &rest array-keys &key &allow-other-keys)
+  (apply #'make-zero-matrix n m array-keys))
+
+
+;;;---------------------------------------------------------------------------
+;;; copy-matrix --
+;;; Uses the code from K Pitman and B. Margolin appeared on CLL a long
+;;; long time ago.
+;;; Note that at least on LW this code has some of the usual problems
+;;; with DOUBLE-FLOATS.
+#|
+(defun copy-array (array)
+  (adjust-array (make-array (array-dimensions array)
+			    :displaced-to array
+			    :element-type (array-element-type array))
+		(array-dimensions array)
+		:displaced-to nil))
+|#
+
+
+(defmethod copy-matrix ((m matrix))
+  (let* ((array (matrix-data m))
+         (result-data
+          (adjust-array (make-array (array-dimensions array)
+                                    :displaced-to array
+                                    :element-type (array-element-type array))
+                        (array-dimensions array)
+                        :displaced-to nil))
+         )
+    (make-instance 'matrix :data result-data)))
+
+
+(defmethod copy-matrix ((m array))
+  (check-type m matrix-array)
+  (adjust-array (make-array (array-dimensions m)
+                            :displaced-to m
+                            :element-type (array-element-type m))
+                (array-dimensions m)
+                :displaced-to nil))
+
+
+;;;---------------------------------------------------------------------------
+;;; Equality.
+
+(defmethod =%2 ((x array) (y array))
+  (and (matrix-array-p x)
+       (matrix-array-p y)
+       ;; (cl:= (matrix-row-number x) (matrix-row-number y))
+       ;; (cl:= (matrix-column-number x) (matrix-column-number y))
+       (cl:= (array-dimension x 0) (array-dimension y 0))
+       (cl:= (array-dimension x 1) (array-dimension y 1))
+       (loop for i from 0 below (array-total-size x)
+             always (=%2 (row-major-aref x i) (row-major-aref y i)))))
+
+
+(defmethod =%2 ((x matrix) (y matrix))
+  (or (eq x y)
+      (=%2 (matrix-data x) (matrix-data y))))
+
+
+(defmethod =%2 ((x matrix) (y array))
+  (=%2 (matrix-data x) y))
+
+
+(defmethod =%2 ((y array) (x matrix))
+  (=%2 (matrix-data x) y))
+
+
+;;;---------------------------------------------------------------------------
+;;; zerop
+
+(defmethod zerop ((x array))
+  (and (matrix-array-p x)
+       (loop for i from 0 below (array-total-size x)
+             always (zerop (row-major-aref x i)))))
+
+
+(defmethod zerop ((x matrix))
+  (zerop (matrix-data x)))
+
+
+;;;---------------------------------------------------------------------------
+;;; Addition.
+
+(defmethod +%2 :before ((x matrix) (y matrix)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod +%2 :before ((x matrix) (y array)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod +%2 :before ((y array) (x matrix)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod +%2 ((x number) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (shape-equal-p y r)))
+  (with-slots (data) y
+    (with-slots ((result data)) r
+      (dotimes (i (array-total-size data) r)
+        (setf (row-major-aref result i) (+%2 x (row-major-aref data i))))
+      )))
+
+
+(defmethod +%2 ((y matrix) (x number) &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (shape-equal-p y r)))
+  (with-slots (data) y
+    (with-slots ((result data)) r
+      (dotimes (i (array-total-size data) r)
+        (setf (row-major-aref result i) (+%2 x (row-major-aref data i))))
+      )))
+    
+
+
+#+with-slots-slow
+(defmethod +%2 ((x matrix) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (with-slots ((m1 data)) x
+    (with-slots ((m2 data)) y
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r
+  )
+
+
+(defmethod +%2 ((x matrix) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (let ((m1 (matrix-data x))
+        (m2 (matrix-data y))
+        (result (matrix-data r))
+        )
+    (dotimes (i (array-total-size m1) r)
+      (setf (row-major-aref result i)
+            (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+    ))
+
+
+#+with-slots-slow
+(defmethod +%2 ((x array) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (let ((m1 x))
+    (with-slots ((m2 data)) y
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r)
+
+
+
+(defmethod +%2 ((x array) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (let ((m1 x)
+        (m2 (matrix-data y))
+        (result (matrix-data r))
+        )
+    (dotimes (i (array-total-size m1) r)
+      (setf (row-major-aref result i)
+            (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+    ))
+
+
+#+with-slots-slow
+(defmethod +%2 ((y matrix) (x array) &optional (r (copy-matrix y) r-supplied-p))
+  (let ((m1 x))
+    (with-slots ((m2 data)) y
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r)
+
+
+
+(defmethod +%2 ((y matrix) (x array) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (let ((m1 x)
+        (m2 (matrix-data y))
+        (result (matrix-data r))
+        )
+    (dotimes (i (array-total-size m1) r)
+      (setf (row-major-aref result i)
+            (cl:+ (row-major-aref m1 i) (row-major-aref m2 i))))
+    ))
+
+
+;;;---------------------------------------------------------------------------
+;;; Subtraction.
+
+
+(defmethod -%2 :before ((x matrix) (y matrix)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod -%2 :before ((x matrix) (y array)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod -%2 :before ((y array) (x matrix)
+                        &optional
+                        (r nil r-supplied-p))
+  (assert (shape-equal-p x y))
+  (when r-supplied-p
+    (assert (matrix-p x))
+    (assert (shape-equal-p x r))))
+
+
+(defmethod -%2 ((x matrix) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (with-slots ((m1 data)) x
+    (with-slots ((m2 data)) y
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:- (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r
+  )
+
+(defmethod -%2 ((x array) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (let ((m1 x))
+    (with-slots ((m2 data)) y
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:- (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r)
+
+(defmethod -%2 ((y matrix) (x array) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (with-slots ((m1 data)) y
+    (let ((m2 x))
+      (with-slots ((result data)) r
+        (dotimes (i (array-total-size m1))
+          (setf (row-major-aref result i)
+                (cl:- (row-major-aref m1 i) (row-major-aref m2 i))))
+        )))
+  r)
+
+
+;;;---------------------------------------------------------------------------
+;;; Multiplication.
+
+(defgeneric make-*-result-matrix (x y &optional element-type)
+  (:documentation
+   "Creates a matrix serve as result of a multiplication.")
+
+  (:method ((x matrix) (y matrix)
+            &optional (element-type *default-matrix-element-type*))
+   (make-matrix (matrix-row-number x)
+                (matrix-column-number y)
+                :element-type element-type))
+
+  (:method ((x array) (y matrix)
+            &optional (element-type *default-matrix-element-type*))
+   (make-matrix (matrix-row-number x)
+                (matrix-column-number y)
+                :element-type element-type))
+
+  (:method ((x matrix) (y array)
+            &optional (element-type *default-matrix-element-type*))
+   (make-matrix (matrix-row-number x)
+                (matrix-column-number y)
+                :element-type element-type))
+
+  (:method ((x vector) (y matrix)
+            &optional (element-type *default-matrix-element-type*))
+   (make-matrix 1
+                (matrix-column-number y)
+                :element-type element-type))
+
+  (:method ((x matrix) (y vector)
+            &optional (element-type *default-matrix-element-type*))
+   (make-matrix (matrix-row-number x)
+                1
+                :element-type element-type)))
+
+
+
+(defgeneric conforming-*-dimensions-p (x y r)
+  (:documentation
+   "Checks whether the dimensions of R are correct to hold XxY.")
+
+  (:method ((x t) (y t) (r t))
+   (error "Result object is not a matrix: ~S." r))
+
+  ;; 1. Matrix results.
+
+  ;; 1.1. Number methods.
+
+  (:method ((x number) (y matrix) (r matrix))
+   (shape-equal-p y r))
+
+  (:method ((x number) (y array) (r matrix))
+   (shape-equal-p y r))
+
+  (:method ((y matrix) (x number) (r matrix))
+   (conforming-*-dimensions-p x y r))
+
+  (:method ((y array) (x number) (r matrix))
+   (conforming-*-dimensions-p x y r))
+
+  ;; 1.2. Matrix and Array arguments.
+
+  (:method ((x array) (y array) (r matrix))
+   (and (matrix-array-p x)
+        (matrix-array-p y)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+  (:method ((x vector) (y array) (r matrix))
+   (and (matrix-array-p y)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+
+  (:method ((x array) (y vector) (r matrix))
+   (and (matrix-array-p x)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+  (:method ((x matrix) (y matrix) (r matrix))
+   (conforming-*-dimensions-p (matrix-data x) (matrix-data y) r))
+
+  (:method ((x array) (y matrix) (r matrix))
+   (conforming-*-dimensions-p x (matrix-data y) r))
+
+  (:method ((x matrix) (y array) (r matrix))
+   (conforming-*-dimensions-p (matrix-data x) y r))
+
+
+  ;; 2.  Array results.
+
+  ;; 2.1. Number methods.
+
+  (:method ((x number) (y matrix) (r array))
+   (shape-equal-p y r))
+
+  (:method ((x number) (y array) (r array))
+   (shape-equal-p y r))
+
+  (:method ((y matrix) (x number) (r array))
+   (conforming-*-dimensions-p x y r))
+
+  (:method ((y array) (x number) (r array))
+   (conforming-*-dimensions-p x y r))
+
+  ;; 2.2. Matrix and Array arguments.
+
+  (:method ((x array) (y array) (r array))
+   (and (matrix-array-p x)
+        (matrix-array-p y)
+        (matrix-array-p r)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+  (:method ((x vector) (y array) (r array))
+   (and (matrix-array-p y)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+  (:method ((x array) (y vector) (r array))
+   (and (matrix-array-p x)
+        (cl:= (matrix-row-number x) (matrix-column-number y))
+        (cl:= (matrix-row-number x) (matrix-row-number r))
+        (cl:= (matrix-column-number y) (matrix-column-number r))))
+
+  (:method ((x matrix) (y matrix) (r array))
+   (conforming-*-dimensions-p (matrix-data x) (matrix-data y) r))
+
+  (:method ((x array) (y matrix) (r array))
+   (conforming-*-dimensions-p x (matrix-data y) r))
+
+  (:method ((x matrix) (y array) (r array))
+   (conforming-*-dimensions-p (matrix-data x) y r))
+
+  ;; 3. Other methods.
+
+  (:method ((x vector) (y vector) (r t))
+   ;; Maybe a warning here is needed.
+   (cl:= (length x) (length y)))
+  )
+
+
+;;; *%2 Methods.
+
+(defmethod *%2 ((x number) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  (with-slots ((m data)) y
+    (with-slots ((result data)) r
+      (dotimes (i (array-total-size m) r)
+        (setf (row-major-aref result i) (*%2 x (row-major-aref m i))))
+      )))
+
+
+(defmethod *%2 ((y matrix) (x number) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (*%2 x y r))
+
+
+(defmethod *%2 ((x matrix) (y matrix)
+                &optional (r (make-*-result-matrix x y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  ;; X is a NxK matrix
+  ;; Y is a KxM matrix
+  ;; R is a NxM matrix
+  (let* ((m1 (matrix-data x))
+         (m2 (matrix-data y))
+         (result (matrix-data r))
+         (n (array-dimension m1 0))
+         (k (array-dimension m1 1))
+         (m (array-dimension m2 0))
+         (z (coerce 0 (array-element-type result)))
+         )
+    (declare (type fixnum n k m))
+    (dotimes (i n r)
+      (dotimes (j m)
+        (let ((temp z))
+          (dotimes (l k)
+            (setf (aref result i j)
+                  (setf temp (+%2 temp (*%2 (aref m1 i l) (aref m2 l j)))))
+            ))
+        ))))
+
+
+(defmethod *%2 ((x array) (y matrix)
+                &optional (r (make-*-result-matrix x y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  ;; X is a NxK matrix
+  ;; Y is a KxM matrix
+  ;; R is a NxM matrix
+  (let* ((m1 x)
+         (m2 (matrix-data y))
+         (result (matrix-data r))
+         (n (array-dimension m1 0))
+         (k (array-dimension m1 1))
+         (m (array-dimension m2 0))
+         (z (coerce 0 (array-element-type result)))
+         )
+    (declare (type fixnum n k m))
+    (dotimes (i n r)
+      (dotimes (j m)
+        (let ((temp z))
+          (dotimes (l k)
+            (setf (aref result i j)
+                  (incf temp (* (aref m1 i l) (aref m2 l j))))
+            ))
+        ))))
+
+
+(defmethod *%2 ((x matrix) (y array)
+                &optional (r (make-*-result-matrix x y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  ;; X is a NxK matrix
+  ;; Y is a KxM matrix
+  ;; R is a NxM matrix
+  (let* ((m1 (matrix-data x))
+         (m2 y)
+         (result (matrix-data r))
+         (n (array-dimension m1 0))
+         (k (array-dimension m1 1))
+         (m (array-dimension m2 1))
+         (z (coerce 0 (array-element-type result)))
+         )
+    (declare (type fixnum n k m))
+    (dotimes (i n r)
+      (dotimes (j m)
+        (let ((temp z))
+          (dotimes (l k)
+            (setf (aref result i j)
+                  (incf temp (* (aref m1 i l) (aref m2 l j))))
+            ))
+        ))))
+      
+
+(defmethod *%2 ((x vector) (y matrix)
+                &optional (r (make-*-result-matrix x y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  (let* ((m1 x)
+         (m2 (matrix-data y))
+         (result (matrix-data r))
+         (n 1)
+         (k (length m1))
+         (m (array-dimension m2 1))
+         (z (coerce 0 (array-element-type result)))
+         )
+    (declare (type fixnum k m) (type (integer 1 1) n))
+    (dotimes (i n r)
+      (dotimes (j m)
+        (let ((temp z))
+          (dotimes (l k)
+            (setf (aref result i j)
+                  (incf temp (* (aref m1 l) (aref m2 l j))))
+            ))
+        ))))
+
+
+(defmethod *%2 ((x matrix) (y vector)
+                &optional (r (make-*-result-matrix x y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  (let* ((m1 y )
+         (m2 (matrix-data x))
+         (result (matrix-data r))
+         (n (array-dimension m1 0))
+         (k (length y))
+         (m k)
+         (z (coerce 0 (array-element-type result)))
+         )
+    (declare (type fixnum n k m))
+    (dotimes (i n r)
+      (dotimes (j m)
+        (let ((temp z))
+          (dotimes (l k)
+            (setf (aref result i j)
+                  (incf temp (* (aref m1 l) (aref m2 l j))))
+            ))
+        ))))
+
+
+(defmethod *%2 ((x number) (y array) &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (conforming-*-dimensions-p x y r)))
+  (let ((m y)
+        (result r)
+        )
+    (dotimes (i (array-total-size m) r)
+      (setf (row-major-aref result i) (*%2 x (row-major-aref m i))))
+    ))
+
+
+(defmethod *%2 ((y array) (x number) &optional (r (copy-matrix y) r-supplied-p))
+  (*%2 x y r))
+
+
+;;; The next one breaks the return type convention.
+#| Defined in 'vector.lisp'.
+(defmethod *%2 ((x vector) (y vector) &optional r)
+  (declare (ignore r))
+  (assert (conforming-*-dimensions-p x y nil))
+  (let ((result 0))
+    (dotimes (i (length x) result)
+      (setf result (+%2 result (* (aref x i) (aref y i)))))))
+|#
+
+
+;;;---------------------------------------------------------------------------
+;;; Division.
+;;; Only the simple form of division is implemented here.
+;;; The general form requires the inverse, which requires extra machinery
+
+(defmethod /%2 ((x number) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (*%2 (/ x) y r))
+
+
+(defmethod /%2 ((y matrix) (x number) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (*%2 (/ x) y r))
+
+
+;;;---------------------------------------------------------------------------
+;;; Exponentiation.
+;;; ... missing ...
+
+
+;;;---------------------------------------------------------------------------
+;;; Element-wise operations.
+
+(defmethod .*%2 ((x number) (y matrix)
+                 &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (shape-equal-p y r)))
+  (with-slots (data) y
+    (with-slots ((result data)) r
+      (dotimes (i (array-total-size data) r)
+        (setf (row-major-aref result i) (*%2 x (row-major-aref data i))))
+      )))
+
+
+(defmethod .*%2 ((y matrix) (x number) &optional (r (copy-matrix y)))
+  (.*%2 x y r))
+
+
+(defmethod .*%2 ((x number) (y array)
+                 &optional (r (copy-matrix y) r-supplied-p))
+  (assert (matrix-array-p y))
+  (when r-supplied-p (assert (shape-equal-p y r)))
+  (let* ((data y)
+         (result r)
+         )
+    (dotimes (i (array-total-size data) r)
+      (setf (row-major-aref result i) (*%2 x (row-major-aref data i))))
+    ))
+
+
+(defmethod .*%2 ((y array) (x number) &optional (r (copy-matrix y)))
+  (.*%2 x y r))
+
+
+
+(defmethod .*%2 ((x array) (y array) &optional (r (copy-matrix y) r-supplied-p))
+  (when r-supplied-p (assert (shape-equal-p y r)))
+  (assert (shape-equal-p x y))
+
+  (dotimes (i (array-total-size y) r)
+    (setf (row-major-aref r i)
+          (*%2 (row-major-aref x i) (row-major-aref y i)))))
+
+
+;;;---------------------------------------------------------------------------
+;;; Transpose
+
+(defgeneric conforming-transpose-dimensions-p (x r)
+  (:documentation
+   "Checks whether the dimensions of R are correct to hold X'.")
+
+  (:method ((x t) (r t))
+   (error "Result object is not a matrix: ~S." r))
+
+  ;; 1. Matrix results.
+
+  (:method ((x array) (r matrix))
+   (and (matrix-array-p x)
+        (cl:= (matrix-row-number x) (matrix-column-number r))
+        (cl:= (matrix-column-number x) (matrix-row-number r))))
+
+  (:method ((x matrix) (r matrix))
+   (and (cl:= (matrix-row-number x) (matrix-column-number r))
+        (cl:= (matrix-column-number x) (matrix-row-number r))))
+
+
+  ;; 2.  Array results.
+
+  (:method ((x array) (r array))
+   (and (matrix-array-p x)
+        (matrix-array-p r)
+        (cl:= (matrix-row-number x) (matrix-column-number r))
+        (cl:= (matrix-column-number x) (matrix-row-number r))))
+
+  (:method ((x matrix) (r array))
+  (and (matrix-array-p r)
+       (cl:= (matrix-row-number x) (matrix-column-number r))
+       (cl:= (matrix-column-number x) (matrix-row-number r))))
+  )
+
+
+
+(defmethod transpose ((m matrix)
+                      &optional
+                      (r (make-matrix (matrix-column-number m)
+                                      (matrix-row-number m)
+                                      :element-type
+                                      (matrix-element-type m))
+                         r-supplied-p))
+  (when r-supplied-p (assert (conforming-transpose-dimensions-p m r)))
+  (let ((rows (matrix-row-number m))
+        (cols (matrix-column-number m))
+        (m (matrix-data m))
+        (result (matrix-data r))
+        )
+    (dotimes (i rows r)
+      (dotimes (j cols)
+        (setf (aref result j i) (aref m i j))))))
+
+
+(defmethod transpose ((m array)
+                      &optional
+                      (r (make-array (array-dimensions m)
+                                     :element-type
+                                     (array-element-type m)
+                                     )
+                         r-supplied-p))
+  (when r-supplied-p (assert (conforming-transpose-dimensions-p m r)))
+  (let ((rows (matrix-row-number m))
+        (cols (matrix-column-number m))
+        )
+    (dotimes (i rows r)
+      (dotimes (j cols)
+        (setf (aref r j i) (aref m i j))))))
+
+
+(defmethod transpose :before ((m array) &optional r)
+  (declare (ignore r))
+  (assert (matrix-array-p m)))
+
+
+;;;---------------------------------------------------------------------------
+;;; Utilities.
+
+#+simple
+(defmethod print-object ((m matrix) stream)
+  (print-unreadable-object (m stream :identity t :type t)
+    (format stream "~S" (matrix-data m))))
+
+
+(defmethod print-object ((m matrix) stream)
+  (let ((d (matrix-data m)))
+    (format stream "#M(~S ~S ~S)"
+            (array-element-type d)
+            (array-dimensions d)
+            d)))
+
+;;; Missing:
+;;; Define #M read macro.
+
+
+;;;; end of file -- matrix.lisp --

Added: trunk/common-math/numerics/linear-algebra/vector-matrix-conditions.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/vector-matrix-conditions.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,27 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; vector-matrix-conditions.lisp --
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+;;;---------------------------------------------------------------------------
+;;; Conditions relative to the vectors and matrix subsystem..
+
+(define-condition incompatible-shapes (error)
+  ((a :accessor incompatible-shape-a
+      :initarg :a)
+   (b :accessor incompatible-shape-b
+      :initarg :b)
+   )
+  (:documentation "The Incompatible Shapes Error.
+This error is signalled by functions that get arguments -- mainly
+matrices and/or vectors -- whose 'shape' is not compatible with
+respect to the semantics of the operation.")
+
+  (:report (lambda (isc stream)
+             (declare (ignore isc))
+             (format stream "The shapes passed have incompatible dimensions.")))
+  )
+  
+
+;;;; end of file -- vector-matrix-conditions.lisp --

Added: trunk/common-math/numerics/linear-algebra/vector-matrix.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/vector-matrix.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,613 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; vector-matrix.lisp --
+;;;; Protocols and functions common to and dependent on vector and matrix
+;;;; definitions.
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+;;;;===========================================================================
+;;;; Protocol.
+
+;;; join and stack
+;;; Note: no 'result' machinery in place yet.
+
+(defgeneric join%2 (d1 d2))
+
+(defgeneric stack%2 (d1 d2))
+
+
+;;; slice
+
+(defgeneric slice (e shape-designator))
+
+
+;;; range
+
+(defstruct (range (:constructor %range (start &optional end step)))
+  (start 0 :type (or fixnum (member * cl:*)))
+  (end nil :type (or null fixnum (member * cl:*)))
+  (step 1 :type fixnum))
+
+
+(defstruct (decreasing-range (:include range)))
+
+(defstruct (increasing-range (:include range)))
+
+
+(defun range (start &optional end (step 1))
+  (if end
+      (if (<= start end)
+          (make-increasing-range :start start :end end :step step)
+          (make-decreasing-range :start start :end end :step step))
+      (if (plusp step)
+          (make-increasing-range :start start :end end :step step)
+          (make-decreasing-range :start start :end end :step step))
+      ))
+
+
+
+;;; ref
+
+(defgeneric ref (e index &rest indexes))
+
+(defgeneric ref%2 (e i j))
+
+
+;;;---------------------------------------------------------------------------
+;;; Implementation.
+
+;;; join%2 --
+
+(defmethod join%2 ((d1 vector) (d2 vector))
+  (concatenate 'vector d1 d2))
+
+
+(defmethod join%2 ((d1 string) (d2 string))
+  (concatenate 'string d1 d2))
+
+
+(defmethod join%2 ((d1 list) (d2 list))
+  (concatenate 'list d1 d2))
+
+
+(defmethod join%2 ((d1 vector) (d2 sequence))
+  (concatenate 'vector d1 d2))
+
+
+(defmethod join%2 ((d1 sequence) (d2 vector))
+  (concatenate (type-of d1) d1 d2))
+
+
+(defmethod join%2 ((d1 column) (d2 column))
+  (let ((initial-contents
+         (map 'list #'vector (column-vector d1) (column-vector d2))))
+    (declare (dynamic-extent initial-contents))
+    (make-array (list (length (column-vector d1)) 2)
+                :initial-contents initial-contents)))
+
+
+(defmethod join%2 ((d1 vector) (d2 column))
+  (unless (cl:= (length (column-vector d2)) 1)
+    (error "Trying to JOIN a vector (1x~D) to a column (~Dx1)."
+           (length d1)
+           (length (column-vector d2))))
+  (concatenate 'vector d1 (column-vector d2)))
+
+
+(defmethod join%2 ((d1 column) (d2 vector))
+  (unless (cl:= (length (column-vector d1)) 1)
+    (error "Trying to JOIN a column (~Dx1) to a vector (1x~D)."
+           (length (column-vector d1))
+           (length d2)))
+  (concatenate 'vector (column-vector d1) d2))
+
+
+(defmethod join%2 ((d1 column) (d2 array))
+  (let ((nr (array-dimension d2 0)))
+    (assert (cl:= (length (column-vector d1)) nr))
+    (let* ((nc (1+ (array-dimension d2 1)))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d2 0 0)
+                               :element-type (array-element-type d2)))
+           (col (column-vector d1))
+           )
+      (dotimes (i nr result)
+        (setf (aref result i 0) (aref col i))
+        (loop for j from 1 below nc
+              do (setf (aref result i j) (aref d2 i (1- j)))))
+      )))
+
+
+(defmethod join%2 ((d1 array) (d2 column))
+  (let ((nr (array-dimension d1 0)))
+    (assert (cl:= (length (column-vector d2)) nr))
+    (let* ((nc (1+ (array-dimension d1 1)))
+           (nc-1 (1- nc))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d1 0 0)
+                               :element-type (array-element-type d1)))
+           (col (column-vector d2))
+           )
+
+      (dotimes (i nr result)
+        (setf (aref result i nc-1) (aref col i))
+        (dotimes (j nc-1)
+          (setf (aref result i j) (aref d1 i j))))
+      )))
+
+
+(defmethod join%2 ((d1 array) (d2 array))
+  (let ((nr1 (array-dimension d1 0))
+        (nr2 (array-dimension d2 0))
+        )
+    (assert (cl:= nr1 nr2))
+    (let* ((nc1 (array-dimension d1 1))
+           (nc2 (array-dimension d2 1))
+           (result (make-array (list nr1 (+ nc1 nc2))
+                               :initial-element (aref d1 0 0)
+                               :element-type (array-element-type d1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref d1 i j))))
+
+      (dotimes (i nr2 result)
+        (dotimes (j nc2)
+          (setf (aref result i (+ j nc1)) (aref d2 i j))))
+      )))
+
+
+(defmethod join%2 ((d1 matrix) (d2 matrix))
+  (let ((nr1 (matrix-row-number d1))
+        (nr2 (matrix-row-number d2))
+        )
+    (assert (cl:= nr1 nr2))
+    (let* ((nc1 (matrix-column-number d1))
+           (nc2 (matrix-column-number d2))
+           (data1 (matrix-data d1))
+           (data2 (matrix-data d2))
+           (result (make-array (list nr1 (+ nc1 nc2))
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result i (+ j nc1)) (aref data2 i j))))
+      )))
+
+
+(defmethod join%2 ((d1 array) (d2 matrix))
+  (let ((nr1 (matrix-row-number d1))
+        (nr2 (matrix-row-number d2))
+        )
+    (assert (cl:= nr1 nr2))
+    (let* ((nc1 (matrix-column-number d1))
+           (nc2 (matrix-column-number d2))
+           (data1 d1)
+           (data2 (matrix-data d2))
+           (result (make-array (list nr1 (+ nc1 nc2))
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result i (+ j nc1)) (aref data2 i j))))
+      )))
+
+
+(defmethod join%2 ((d1 matrix) (d2 array))
+  (let ((nr1 (matrix-row-number d1))
+        (nr2 (matrix-row-number d2))
+        )
+    (assert (cl:= nr1 nr2))
+    (let* ((nc1 (matrix-column-number d1))
+           (nc2 (matrix-column-number d2))
+           (data1 (matrix-data d1))
+           (data2 d2)
+           (result (make-array (list nr1 (+ nc1 nc2))
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result i (+ j nc1)) (aref data2 i j))))
+      )))
+
+
+(defmethod join%2 ((d1 vector) (d2 matrix))
+  (let ((result (join%2 d1 (matrix-data d2))))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod join%2 ((d2 matrix) (d1 vector))
+  (let ((result (join%2 (matrix-data d2) d1)))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod join%2 ((d1 column) (d2 matrix))
+  (let ((result (join%2 d1 (matrix-data d2))))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod join%2 ((d2 matrix) (d1 column))
+  (let ((result (join%2 (matrix-data d2) d1)))
+    (make-instance 'matrix :data result)))
+
+
+;;; stack%2 --
+
+(defmethod stack%2 ((d1 column) (d2 column))
+  (column (concatenate 'vector (column-vector d1) (column-vector d2))))
+
+
+(defmethod stack%2 ((d1 vector) (d2 array))
+  (let ((nc (array-dimension d2 1)))
+    (assert (cl:= (length d1) nc))
+    (let* ((nr (1+ (array-dimension d2 0)))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d2 0 0)
+                               :element-type (array-element-type d2)))
+           )
+      (dotimes (i nc)
+        (setf (aref result 0 i) (aref d1 i)))
+      (loop for i from 1 below nr
+            do (dotimes (j nc)
+                 (setf (aref result i j) (aref d2 (1- i) j))))
+      result)))
+
+
+(defmethod stack%2 ((d1 sequence) (d2 array))
+  (let ((nc (array-dimension d2 1)))
+    (assert (cl:= (length d1) nc))
+    (let* ((nr (1+ (array-dimension d2 0)))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d2 0 0)
+                               :element-type (array-element-type d2)))
+           )
+      (dotimes (i nc)
+        (setf (aref result 0 i) (elt d1 i)))
+      (loop for i from 1 below nr
+            do (dotimes (j nc)
+                 (setf (aref result i j) (aref d2 (1- i) j))))
+      result)))
+
+
+(defmethod stack%2 ((d1 array) (d2 vector))
+  (let ((nc (array-dimension d1 1)))
+    (assert (cl:= (length d2) nc))
+    (let* ((nr (1+ (array-dimension d1 0)))
+           (nr-1 (1- nr))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d1 0 0)
+                               :element-type (array-element-type d1)))
+           )
+
+      (dotimes (i nr-1)
+        (dotimes (j nc)
+          (setf (aref result i j) (aref d1 i j))))
+      (dotimes (i nc)
+        (setf (aref result nr-1 i) (aref d2 i)))
+      result)))
+
+
+(defmethod stack%2 ((d1 array) (d2 sequence))
+  (let ((nc (array-dimension d1 1)))
+    (assert (cl:= (length d2) nc))
+    (let* ((nr (1+ (array-dimension d1 0)))
+           (nr-1 (1- nr))
+           (result (make-array (list nr nc)
+                               :initial-element (aref d1 0 0)
+                               :element-type (array-element-type d1)))
+           )
+
+      (dotimes (i nr-1)
+        (dotimes (j nc)
+          (setf (aref result i j) (aref d1 i j))))
+      (dotimes (i nc)
+        (setf (aref result nr-1 i) (elt d2 i)))
+      result)))
+
+
+(defmethod stack%2 ((d1 array) (d2 array))
+  (let ((nc1 (array-dimension d1 1))
+        (nc2 (array-dimension d2 1))
+        )
+    (assert (cl:= nc1 nc2))
+    (let* ((nr1 (array-dimension d1 0))
+           (nr2 (array-dimension d2 0))
+           (result (make-array (list (+ nr1 nr2) nc1)
+                               :initial-element (aref d1 0 0)
+                               :element-type (array-element-type d1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref d1 i j))))
+
+      (dotimes (i nr2 result)
+        (dotimes (j nc2)
+          (setf (aref result (+ i nr1) j) (aref d2 i j))))
+      )))
+
+
+(defmethod stack%2 ((d1 matrix) (d2 matrix))
+  (let ((nc1 (matrix-column-number d1))
+        (nc2 (matrix-column-number d2))
+        )
+    (assert (cl:= nc1 nc2))
+    (let* ((nr1 (matrix-row-number d1))
+           (nr2 (matrix-row-number d2))
+           (data1 (matrix-data d1))
+           (data2 (matrix-data d2))
+           (result (make-array (list (+ nr1 nr2) nc1)
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result (+ i nr1) j) (aref data2 i j))))
+      )))
+
+
+(defmethod stack%2 ((d1 array) (d2 matrix))
+  (let ((nc1 (matrix-column-number d1))
+        (nc2 (matrix-column-number d2))
+        )
+    (assert (cl:= nc1 nc2))
+    (let* ((nr1 (matrix-row-number d1))
+           (nr2 (matrix-row-number d2))
+           (data1 d1)
+           (data2 (matrix-data d2))
+           (result (make-array (list (+ nr1 nr2) nc1)
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result (+ i nr1) j) (aref data2 i j))))
+      )))
+
+
+
+(defmethod stack%2 ((d1 matrix) (d2 array))
+  (let ((nc1 (matrix-column-number d1))
+        (nc2 (matrix-column-number d2))
+        )
+    (assert (cl:= nc1 nc2))
+    (let* ((nr1 (matrix-row-number d1))
+           (nr2 (matrix-row-number d2))
+           (data1 (matrix-data d1))
+           (data2 d2)
+           (result (make-array (list (+ nr1 nr2) nc1)
+                               :initial-element (aref data1 0 0)
+                               :element-type (array-element-type data1)))
+           )
+
+      (dotimes (i nr1)
+        (dotimes (j nc1)
+          (setf (aref result i j) (aref data1 i j))))
+
+      (dotimes (i nr2 (make-instance 'matrix :data result))
+        (dotimes (j nc2)
+          (setf (aref result (+ i nr1) j) (aref data2 i j))))
+      )))
+
+
+(defmethod stack%2 ((d1 vector) (d2 matrix))
+  (let ((result (stack%2 d1 (matrix-data d2))))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod stack%2 ((d2 matrix) (d1 vector))
+  (let ((result (stack%2 (matrix-data d2) d1)))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod stack%2 ((d1 column) (d2 matrix))
+  (let ((result (stack%2 d1 (matrix-data d2))))
+    (make-instance 'matrix :data result)))
+
+
+(defmethod stack%2 ((d2 matrix) (d1 column))
+  (let ((result (stack%2 (matrix-data d2) d1)))
+    (make-instance 'matrix :data result)))
+
+
+;;; slice --
+#|
+(defmethod slice ((v vector) (x fixnum))
+  (aref v x))
+
+
+(defmethod slice ((v vector) (sd list))
+  (assert (<= (list-length sd) 2))
+  (destructuring-bind (start &optional end)
+      sd
+    (let ((start (cond ((or (eq start '*) (eq start 'cl:*)) 0)
+                       ((typep start `(mod ,array-total-size-limit)) start)
+                       (t (error "Unrecognized start ~S in slice designator."
+                                 start))))
+          (end (cond ((or (null end) (eq end '*) (eq end 'cl:*)) nil)
+                     ((typep end `(mod ,array-total-size-limit)) end)
+                     (t  (error "Unrecognized end ~S in slice designator."
+                                 end))))
+          )
+      (subseq v start end))))
+
+
+(defmethod slice ((v column) (sd list))
+  (column (slice (column-vector v) sd)))
+
+
+(defmethod slice ((v vector) (sd (eql '*)))
+  (copy-vector v))
+
+
+(defmethod slice ((v vector) (sd (eql 'cl:*)))
+  (copy-vector v))
+
+
+(defmethod slice ((v column) (sd (eql '*)))
+  (copy-vector v))
+
+
+(defmethod slice ((v column) (sd (eql 'cl:*)))
+  (copy-vector v))
+
+
+(defmethod slice (()))
+                      |#   
+    
+
+
+;;; ref --
+
+(defmethod ref ((v vector) (i fixnum) &rest indexes)
+  (when indexes
+    (error "REF of a vector requires only one index but ~D were supplied."
+           (1+ (list-length indexes))))
+
+
+  (aref v i))
+
+
+(defmethod ref ((v vector) (i increasing-range) &rest indexes)
+  (when indexes
+    (error "REF of a vector requires only one index or range but a range and ~D indexes were supplied."
+           (list-length indexes)))
+
+  (loop for vi from (range-start i)
+        below (or (range-end i) (length v))
+        by (range-step i)
+        collect (aref v vi) into vs
+        finally (return (coerce vs 'vector))))
+
+
+(defmethod ref ((v vector) (i decreasing-range) &rest indexes)
+  (when indexes
+    (error "REF of a vector requires only one index or range but a range and ~D indexes were supplied."
+           (list-length indexes)))
+
+  (loop for vi from (or (range-end i) (1- (length v)))
+        downto (range-start i)
+        by (abs (range-step i))
+        collect (aref v vi) into vs
+        finally (return (coerce vs 'vector))))
+
+
+(defmethod ref ((v vector) (i vector) &rest indexes)
+  (when indexes
+    (error "REF of a vector requires only one index or subset but a subset and ~D indexes were supplied."
+           (list-length indexes)))
+
+  (loop for x across i
+        collect (aref v x) into vs
+        finally (return (coerce vs 'vector))))
+
+
+(defmethod ref ((v vector) (i list) &rest indexes)
+  (when indexes
+    (error "REF of a vector requires only one index or subset but a subset and ~D indexes were supplied."
+           (list-length indexes)))
+
+  (loop for x in i
+        collect (aref v x) into vs
+        finally (return (coerce vs 'vector))))
+
+
+(defmethod ref ((v column) (i fixnum) &rest indexes)
+  (apply #'ref (column-vector v) i indexes))
+
+
+(defmethod ref ((v column) (i range) &rest indexes)
+  (column (apply #'ref (column-vector v) i indexes)))
+
+
+(defmethod ref ((v column) (i vector) &rest indexes)
+  (column (apply #'ref (column-vector v) i indexes)))
+
+
+(defmethod ref ((v column) (i list) &rest indexes)
+  (column (apply #'ref (column-vector v) i indexes)))
+
+
+(defmethod ref ((m matrix) (i t) &rest indexes)
+  (when (cl:/= 1 (list-length indexes))
+    (error "........"))
+
+  (ref%2 m i (first indexes)))
+
+    
+
+(defmethod ref%2 ((m matrix) (i fixnum) (j fixnum))
+  (aref (matrix-data m) i j))
+
+
+(defmethod ref%2 ((m matrix) (i fixnum) (j vector))
+  (loop with md = (matrix-data m)
+        for x across j
+        collecting (aref md i x) into result
+        finally return (coerce result 'vector)))
+
+
+(defmethod ref%2 ((m matrix) (i vector) (j fixnum))
+  (loop with md = (matrix-data m)
+        for x across i
+        collecting (aref md x j) into result
+        finally return (coerce result 'vector)))
+
+
+(defmethod ref%2 ((m matrix) (i vector) (j vector))
+  (loop with md = (matrix-data m)
+        for x across i
+        collecting (loop for y across j
+                         collecting (aref md x y))
+        into result
+        finally
+        (return (make-instance 'matrix
+                               :data (make-array (list (length i)
+                                                       (length j))
+                                                 :initial-contents result)))))
+
+
+           
+
+
+;;;;===========================================================================
+;;;; Generic Interface Functions.
+
+(defun join (&rest elements)
+  (cl:reduce #'join%2 elements))
+
+
+(defun stack (&rest elements)
+  (cl:reduce #'stack%2 elements))
+
+;;;; end of file -- vector-matrix.lisp --

Added: trunk/common-math/numerics/linear-algebra/vector.lisp
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/linear-algebra/vector.lisp	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,461 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; vector.lisp --
+;;;; There is no wrapper for vectors, but we do have a class (struct)
+;;;; for 'column' vectors.
+;;;; Apart from that there are some specialized generic functions on
+;;;; vectors.
+
+(in-package "CL.MATH.LINEAR-ALGEBRA")
+
+(defparameter *default-vector-element-type* 'double-float)
+
+
+(deftype column-array (&optional (type 'cl:number) (length 'cl:*))
+  `(array ,type (,length 1)))
+
+
+(defstruct (column (:constructor column (vector)))
+  "The Column Structure.
+A representation for `column' vectors."
+  (vector #() :type (or list vector)))
+
+
+(defmethod print-object ((c column) (s stream))
+  (format s "(~S ~S)" 'column (column-vector c)))
+
+
+;;;---------------------------------------------------------------------------
+;;; Protocol.
+
+(defgeneric vector-p (v)
+  (:method ((v vector)) t)
+  (:method ((v column)) t)
+  (:method ((v t)) nil)
+  )
+
+
+(defgeneric vector-element-type (v)
+  (:method ((v vector)) (array-element-type v))
+  (:method ((v column)) (array-element-type (column-vector v)))
+  )
+
+
+(defgeneric vector-length (m)
+  (:method ((x vector)) (length x))
+  (:method ((x column)) (length (column-vector x)))
+  )
+
+
+;;;---------------------------------------------------------------------------
+;;; Creation.
+
+(defun make-vector (n
+                    &rest array-keys
+                    &key
+                    (element-type *default-vector-element-type*)
+                    (column-p nil)
+                    &allow-other-keys
+                    )
+  (remf array-keys :column-p)
+  (let ((new-v (apply #'make-array n
+                      (append array-keys
+                              (list :initial-element (coerce 0 element-type)
+                                    :element-type
+                                    element-type)))))
+    (if column-p
+        (column new-v)
+        new-v)))
+
+
+(defun make-zero-vector (n
+                         &rest array-keys
+                         &key
+                         (element-type *default-matrix-element-type*)
+                         &allow-other-keys)
+  (when (getf array-keys :initial-element)
+    (warn "MAKE-ZERO-MATRIX passed and :INITIAL-ELEMENT argument.")
+    (remf array-keys :initial-element))
+  (apply #'make-vector
+                      n
+                      (append array-keys
+                              (list :initial-element (coerce 0 element-type)
+                                    :element-type element-type))))
+
+
+;;;---------------------------------------------------------------------------
+;;; copy-vector
+;;; Uses the code from K Pitman and B. Margolin appeared on CLL a long
+;;; long time ago.
+;;; Note that at least on LW this code has some of the usual problems
+;;; with DOUBLE-FLOATS.
+#|
+(defun copy-array (array)
+  (adjust-array (make-array (array-dimensions array)
+			    :displaced-to array
+			    :element-type (array-element-type array))
+		(array-dimensions array)
+		:displaced-to nil))
+|#
+
+(defgeneric copy-vector (v)
+  (:documentation "Returns a (shallow) copy of vector V.
+The effect are the same as CL:COPY-SEQ for CL vectors while columns
+are treated accordingly."))
+
+
+(defmethod copy-vector ((v vector))
+  "COPY-VECTOR method for VECTORs." 
+  (cl:copy-seq v))
+
+
+(defmethod copy-vector ((v column))
+  "COPY-VECTOR method for COLUMN vectors."
+  (column (cl:copy-seq (column-vector v))))
+
+
+(defmethod copy-vector ((v array))
+  (check-type v column-array)
+  (adjust-array (make-array (array-dimensions v)
+			    :displaced-to v
+			    :element-type (array-element-type v))
+		(array-dimensions v)
+		:displaced-to nil))
+  
+
+
+#|
+(defmethod copy-vector ((v vector)
+                        &optional
+                        (result
+                         (adjust-array
+                          (make-array (length v)
+                                      :displaced-to v
+                                      :element-type (array-element-type v))
+                          (array-dimensions v)
+                          :displaced-to nil)
+                         result-supplied-p))
+  "COPY-VECTOR method for VECTORs." 
+  (when result-supplied-p
+    (assert (vector-p result))
+    (assert (cl:= (length result) (vector-length v)))
+    (map-into result #'identity v))
+  result)
+
+
+(defmethod copy-vector ((c column)
+                        &optional
+                        (result
+                         (let ((v (column-vector c)))
+                           (column
+                            (adjust-array
+                             (make-array (length v)
+                                         :displaced-to v
+                                         :element-type (array-element-type v))
+                             (array-dimensions v)
+                             :displaced-to nil)))
+                         result-supplied-p))
+  "COPY-VECTOR method for COLUMN vectors."
+  (when result-supplied-p
+    (assert (column-p result))
+    (assert (cl:= (vector-length result) (vector-length c)))
+    (map-into (column-vector result) #'identity (column-vector c)))
+  result)
+|#
+
+
+
+;;;---------------------------------------------------------------------------
+;;; Equality.
+
+(defmethod =%2 ((x vector) (y vector))
+  (and (cl:= (length x) (length y))
+       (every #'=%2 x y)))
+
+
+(defmethod =%2 ((x vector) (y column))
+  (and (or (= 1 (length x) (vector-length y)) ; Only cases when this may happen.
+           (= 0 (length x) (vector-length y)))
+       (=%2 x (column-vector y))))
+
+
+(defmethod =%2 ((y column) (x vector))
+  (=%2 x y))
+
+
+;;;---------------------------------------------------------------------------
+;;; zerop
+
+(defmethod zerop ((x vector))
+  (cl:every #'zerop x))
+
+
+(defmethod zerop ((x column))
+  (cl:every #'zerop (column-vector x)))
+
+
+;;;---------------------------------------------------------------------------
+;;; Addition.
+
+(defmethod +%2 :before ((x vector) (y vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (unless (eq y r)
+    (let ((xl (length x)))
+      (assert (cl:= xl (length y)))
+      (when r-supplied-p
+        (assert (vector-p r))
+        (assert (cl:= xl (vector-length r)))
+        ))))
+
+
+(defmethod +%2 :before ((x vector) (y column)
+                        &optional
+                        (r nil r-supplied-p))
+  (declare (ignore r r-supplied-p))
+  (assert (or (cl:= 1 (length x) (vector-length y))
+              (cl:= 0 (length x) (vector-length y))))
+  )
+
+
+(defmethod +%2 :before ((y column) (x vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (declare (ignore r r-supplied-p))
+  (assert (or (cl:= 1 (length x) (vector-length y))
+              (cl:= 0 (length x) (vector-length y))))
+  )
+
+
+(defmethod +%2 :before ((x number) (y vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (unless (eq y r)
+    (when r-supplied-p
+      (assert (vector-p r))
+      (assert (cl:= (length y) (vector-length r)))
+      )))
+
+
+(defmethod +%2 ((x number) (y vector) &optional (r (copy-vector y)))
+  (dotimes (i (length y) r)
+    (setf (aref r i) (+%2 x (aref y i)))))
+
+
+(defmethod +%2 ((y vector) (x number) &optional (r (copy-vector y)))
+  (+%2 x y r))
+
+
+(defmethod +%2 ((x vector) (y vector) &optional (r (copy-vector y)))
+  (dotimes (i (length x) r)
+    (setf (aref r i) (+%2 (aref x i) (aref y i)))))
+
+
+(defmethod +%2 ((x vector) (y column)
+                &optional (r (copy-vector (column-vector y))))
+  ;; This is valid only for vectors and columns of length 1 (or 0).
+  (+%2 x (column-vector y) r))
+
+
+(defmethod +%2 ((x column) (y vector) &optional (r (copy-vector y)))
+  ;; This is valid only for vectors and columns of length 1 (or 0).
+  (+%2 (column-vector x) y r))
+
+
+;;;---------------------------------------------------------------------------
+;;; Subtraction.
+
+(defmethod -%2 :before ((x vector) (y vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (let ((xl (length x)))
+    (assert (cl:= xl (length y)))
+    (when r-supplied-p
+      (assert (vector-p r))
+      (assert (cl:= xl (vector-length r)))
+      )))
+
+
+(defmethod -%2 :before ((x vector) (y column)
+                        &optional
+                        (r nil r-supplied-p))
+  (declare (ignore r r-supplied-p))
+  (assert (or (cl:= 1 (length x) (vector-length y))
+              (cl:= 0 (length x) (vector-length y))))
+  )
+
+
+(defmethod -%2 :before ((y column) (x vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (declare (ignore r r-supplied-p))
+  (assert (or (cl:= 1 (length x) (vector-length y))
+              (cl:= 0 (length x) (vector-length y))))
+  )
+
+
+(defmethod -%2 :before ((x number) (y vector)
+                        &optional
+                        (r nil r-supplied-p))
+  (unless (eq y r)
+    (when r-supplied-p
+      (assert (vector-p r))
+      (assert (cl:= (length y) (vector-length r)))
+      )))
+
+
+(defmethod -%2 ((x vector) (y vector) &optional (r (copy-vector y)))
+  (dotimes (i (length x) r)
+    (setf (aref r i) (-%2 (aref x i) (aref y i)))))
+
+
+
+(defmethod -%2 ((x vector) (y column)
+                &optional (r (copy-vector (column-vector y))))
+  ;; This is valid only for vectors and columns of length 1 (or 0).
+  (-%2 x (column-vector y) r))
+
+
+(defmethod -%2 ((x column) (y vector) &optional (r (copy-vector y)))
+  ;; This is valid only for vectors and columns of length 1 (or 0).
+  (-%2 (column-vector x) r r))
+
+
+;;;---------------------------------------------------------------------------
+;;; Multiplication.
+;;; Note that left and right multiplications are different!
+;;; They follow the matrix multiplication rules.
+;;; Here we treat only the vector x column multiplication as the
+;;; column x vector has a matrix as a result.
+
+(defmethod *%2 :before ((x vector) (y column) &optional r)
+  (declare (ignore r))
+  (assert (cl:= (cl:length x) (vector-length y))))
+
+
+(defmethod *%2 ((x vector) (y column) &optional r)
+  (declare (ignore r))
+  (let ((result (coerce 0 (array-element-type x)))
+        (y (column-vector y))
+        )
+    (dotimes (i (cl:length x) result)
+      (setf result (+%2 result (*%2 (aref x i) (aref y i)))))
+    ))
+
+;;; The next one breaks the correct semantics passing of arguments,
+;;; but it is provided as a convenience.
+
+(defmethod *%2 ((x vector) (y vector) &optional r)
+  (declare (ignore r))
+  (assert (cl:= (cl:length x) (cl:length y)))
+  (let ((result (coerce 0 (array-element-type x))))
+    (dotimes (i (cl:length x) result)
+      (setf result (+%2 result (*%2 (aref x i) (aref y i)))))))
+
+
+;;; Scalar multiplication.
+
+(defmethod *%2 :before ((x number) (v vector) &optional (r nil r-supplied-p))
+  (when r-supplied-p
+    (assert (cl:vectorp r))
+    (assert (cl:= (cl:length v) (vector-length r)))))
+
+
+(defmethod *%2 :before ((x number) (v column) &optional (r nil r-supplied-p))
+  (when r-supplied-p
+    (assert (column-p r))
+    (assert (cl:= (vector-length v) (vector-length r)))))
+
+
+(defmethod *%2 ((x number) (v vector) &optional (r (copy-vector v)))
+  (map-into r (lambda (e) (*%2 x e)) v))
+
+
+(defmethod *%2 ((v vector) (x number) &optional (r (copy-vector v)))
+  (map-into r (lambda (e) (*%2 x e)) v))
+
+
+(defmethod *%2 ((x number) (v column) &optional (r (copy-vector v)))
+  (map-into (column-vector r) (lambda (e) (*%2 x e)) v)
+  r)
+
+
+(defmethod *%2 ((v column) (x number) &optional (r (copy-vector v)))
+  (*%2 x v r))
+
+
+;;;---------------------------------------------------------------------------
+;;; Division.
+;;; Only the simple form of division is implemented here.
+;;; The general form requires the inverse, which requires extra machinery
+
+#|
+(defmethod /%2 ((x number) (y matrix) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (*%2 (/ x) y r))
+
+
+(defmethod /%2 ((y matrix) (x number) &optional (r (copy-matrix y) r-supplied-p))
+  (declare (ignore r-supplied-p))
+  (*%2 (/ x) y r))
+|#
+
+;;;---------------------------------------------------------------------------
+;;; Exponentiation.
+;;; All errors here ftb.
+
+
+;;;---------------------------------------------------------------------------
+;;; Transpose
+
+(defmethod transpose ((v vector) &optional (r (column (copy-vector v)) r-supplied-p))
+  (if r-supplied-p
+      (map-into (column-vector r) #'identity v))
+      r)
+
+
+(defmethod transpose ((v column)
+                      &optional
+                      (r (copy-vector (column-vector v)) r-supplied-p))
+  (if r-supplied-p
+      (map-into r #'identity (column-vector v))
+      r))
+
+
+(defmethod transpose :before ((v vector) &optional (r nil r-supplied-p))
+  (when r-supplied-p
+    (assert (column-p r))
+    (assert (cl:= (cl:length v) (vector-length r)))))
+
+
+(defmethod transpose :before ((v column) &optional (r nil r-supplied-p))
+  (when r-supplied-p
+    (assert (cl:vectorp r))
+    (assert (cl:= (cl:length r) (vector-length v)))))
+
+
+;;;---------------------------------------------------------------------------
+;;; Other functions.
+
+(defun iota (n &optional (start 0) (step 1 step-supplied-p)
+               &aux (initial-contents ()))
+  (cond ((< n start)
+         (when step-supplied-p (assert (minusp step)))
+         (loop for x from start above n by step
+               collect x into xs
+               finally (setf initial-contents xs)))
+        ((> n start)
+         (when step-supplied-p (assert (plusp step)))
+         (loop for x from start below n by step
+               collect x into xs
+               finally (setf initial-contents xs)))
+        (t ()))
+  (make-array n :initial-contents initial-contents))
+
+
+
+;;;---------------------------------------------------------------------------
+;;; Utilities.
+
+
+;;;; end of file -- matrix.lisp --

Added: trunk/common-math/numerics/numerics.system
==============================================================================
--- (empty file)
+++ trunk/common-math/numerics/numerics.system	Wed Aug 16 17:07:41 2006
@@ -0,0 +1,18 @@
+;;;; -*- Mode: Lisp -*-
+
+;;;; numerics.system --
+
+(mk:defsystem "numerics"
+  :components ((:system "linear-algebra")
+	       )
+  )
+
+
+(eval-when (:load-toplevel :execute)
+  (mk:add-registry-location (make-pathname :name nil
+					   :type nil
+					   :defaults *load-truename*))
+  )
+
+;;;; end of file -- numerics.system --
+



More information about the Common-math-cvs mailing list