From jivestgarden at common-lisp.net Tue Sep 1 10:57:50 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Tue, 01 Sep 2009 06:57:50 -0400 Subject: [lisplab-cvs] r91 - src/matrix Message-ID: Author: jivestgarden Date: Tue Sep 1 06:57:49 2009 New Revision: 91 Log: new function map-into Modified: package.lisp src/matrix/level2-generic.lisp src/matrix/level2-interface.lisp src/matrix/level2-matrix-dge.lisp src/matrix/level2-matrix-zge.lisp Modified: package.lisp ============================================================================== --- package.lisp (original) +++ package.lisp Tue Sep 1 06:57:49 2009 @@ -163,7 +163,8 @@ "MCREATE" "COPY-CONTENTS" - "MMAP" + "MMAP" + "MMAP-INTO" "MFILL" "TO-VECTOR" "TO-MATRIX" Modified: src/matrix/level2-generic.lisp ============================================================================== --- src/matrix/level2-generic.lisp (original) +++ src/matrix/level2-generic.lisp Tue Sep 1 06:57:49 2009 @@ -83,23 +83,24 @@ (apply #'mmap (type-of a) f a args)) (defmethod mmap ((type symbol) f (a matrix-base) &rest args) - (apply #'mmap (find-class type) f a args)) + (apply #'mmap-into (make-matrix-instance type (dim a) 0) f a args)) -(defmethod mmap (type f (a matrix-base) &rest args) - (let ((b (make-matrix-instance type (dim a) 0))) - (cond ((not args) +;; TODO map of matrix desciptions + +(defmethod mmap-into ((b matrix-base) f (a matrix-base) &rest args) + (cond ((not args) + (dotimes (i (size a)) + (setf (vref b i) (funcall f (vref a i))))) + ((not (cdr args)) + (let ((c (car args))) (dotimes (i (size a)) - (setf (vref b i) (funcall f (vref a i))))) - ((not (cdr args)) - (let ((c (car args))) - (dotimes (i (size a)) - (setf (vref b i) (funcall f (vref a i) (vref c i)))))) - (t (dotimes (i (size a)) - (setf (vref b i) (apply f (vref a i) - (mapcar (lambda (x) - (vref x i)) - args)))))) - b)) + (setf (vref b i) (funcall f (vref a i) (vref c i)))))) + (t (dotimes (i (size a)) + (setf (vref b i) (apply f (vref a i) + (mapcar (lambda (x) + (vref x i)) + args)))))) + b) (defmethod msum ((m matrix-base)) "Sums all elements of m." Modified: src/matrix/level2-interface.lisp ============================================================================== --- src/matrix/level2-interface.lisp (original) +++ src/matrix/level2-interface.lisp Tue Sep 1 06:57:49 2009 @@ -119,6 +119,9 @@ (:documentation "Generalization of map, where type = t gives output type equals type of m.")) +(defgeneric mmap-into (result f m &rest args) + (:documentation "Generalization of map-into.")) + (defgeneric mfill (a value) (:documentation "Sets each element to the value. Destructive")) Modified: src/matrix/level2-matrix-dge.lisp ============================================================================== --- src/matrix/level2-matrix-dge.lisp (original) +++ src/matrix/level2-matrix-dge.lisp Tue Sep 1 06:57:49 2009 @@ -31,15 +31,13 @@ :rows (rows matrix) :cols (cols matrix))) -(defmethod mmap ((type matrix-base-dge) f (a matrix-base-dge) &rest args) - (let ((b (copy a))) - (apply #'map-into - (matrix-store b) - (lambda (&rest args) - (coerce (apply f args) 'double-float)) - (matrix-store a) (mapcar #'matrix-store args)) - b)) - +(defmethod mmap-into ((out matrix-base-dge) f (a matrix-base-dge) &rest args) + (apply #'map-into + (matrix-store out) + (lambda (&rest args) + (coerce (apply f args) 'double-float)) + (matrix-store a) (mapcar #'matrix-store args)) + out) (defmethod msum ((m matrix-base-dge)) (let ((sum 0.0) Modified: src/matrix/level2-matrix-zge.lisp ============================================================================== --- src/matrix/level2-matrix-zge.lisp (original) +++ src/matrix/level2-matrix-zge.lisp Tue Sep 1 06:57:49 2009 @@ -32,6 +32,18 @@ :rows (rows matrix) :cols (cols matrix))) +(defmethod copy-contents ((from matrix-base-dge) (to matrix-base-zge) &optional (converter nil)) + (if converter + (call-next-method) ;; Could have some testes here to improve performance + (let* ((store-a (matrix-store from)) + (store-b (matrix-store to)) + (len (length store-a))) + (declare (type type-blas-store store-a store-b) + (type type-blas-idx len)) + (dotimes (i len) + (setf (aref store-b (* 2 i)) (aref store-a i))) + to))) + (defmethod msum ((m matrix-base-zge)) (let ((sum-r 0.0) (sum-i 0.0) From jivestgarden at common-lisp.net Thu Sep 10 19:18:53 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Thu, 10 Sep 2009 15:18:53 -0400 Subject: [lisplab-cvs] r92 - doc/manual Message-ID: Author: jivestgarden Date: Thu Sep 10 15:18:53 2009 New Revision: 92 Log: more writing Modified: doc/manual/lisplab.texi Modified: doc/manual/lisplab.texi ============================================================================== --- doc/manual/lisplab.texi (original) +++ doc/manual/lisplab.texi Thu Sep 10 15:18:53 2009 @@ -5,7 +5,7 @@ @copying GPL -Copyright @copyright{} 2009 Jorn Inge Vestgaarden +Copyright @copyright{} 2009 Joern Inge Vestgaarden @end copying @titlepage @@ -29,6 +29,7 @@ * Getting started:: * Tutorial:: * Structure:: +* Discussion:: * Index:: @end menu @@ -84,6 +85,9 @@ @item The @code{*READ-DEFAULT-FLOAT-FORMAT*} must be @code{double-float}. @end itemize +Except from this, Lisplab should be self-contained and not depend on +any other projects. + @section Installing Lisplab is ASDF installable, but before you come so far you need to specify the location of the foreign libraries. @@ -203,15 +207,21 @@ @node Tutorial @chapter Tutorial + @section Starting -To test Lisplab open Emacs and Slime in the lisplab directory. +Currently Lisplab only runs on SBCL, and there is a small porting +job (mainly the FFIs and a few uses of SB-EXT package) to +get it run on other platforms. If you have SBCL you must +make sure that @code{lisplab.asd} is (or pointed to) in @code{asdf:*centeral-registry*}. +Then type @example -CL-USER> (load "start.lisp") +CL-USER> (require :lisplab) CL-USER> (in-package :ll) @end example The main package of Lisplab is @i{lisplab}, with nickname @i{ll}. The tutorial assues that you are in the @i{lisplab} package or -use it. +use it. There is also a package @i{lisplab-user}, with nickname @i{ll-user} +that uses @i{lisplab}. @section The dotted algebra @@ -232,6 +242,7 @@ If you want to extend the algebra, e.g. with polynomials, you should add specializing methods to these generic functions. + @section Matrix classes The matrix classes hierarchy has three lines of inheritance. The first is on structure, the second is on element type, and @@ -266,6 +277,7 @@ by default. To add new classes in a structured way, @xref{Structure}. + @section Matrix construction The constructor @code{make-matrix-instance} is not the primary choice to create a matrix. Its better to use a special @@ -318,6 +330,7 @@ (e.g., conversion from complex to real), use @code{copy-contents} instead. + @section Matrix element reference To access a matrix element use the generic function @code{mref} @example @@ -335,6 +348,22 @@ @end example which is also settable. Note that the matrices are column major order. + + at section Matrix map +There are two methods for mapping of matrices: @code{mmap} and + at code{mmap-into}. For example + at example +LL> (mmap 'matrix-dge #'realpart (zmat (1 %i) (-%i 2))) +# + at end example +The output matrix takes the structure from the first arguments, but +ignores in general matrix structure. If first argument @code{t} output +type is same as type of first matrix argument. + + @section The dotted algebra The element-vise functions by conventions have names starting with a dot (period). The dotted algebra works on the single elements and @@ -463,6 +492,7 @@ Note that the IO functions are currently in a poor state. + @section Matrices without store The class @code{function-matrix} implements matrices with functions and has no store. @@ -482,6 +512,7 @@ Function matrices are also used to view a part or restructured other matrix with @code{view-matrix}, @code{view-col}, or @code{view-row}. + @section Ordinary functions These are: @code{.sin}, @code{.cos}, @code{.sin}, @code{.tan}, @@ -491,6 +522,7 @@ @code{.conj}, @code{.realpart}, @code{.imagpart}, @code{.exp}, @code{.abs}. + @section Special functions These are: @code{.besj}, @code{.besy}, @@ -498,6 +530,7 @@ @code{.besh1}, @code{.besh2}, @code{.ai}, @code{.gamma}. + @section Infix notation Infix input is with the macro @code{w/infix}, where you must have spaces before and after @@ -516,6 +549,7 @@ @node Structure @chapter Structure + @section Design principles Design principles for the full library @itemize @@ -523,15 +557,13 @@ @item It makes a @i{homogeneous platform} for all kinds of mathematical calculations. (So it's a lot more than just a matrix library) - at item User applications need only to stay in Common Lisp. + at item User applications should need to stay only in Common Lisp. (There should be no need for optimized math in FFIs or special languages like Maxima) @item Every common mathematical operator and function -is represented by a @i{CLOS generic function}. (By convention -the names of the operators start with a dot and is called -the dotted algebra, where algebra is used in the widest possible sense -of the word). +is represented by a @i{CLOS generic function}. @item Modular structure (Inspired by GSL). + at item Error checks is primarily callers responsibility, not Lisplab's! @item To steal as much as possible from as many as possible (I love free software). @end itemize @@ -539,21 +571,22 @@ Design principles for the matrix part @itemize @item Layered structure where dependencies are -primarily on the layer below -- not vertical in the layer. - at item The layers get larger upwards. Combined with the previous -principle it ensures a modular structure! +primarily on the layer below -- not vertical within the layer. + at item Layer 0 is mainly interfaces and generic functions, not implementations. +Level 1 and 2 are small. This structure should encourage modularity. @end itemize - - @section Package structure So far, there is only one main package, called, you might guess it: @i{lisplab}. Except from that there are only a few special packages -for generated code and FFIs: Slatec, Blas, and FFTW. +for generated code and FFIs: Slatec, Blas, and FFTW. There is also +a package @i{lisplab-user} for test code and applications. + @section The four levels, 0 -- 3. -Lisplab has a layered structure with four levels, 0 -- 3, +The Lisplab matrix and linear algebra code +has a layered structure with four levels, 0 -- 3, where @itemize @item @b{Level 0} is matrix independent and contains @@ -596,7 +629,12 @@ denote the level, it is most probably level 3, or outside the level system (non matrix code). + @section Matrix class hierarchy +All matrices are subclasses of @code{matrix-base}, and as +far as possible the generic functions specialize +on one or many of its subclasses. + The matrix class hierarchy has three independent lines of inheritance @itemize @@ -605,12 +643,60 @@ @item On implementation @end itemize The structure is inspired by the stream example in -Object-Oriented Programming in Common Lisp, -by Sonya E. Keene. +Object-Oriented Programming in Common Lisp, by Sonya E. Keene. + + + at subsection The structure +The structure tells what kind of symmetries or other +special properties the matrix has. +Two matrix classes + at itemize + at item @code{matrix-structure-general}, where the matrix +has no known symmetries. + at item @code{matrix-structure-diagonal}, where only +diagonal elements are non-zero. + at end itemize + + at subsection The element type +The element type classes has no other purpose than to be +represents a Common Lisp types.. + at itemize + at item @code{matrix-element-base}, represents @code{t} + at item @code{matrix-element-double-float}, represents @code{double-float} + at item @code{matrix-element-complex-double-float}, represents @code{complex double-float} + at end itemize + + at subsection The implementation +Since Lisplab has many competing implementation of the same +generic functions, the implementation class structure tells which +one too choose. There are currently four classes in a straight +line of inheritance + at itemize + at item matrix-implementation-base + at item matrix-implementation-lisp, use native Common Lisp if possible. + at item matrix-implementation-blas, use foreign libraries if possible. + at end itemize +This standard method dispatch ensures foreign library methods +are chosen before native lisp. @i{It is the responsibility of the +methods to call next method if the library is not loaded}. + + + at node Discussion + at chapter Discussion + + at section Experiences with Common Lisp in high performance computing + at section The foreign function interfaces + at section Parallel execution +To request usage of more threads, call @code{init-threads}. +Currently, only the calls to FFTW will react to this. + at section Symbolic calculations +There is some minor code for this, but it is not yet included +in the package. Symbolic code should be developed only with +knowledge of the generic methods of the dotted algebra (The level 0). @c End stuff From jivestgarden at common-lisp.net Sat Sep 12 19:29:39 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sat, 12 Sep 2009 15:29:39 -0400 Subject: [lisplab-cvs] r93 - doc/manual Message-ID: Author: jivestgarden Date: Sat Sep 12 15:29:38 2009 New Revision: 93 Log: almost finished manual Modified: doc/manual/lisplab.texi Modified: doc/manual/lisplab.texi ============================================================================== --- doc/manual/lisplab.texi (original) +++ doc/manual/lisplab.texi Sat Sep 12 15:29:38 2009 @@ -3,14 +3,16 @@ @settitle Lisplab manual @copying -GPL +This manual is for Lisplab version 0.1, updated 10. September 2009. Copyright @copyright{} 2009 Joern Inge Vestgaarden @end copying @titlepage @title Lisplab manual - + at subtitle A mathematics library for Common Lisp + at author Joern Inge Vestgaarden + @page @vskip 0pt plus 1filll @insertcopying @@ -19,10 +21,13 @@ @contents @ifnottex - at node Top + at node Top + @top Lisplab manual @end ifnottex + + @menu * Introduction:: @@ -30,7 +35,7 @@ * Tutorial:: * Structure:: * Discussion:: -* Index:: + at c * Index:: @end menu @c The body @@ -173,7 +178,7 @@ Lisplab started as a refactoring of Matlisp (To make my simulations run on Windows for my professor), but -I ended up by reimplementing most of it, keeping +I (Joern Inge) ended up by reimplementing most of it, keeping only the interfaces to Blas and Lapack. Currently, Lisplab and Matlisp have more or less the same functionality. Lisplab differ from Matlisp in the following ways @@ -224,25 +229,6 @@ that uses @i{lisplab}. - at section The dotted algebra -Central in Lisplab is an algebra (in the widest possible sense of the word) -with the functions - at code{.+}, @code{.-}, @code{.*}, @code{./}, and @code{.^}. -These are generalization of - at code{+}, @code{-}, @code{*}, @code{/}, and @code{^}. -For numbers they work the same, - at example -LL> (.+ 1 2) -3 - at end example -The functions @code{.+}, @code{.-}, @code{.*}, @code{./}, and @code{.^} -are mainly wrappers that call @code{reduce} on its arguments with the -generic functions - at code{.add}, @code{.sub}, @code{.mul}, @code{.div}, and @code{.expt}. -If you want to extend the algebra, e.g. with polynomials, -you should add specializing methods to these generic functions. - - @section Matrix classes The matrix classes hierarchy has three lines of inheritance. The first is on structure, the second is on element type, and @@ -331,7 +317,7 @@ use @code{copy-contents} instead. - at section Matrix element reference + at section Matrix element reference (mref and vref) To access a matrix element use the generic function @code{mref} @example LL> (mref (dmat (1 2) (3 4)) 0 1) @@ -349,27 +335,30 @@ which is also settable. Note that the matrices are column major order. - at section Matrix map -There are two methods for mapping of matrices: @code{mmap} and - at code{mmap-into}. For example + + at section The dotted algebra (.+, .*, .sin, ...) +Central in Lisplab is an algebra (in the widest possible sense of the word) +with the functions + at code{.+}, @code{.-}, @code{.*}, @code{./}, and @code{.^}. +These are generalization of + at code{+}, @code{-}, @code{*}, @code{/}, and @code{^}. +For numbers they work the same, @example -LL> (mmap 'matrix-dge #'realpart (zmat (1 %i) (-%i 2))) -# +LL> (.+ 1 2) +3 @end example -The output matrix takes the structure from the first arguments, but -ignores in general matrix structure. If first argument @code{t} output -type is same as type of first matrix argument. - +The functions @code{.+}, @code{.-}, @code{.*}, @code{./}, and @code{.^} +are mainly wrappers that call @code{reduce} on its arguments with the +generic functions + at code{.add}, @code{.sub}, @code{.mul}, @code{.div}, and @code{.expt}. +If you want to extend the algebra, e.g. with polynomials, +you should add specializing methods to these generic functions. - at section The dotted algebra The element-vise functions by conventions have names starting with a dot (period). The dotted algebra works on the single elements and is structure agnostic. The functions of the dotted algebra -introduce a programming style -much the same as for Matlab, and combined with the linear algebra +introduce a programming style much the same as for Matlab, +and combined with the linear algebra functions, you can write compact programs, without the slow single element references. @example @@ -513,6 +502,21 @@ with @code{view-matrix}, @code{view-col}, or @code{view-row}. + at section Matrix map +There are two methods for mapping of matrices: @code{mmap} and + at code{mmap-into}. For example + at example +LL> (mmap 'matrix-dge #'realpart (zmat (1 %i) (-%i 2))) +# + at end example +The output matrix takes the structure from the first arguments, but +ignores in general matrix structure. If first argument @code{t} output +type is same as type of first matrix argument. + + @section Ordinary functions These are: @code{.sin}, @code{.cos}, @code{.sin}, @code{.tan}, @@ -561,10 +565,13 @@ (There should be no need for optimized math in FFIs or special languages like Maxima) @item Every common mathematical operator and function -is represented by a @i{CLOS generic function}. +is represented by a @i{CLOS generic function}. This is called the dotted algebra. @item Modular structure (Inspired by GSL). + at item Trust the Lisp system and use foreign code as little as possible. + at item Avoid programming mathematical algorithms in macros. Despite the +advantages (fast and generic at the same time) it is hard to understand and debug. @item Error checks is primarily callers responsibility, not Lisplab's! - at item To steal as much as possible from as many as possible + at item To steal as much code as possible from as many as possible (I love free software). @end itemize @@ -684,26 +691,40 @@ @node Discussion @chapter Discussion - at section Experiences with Common Lisp in high performance computing - @section The foreign function interfaces +The elements of Lisplab typed matrices (double-float and complex double-float) are +stored as 1D simple arrays, and most Lisps will then have +a SAP inside the array pointer which is binary compatible +with Fortran. This adds some overhead to matrix element references, +but simplifies the garbage collections. + +Matlisp has an extra layer with Fortran compatibility above +the ordinary C FFI. This layer is mainly unchanged compared +to Matlisp, but only the SBCL FFI is in the code. The +FFIs for other lisps could easily be added, but not without testing. + +The FFI for FFTW is a mock-up for SBCL, and it only is for standard +complex transforms and inverse transforms. Of course, a lot more can +be done, but this simple version works quite OK. In long term the SBCL +FFI should be replaced with a general one. + @section Parallel execution To request usage of more threads, call @code{init-threads}. -Currently, only the calls to FFTW will react to this. +Currently only the calls to FFTW will react to this. @section Symbolic calculations -There is some minor code for this, but it is not yet included -in the package. Symbolic code should be developed only with -knowledge of the generic methods of the dotted algebra (The level 0). +There is draft code for symbolic calculations, but it is not yet included +in the build. The symbolic code need not know anything about the rest of Lisplab, +except for the generic methods of the dotted algebra (The level 0). @c End stuff - at node Index - at unnumbered Index + at c @node Index + at c @unnumbered Index - at printindex cp + at c @printindex cp @bye From jivestgarden at common-lisp.net Sat Sep 26 12:38:03 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sat, 26 Sep 2009 08:38:03 -0400 Subject: [lisplab-cvs] r94 - doc/manual src/matrix Message-ID: Author: jivestgarden Date: Sat Sep 26 08:38:02 2009 New Revision: 94 Log: improvements and optimizations Modified: doc/manual/lisplab.texi lisplab.asd package.lisp src/matrix/level1-util.lisp src/matrix/level2-constructors.lisp src/matrix/level2-generic.lisp src/matrix/level2-matrix-dge.lisp src/matrix/level2-matrix-zge.lisp Modified: doc/manual/lisplab.texi ============================================================================== --- doc/manual/lisplab.texi (original) +++ doc/manual/lisplab.texi Sat Sep 26 08:38:02 2009 @@ -662,26 +662,28 @@ has no known symmetries. @item @code{matrix-structure-diagonal}, where only diagonal elements are non-zero. + at item Other types to come. @end itemize @subsection The element type The element type classes has no other purpose than to be -represents a Common Lisp types.. +represents a Common Lisp types. @itemize @item @code{matrix-element-base}, represents @code{t} @item @code{matrix-element-double-float}, represents @code{double-float} @item @code{matrix-element-complex-double-float}, represents @code{complex double-float} @end itemize + @subsection The implementation Since Lisplab has many competing implementation of the same generic functions, the implementation class structure tells which one too choose. There are currently four classes in a straight line of inheritance @itemize - at item matrix-implementation-base - at item matrix-implementation-lisp, use native Common Lisp if possible. - at item matrix-implementation-blas, use foreign libraries if possible. + at item @code{matrix-implementation-base} + at item @code{matrix-implementation-lisp}, use native Common Lisp if possible. + at item @code{matrix-implementation-blas}, use foreign libraries if possible. @end itemize This standard method dispatch ensures foreign library methods are chosen before native lisp. @i{It is the responsibility of the Modified: lisplab.asd ============================================================================== --- lisplab.asd (original) +++ lisplab.asd Sat Sep 26 08:38:02 2009 @@ -12,14 +12,15 @@ (defun load-lisplab-lib (name) (when name - (sb-alien:load-shared-object name))) + #+sbcl (sb-alien:load-shared-object name))) (defun explain-lisplab-lib (name path) (format t "Loads ~A. Path ~a" name path)) (declaim (inline |fftw_init_threads|)) -(sb-alien:define-alien-routine |fftw_init_threads| +#+sbcl (sb-alien:define-alien-routine |fftw_init_threads| sb-alien:int) +#-sbcl (defun fftw_init_threads (n)) (defsystem :lisplab ;; Default system, without all libs Modified: package.lisp ============================================================================== --- package.lisp (original) +++ package.lisp Sat Sep 26 08:38:02 2009 @@ -150,6 +150,8 @@ "DCOL" "DROW" "DRANDOM" + "DRANGE" + "DGRID" "ZMAT" "ZNEW" "ZCOL" Modified: src/matrix/level1-util.lisp ============================================================================== --- src/matrix/level1-util.lisp (original) +++ src/matrix/level1-util.lisp Sat Sep 26 08:38:02 2009 @@ -151,3 +151,10 @@ (setf (aref store i) rv))) store)) +(defun copy-matrix-stores (a b) + (let ((len (length a))) + (declare (type type-blas-store a b) + (type type-blas-idx len)) + (dotimes (i len) + (setf (aref b i) (aref a i)))) + b) \ No newline at end of file Modified: src/matrix/level2-constructors.lisp ============================================================================== --- src/matrix/level2-constructors.lisp (original) +++ src/matrix/level2-constructors.lisp Sat Sep 26 08:38:02 2009 @@ -98,6 +98,34 @@ "Creates a matrix-dge matrix" (mnew 'matrix-dge value rows cols)) +(defun drange (n from to &optional (shift 0)) + "Creates a column vector of length n, with elements of equal spacing +between from and to. The shift is the a number between 0 and 1 and +shifts the start position. + +For example: (drange 4 0 1) -> 0 1 2 3, while + (drange 4 0 1 0.5) -> 0.5 1.5 2.5 3.5." + (let ((x (dnew 0 n 1)) + (dx (./ (.- to from)))) + (dotimes (i n) + (setf (vref x i) (.+ from (.* dx (.+ i shift))))) + x)) + +(defun dgrid (xv yv) + "Creates grid matrices from input vectors. Input are the x and y vectors +and outputs are a list of x and y matrices. The input vectors are +typically created with drange." + (let* ((r (size xv)) + (c (size yv)) + (x (dnew 0 r c)) + (y (dnew 0 r c))) + (dotimes (i r) + (dotimes (j c) + (setf (mref x i j) (vref xv i) + (mref y i j) (vref yv j)))) + (list x y))) + + ;;; Constructors for matrix-zge (defmacro zmat (&body args) Modified: src/matrix/level2-generic.lisp ============================================================================== --- src/matrix/level2-generic.lisp (original) +++ src/matrix/level2-generic.lisp Sat Sep 26 08:38:02 2009 @@ -24,6 +24,12 @@ (in-package :lisplab) +(defmethod mcreate ((m number) &optional (val 0.0) dim) + ;; This is not about matrices at all, but is usefull + ;; when you use the dotted algebra and is not sure is input is numbers or matrices. + ;; TODO what the dim, should I use it or ignore it + val) + (defmethod square-matrix? ((x matrix-base)) (= (rows x) (cols x))) Modified: src/matrix/level2-matrix-dge.lisp ============================================================================== --- src/matrix/level2-matrix-dge.lisp (original) +++ src/matrix/level2-matrix-dge.lisp Sat Sep 26 08:38:02 2009 @@ -31,6 +31,14 @@ :rows (rows matrix) :cols (cols matrix))) +(defmethod copy-contents ((a matrix-base-dge) (b matrix-base-dge) &optional (converter nil)) + (let ((store-a (matrix-store a)) + (store-b (matrix-store b))) + (if converter + (map-into store-b converter store-a) + (copy-matrix-stores store-a store-b))) + b) + (defmethod mmap-into ((out matrix-base-dge) f (a matrix-base-dge) &rest args) (apply #'map-into (matrix-store out) Modified: src/matrix/level2-matrix-zge.lisp ============================================================================== --- src/matrix/level2-matrix-zge.lisp (original) +++ src/matrix/level2-matrix-zge.lisp Sat Sep 26 08:38:02 2009 @@ -55,22 +55,48 @@ (incf sum-i (aref m0 (1+ i)))) (complex sum-r sum-i))) + +;;; Hm, much shared code here. Could make a unifying macro. + (defmethod .imagpart ((a matrix-base-zge)) (let* ((description (create-matrix-description a :et :d)) - (b (make-matrix-instance description (dim a) 0))) - (copy-contents a b #'imagpart) + (b (make-matrix-instance description (dim a) 0)) + (store-a (matrix-store a)) + (store-b (matrix-store b)) + (len (size a))) + (declare (type type-blas-store store-a store-b) + (type type-blas-idx len)) + (dotimes (i len) + (setf (aref store-b i) + (aref store-a (1+ (* 2 i))))) b)) (defmethod .realpart ((a matrix-base-zge)) (let* ((description (create-matrix-description a :et :d)) - (b (make-matrix-instance description (dim a) 0))) - (copy-contents a b #'realpart) + (b (make-matrix-instance description (dim a) 0)) + (store-a (matrix-store a)) + (store-b (matrix-store b)) + (len (size a))) + (declare (type type-blas-store store-a store-b) + (type type-blas-idx len)) + (dotimes (i len) + (setf (aref store-b i) + (aref store-a (* 2 i)))) b)) (defmethod .abs ((a matrix-base-zge)) (let* ((description (create-matrix-description a :et :d)) - (b (make-matrix-instance description (dim a) 0))) - (copy-contents a b #'abs) + (b (make-matrix-instance description (dim a) 0)) + (store-a (matrix-store a)) + (store-b (matrix-store b)) + (len (size a))) + (declare (type type-blas-store store-a store-b) + (type type-blas-idx len)) + (dotimes (i len) + (setf (aref store-b i) + (let ((x (aref store-a (* 2 i))) + (y (aref store-a (1+ (* 2 i))))) + (sqrt (+ (* x x) (* y y)))))) b)) (defmacro def-binary-op-matrix-base-zge (new old) From jivestgarden at common-lisp.net Sat Sep 26 14:23:10 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sat, 26 Sep 2009 10:23:10 -0400 Subject: [lisplab-cvs] r95 - src/matrix Message-ID: Author: jivestgarden Date: Sat Sep 26 10:23:09 2009 New Revision: 95 Log: Cleaning pluss export and import of matrices Added: src/matrix/level1-sparse.lisp Modified: src/matrix/level1-classes.lisp src/matrix/level1-util.lisp src/matrix/level2-constructors.lisp src/matrix/level2-generic.lisp src/matrix/level2-interface.lisp src/matrix/level2-matrix-zge.lisp Modified: src/matrix/level1-classes.lisp ============================================================================== --- src/matrix/level1-classes.lisp (original) +++ src/matrix/level1-classes.lisp Sat Sep 26 10:23:09 2009 @@ -99,7 +99,9 @@ :accessor size :type type-blas-idx))) -;;; The actual classes ment for instantiation +;;; The actual classes meant for instantiation + +;;;; General matrices with unspecified element types (defclass matrix-ge (matrix-structure-general matrix-element-base matrix-implementation-lisp) Added: src/matrix/level1-sparse.lisp ============================================================================== --- (empty file) +++ src/matrix/level1-sparse.lisp Sat Sep 26 10:23:09 2009 @@ -0,0 +1,73 @@ +;;; Lisplab, level1-sparse.lisp +;;; General sparse matrices base on hash tables + +;;; Copyright (C) 2009 Joern Inge Vestgaarden +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License along +;;; with this program; if not, write to the Free Software Foundation, Inc., +;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +;;; Note that there is probably not much to save using this on most operations +;;; since they by default go through all elements. + + +(in-package :lisplab) + +(defclass matrix-sparse + (matrix-structure-general matrix-element-base matrix-implementation-lisp) + ((hash-store + :initarg :store + :initform nil + :reader matrix-hash-store) + (default-element + :initarg :default-element + :initform nil + :accessor matrix-default-element)) + (:documentation "A sparse matrix")) + +(defmethod initialize-instance :after ((m matrix-sparse) &key (value 0)) + (with-slots (rows cols size hash-store default-element ) m + (setf size (* rows cols)) + (unless hash-store + (setf hash-store (make-hash-table :test 'eq))) + (unless default-element + (setf default-element value)))) + +;;; Add clases to the description system +(add-matrix-class 'matrix-sparse :any :sparse :any) + +(defmethod mref ((matrix matrix-sparse) row col) + (multiple-value-bind (val ok) + (gethash (column-major-idx row col (slot-value matrix 'rows)) + (slot-value matrix 'hash-store)) + (if ok + val + (slot-value matrix 'default-element)))) + +(defmethod (setf mref) (value (matrix matrix-sparse) row col) + (setf (gethash (column-major-idx row col (slot-value matrix 'rows)) + (slot-value matrix 'hash-store)) + value)) + +(defmethod vref ((matrix matrix-sparse) idx) + (multiple-value-bind (val ok) + (gethash idx + (slot-value matrix 'hash-store)) + (if ok + val + (slot-value matrix 'default-element)))) + +(defmethod (setf vref) (value (matrix matrix-sparse) idx) + (setf (gethash idx + (slot-value matrix 'hash-store)) + value)) \ No newline at end of file Modified: src/matrix/level1-util.lisp ============================================================================== --- src/matrix/level1-util.lisp (original) +++ src/matrix/level1-util.lisp Sat Sep 26 10:23:09 2009 @@ -1,5 +1,5 @@ ;;; Lisplab, level1-util.lisp -;;; Level1, utility functions for matrix defenitions +;;; Level1, utility functions for matrix definitions. ;;; ;;; Copyright (C) 2009 Joern Inge Vestgaarden @@ -72,18 +72,6 @@ (complex double-float)) (setf ref-blas-complex-store))) -(defun fill-matrix-with-list (m x) - (let* ((rows (rows m)) - (cols (cols m))) - (do ((xx x (cdr xx)) - (i 0 (1+ i))) - ((= i rows)) - (do ((yy (car xx) (cdr yy)) - (j 0 (1+ j))) - ((= j cols)) - (setf (mref m i j) (car yy)))) - m)) - (defun column-major-idx (i j rows) (truly-the type-blas-idx (+ i (truly-the type-blas-idx (* j rows))))) Modified: src/matrix/level2-constructors.lisp ============================================================================== --- src/matrix/level2-constructors.lisp (original) +++ src/matrix/level2-constructors.lisp Sat Sep 26 10:23:09 2009 @@ -30,20 +30,24 @@ (setf dim (dim a))) (make-matrix-instance (class-of a) dim value)) -(defmethod mmcreate ((a matrix-base) (b matrix-base) &optional (value 0) dim) - ;; TODO make real implmentaiton of this based on descriptions - (unless dim - (setf dim (dim a))) - (if (or (equal '(complex double-float) (element-type a)) - (equal '(complex double-float) (element-type b))) - (make-matrix-instance 'matrix-zge dim value) - (make-matrix-instance 'matrix-dge dim value))) - (defmethod convert ((x matrix-base) type) (let ((y (make-matrix-instance type (dim x) 0))) (copy-contents x y) y)) +(defun fill-matrix-with-list (m x) + "Helper function for convert." + (let* ((rows (rows m)) + (cols (cols m))) + (do ((xx x (cdr xx)) + (i 0 (1+ i))) + ((= i rows)) + (do ((yy (car xx) (cdr yy)) + (j 0 (1+ j))) + ((= j cols)) + (setf (mref m i j) (car yy)))) + m)) + (defmethod convert ((x cons) type) ;; Should it be moved to some other file? ;; TODO some better way ... some more general guessing routine @@ -60,7 +64,7 @@ (defmethod mnew (type value rows &optional cols) (make-matrix-instance type (list rows cols) value)) -(defmacro mat (type &body args) +(defmacro mmat (type &body args) "Creates a matrix." `(convert ,(cons 'list (mapcar (lambda (x) @@ -68,11 +72,11 @@ args)) ,type)) -(defun col (type &rest args) +(defun mcol (type &rest args) "Creates a column matrix." (convert (mapcar 'list args) type)) -(defun row (type &rest args) +(defun mrow (type &rest args) "Creates a row matrix." (convert args type)) @@ -84,15 +88,15 @@ (defmacro dmat (&body args) "Creates a matrix-dge matrix." - `(mat 'matrix-dge , at args)) + `(mmat 'matrix-dge , at args)) (defun dcol (&rest args) "Creates a matrix-dge column matrix." - (apply #'col 'matrix-dge args)) + (apply #'mcol 'matrix-dge args)) (defun drow (&rest args) "Creates a matrix-dge row matrix." - (apply #'row 'matrix-dge args)) + (apply #'mrow 'matrix-dge args)) (defun dnew (value rows &optional (cols 1)) "Creates a matrix-dge matrix" @@ -130,15 +134,15 @@ (defmacro zmat (&body args) "Creates a matrix-dge matrix." - `(mat 'matrix-zge , at args)) + `(mmat 'matrix-zge , at args)) (defun zcol (&rest args) "Creates a matrix-zge column matrix." - (apply #'col 'matrix-zge args)) + (apply #'mcol 'matrix-zge args)) (defun zrow (&rest args) "Creates a matrix-zge row matrix." - (apply #'row 'matrix-zge args)) + (apply #'mrow 'matrix-zge args)) (defun znew (value rows &optional (cols 1)) "Creates a matrix-zge matrix" Modified: src/matrix/level2-generic.lisp ============================================================================== --- src/matrix/level2-generic.lisp (original) +++ src/matrix/level2-generic.lisp Sat Sep 26 10:23:09 2009 @@ -178,6 +178,21 @@ (mref A (- i dr) (- j dc))))) B)) +(defmethod export-list ((m matrix-base)) + (let ((res nil)) + (dotimes (i (size m)) + (push (vref m i) res)) + (nreverse res))) + +(defmethod import-list ((m matrix-base) list) + (let ((tmp list)) + (dotimes (i (size m)) + (unless tmp + (return-from import-list m)) + (setf (vref m i) (car tmp) + tmp (cdr tmp))) + m)) + (defmethod reshape ((a matrix-base) shape) (let ((B (mcreate a 0 shape))) (dotimes (i (size B)) @@ -292,7 +307,8 @@ (defmacro expand-matrix-ge-num-num () (cons 'progn (mapcar (lambda (name) - ;; Note: not using the (cdr name) , which is only valid for build in lisp types. + ;; Note: not using the (cdr name) , which is only valid + ;; for build in lisp types. `(defmethod ,(car name) ((x matrix-ge)) (each-element-function-matrix-ge x (,(car name) x)))) +functions-real-to-real+))) @@ -302,7 +318,6 @@ (defmethod .log ((x matrix-ge) &optional base) (each-element-function-matrix-ge x (.log x base))) - ;;; Bessel functions (defmethod .besj (n (x matrix-ge)) Modified: src/matrix/level2-interface.lisp ============================================================================== --- src/matrix/level2-interface.lisp (original) +++ src/matrix/level2-interface.lisp Sat Sep 26 10:23:09 2009 @@ -17,9 +17,15 @@ ;;; with this program; if not, write to the Free Software Foundation, Inc., ;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +;;; TODO sort and possibly move to other levels + (in-package :lisplab) -;;; TODO sort and possibly move to other levels +(defgeneric export-list (m) + (:documentation "Exports the elements of the matrix to a list.")) + +(defgeneric import-list (m list) + (:documentation "Imports the elements of the matrix from a list.")) (defgeneric .some (pred a &rest matrices) (:documentation "Generalizes some")) @@ -29,14 +35,11 @@ (defgeneric sub-matrix (m rr cc) (:documentation "Copies a sub matrix of m. The format of rr = (start stop) or rr = (start step stop) -and the same for the coulumns.")) +and the same for the columns.")) (defgeneric copy-contents (a b &optional converter) (:documentation "Copies all elements from a to b.")) -(defgeneric new (class dim &optional element-type value) - (:documentation "Deprecated. Use mnew in stead. Creates a new matrix filled with numeric arguments.")) - (defgeneric mnew (class value rows &optional cols) (:documentation "General matrix constructor. Creates a new matrix filled with numeric arguments.")) @@ -44,23 +47,12 @@ (:documentation "Creates a new matrix of the same type and with the same value as the other, but with all elements set to value.")) -(defgeneric mmcreate (a b &optional value dim) - (:documentation "Creates a new matrix. The new matrix has a type derived from a and b, -and all elements set to value.")) - (defgeneric square-matrix? (x) (:documentation "True when the matrix is square, obviously.")) (defgeneric diag (v) (:documentation "Creates a diagnoal matrix from the vector.")) -#+nil (defgeneric dlmwrite (matrix &optional file &rest args) - (:documentation "Write all elements to a text file or stream in -row major order. File t means standard output.")) - -#+nil (defgeneric dlmread (class &optional file-or-stream &rest args) - (:documentation "Reads a text file or stream and outputs a matrix")) - (defgeneric to-vector! (a) (:documentation "Reshape the object to 1D. Destructive")) @@ -112,7 +104,6 @@ (:documentation "Returns a transposed matrix with same (shared) elements")) - ;;;; Single-element operations (defgeneric mmap (type f m &rest args) @@ -125,11 +116,6 @@ (defgeneric mfill (a value) (:documentation "Sets each element to the value. Destructive")) -#+nil (defgeneric .map (f m &rest rest) - (:documentation "Maps the function on each element. The returned -object has dimensionality of the first object")) - - ;;; Helpers (defgeneric msum (m) Modified: src/matrix/level2-matrix-zge.lisp ============================================================================== --- src/matrix/level2-matrix-zge.lisp (original) +++ src/matrix/level2-matrix-zge.lisp Sat Sep 26 10:23:09 2009 @@ -32,6 +32,14 @@ :rows (rows matrix) :cols (cols matrix))) +(defmethod copy-contents ((a matrix-base-zge) (b matrix-base-zge) &optional (converter nil)) + (let ((store-a (matrix-store a)) + (store-b (matrix-store b))) + (if converter + (map-into store-b converter store-a) + (copy-matrix-stores store-a store-b))) + b) + (defmethod copy-contents ((from matrix-base-dge) (to matrix-base-zge) &optional (converter nil)) (if converter (call-next-method) ;; Could have some testes here to improve performance From jivestgarden at common-lisp.net Sat Sep 26 18:26:50 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sat, 26 Sep 2009 14:26:50 -0400 Subject: [lisplab-cvs] r96 - doc/manual src/io src/linalg src/test Message-ID: Author: jivestgarden Date: Sat Sep 26 14:26:49 2009 New Revision: 96 Log: fixed dlmread and dlmwrite Added: src/io/level3-io-interface.lisp Modified: doc/manual/lisplab.texi lisplab.asd package.lisp src/io/level3-io.lisp src/linalg/level3-linalg-generic.lisp src/test/test-methods.lisp Modified: doc/manual/lisplab.texi ============================================================================== --- doc/manual/lisplab.texi (original) +++ doc/manual/lisplab.texi Sat Sep 26 14:26:49 2009 @@ -296,7 +296,7 @@ while @code{dmat} is a macro. Similarly, there are @code{znew}, @code{zcol}, @code{zrow}, and @code{zmat} for double float matrices and - at code{new}, @code{col}, @code{row}, and @code{mat} + at code{mnew}, @code{mcol}, @code{mrow}, and @code{mmat} for any matrices. The latter take matrix class as first argument. Often you want to create a matrix of the same type as a input Modified: lisplab.asd ============================================================================== --- lisplab.asd (original) +++ lisplab.asd Sat Sep 26 14:26:49 2009 @@ -66,6 +66,7 @@ (:file "level1-classes") (:file "level1-constructors") (:file "level1-matrix") + (:file "level1-sparse") (:file "level1-array") (:file "level2-interface") @@ -84,7 +85,7 @@ (:module :src/io :depends-on (:src/matrix) :components - ( + ((:file "level3-io-interface") (:file "level3-io"))) ;; Modified: package.lisp ============================================================================== --- package.lisp (original) +++ package.lisp Sat Sep 26 14:26:49 2009 @@ -140,11 +140,10 @@ "ROWS" "COLS" ;; Matrix level 2 constructors - "FUNMAT" - "FMAT" - "MAT" - "COL" - "ROW" + "MNEW" + "MMAT" + "MCOL" + "MROW" "DMAT" "DNEW" "DCOL" @@ -156,15 +155,17 @@ "ZNEW" "ZCOL" "ZROW" + "FUNMAT" + "FMAT" ;; Matrix level 2 methods ".EVERY"; to level0 or change name? ".SOME" ; to level0 or change name? "SQUARE-MATRIX?" - "MNEW" "MCREATE" "COPY-CONTENTS" - + "EXPORT-LIST" + "IMPORT-LIST" "MMAP" "MMAP-INTO" "MFILL" Added: src/io/level3-io-interface.lisp ============================================================================== --- (empty file) +++ src/io/level3-io-interface.lisp Sat Sep 26 14:26:49 2009 @@ -0,0 +1,27 @@ +;;; Lisplab, level3-io.lisp +;;; Input output operations + +;;; Copyright (C) 2009 Joern Inge Vestgaarden +;;; +;;; This program is free software; you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 2 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License along +;;; with this program; if not, write to the Free Software Foundation, Inc., +;;; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +(in-package :lisplab) + +(defgeneric dlmwrite (matrix file-or-stream &key dlm printer) + (:documentation "Write matrix to ASCII-delimited file or stream")) + +(defgeneric dlmread (class in) + (:documentation "Reads a delimited anscii test file and returns a matrix. +Currently only space delimited.")) Modified: src/io/level3-io.lisp ============================================================================== --- src/io/level3-io.lisp (original) +++ src/io/level3-io.lisp Sat Sep 26 14:26:49 2009 @@ -25,56 +25,65 @@ (in-package :lisplab) -(defun dlmwrite (a &optional (out t) +(defmethod dlmwrite ((a matrix-base) + (stream stream) &key (dlm " ") - (fmt "~S")) - "Write matrix as a delimited anscii test file." - (let* ((out (if (eq out t) *standard-output* out))) - (flet ((printit (out) - (if (scalar? a) - (prin1 a out) - (progn - (format out "~&") - (dotimes (i (rows a)) - (dotimes (j (cols a)) - (format out fmt (mref a i j)) - (when (< j (1- (cols a))) - (princ dlm out))) - (when (< i (1- (rows a))) - (princ #\Newline out))))))) - (if (streamp out) - (printit out) - (with-open-file (out out :direction :output :if-exists :supersede) - (printit out)))))) + (printer #'prin1)) + (dotimes (i (rows a)) + (format stream "~&") + (dotimes (j (cols a)) + (funcall printer (mref a i j) stream) + (when (< j (1- (cols a))) + (princ dlm stream))))) -(defun dlmread (class &optional (in t)) - "Reads a delimited anscii test file and returns a matrix. Currently only space delimited." +(defmethod dlmwrite ((a matrix-base) + (name pathname) + &key + (dlm " ") + (printer #'prin1)) + (with-open-file (stream name :direction :output :if-exists :supersede) + (dlmwrite a stream :dlm dlm :printer printer))) + +(defmethod dlmwrite ((a matrix-base) + (name string) + &key + (dlm " ") + (printer #'prin1)) + (dlmwrite a (pathname name) :dlm dlm :printer printer)) + +(defun dlmread-list (in) + "Helper function that reads a delimited file as a list of lists." ;; TODO: Fixit. Non-space formated matrices - (let* ((in (if (eq in t) *standard-input* in)) - (end (gensym)) + (let* ((end (gensym)) (rows nil)) - (labels ((line (in) (let ((line (read-line in nil end nil))) - (if (eq line end) - end - (if (eql (char line 0) #\#) - (line in) - line)))) - (element (in) (read in nil end nil)) - (getit (in) - (do ((line (line in) (line in))) - ((eq line end)) - (let ((s (make-string-input-stream line)) - (cols nil)) - (do ((elm (element s) (element s))) - ((eq elm end)) - (push elm cols)) - (push (reverse cols) rows))))) - (if (streamp in) - (getit in) - (with-open-file (in in :direction :input) - (getit in)))) - (convert (reverse rows) class))) + (labels ((line () (let ((line (read-line in nil end nil))) + (if (eq line end) + end + (if (eql (char line 0) #\#) + (line) + line))))) + (do ((line (line) (line))) + ((eq line end)) + (let ((s (make-string-input-stream line)) + (cols nil)) + (flet ((element () (read s nil end nil))) + (do ((elm (element) (element))) + ((eq elm end)) + (push elm cols)) + (push (nreverse cols) rows)))) + (nreverse rows)))) + +(defmethod dlmread (class (in stream)) + (convert (dlmread-list in) + class)) + +(defmethod dlmread (class (name pathname)) + (with-open-file (in name :direction :input) + (dlmread class in))) + +(defmethod dlmread (class (name string)) + (dlmread class (pathname name))) (defun pgmwrite (m filename &key @@ -109,7 +118,7 @@ (verbose nil) (max (mmax m)) (min (mmin m))) - "Writes matrix as postsrcipt bitmap. Port of a2ps.c by Eric Weeks." + "Writes matrix as postscript bitmap. Port of a2ps.c by Eric Weeks." ;; TODO: clean up and some more lispifying. ;; TODO: more testing. ;; TOOD: change name to epswrite. @@ -168,3 +177,57 @@ (format out "~%")) (format out "showpage~%")))) + +;;;; Trash + + +#+nil (defun dlmwrite (a &optional (out t) + &key + (dlm " ") + (fmt "~S")) + "Write matrix as a delimited anscii test file." + (let* ((out (if (eq out t) *standard-output* out))) + (flet ((printit (out) + (if (scalar? a) + (prin1 a out) + (progn + (format out "~&") + (dotimes (i (rows a)) + (dotimes (j (cols a)) + (format out fmt (mref a i j)) + (when (< j (1- (cols a))) + (princ dlm out))) + (when (< i (1- (rows a))) + (princ #\Newline out))))))) + (if (streamp out) + (printit out) + (with-open-file (out out :direction :output :if-exists :supersede) + (printit out)))))) + +#+nil (defun dlmread (class &optional (in t)) + "Reads a delimited anscii test file and returns a matrix. Currently only space delimited." + ;; TODO: Fixit. Non-space formated matrices + (let* ((in (if (eq in t) *standard-input* in)) + (end (gensym)) + (rows nil)) + (labels ((line (in) (let ((line (read-line in nil end nil))) + (if (eq line end) + end + (if (eql (char line 0) #\#) + (line in) + line)))) + (element (in) (read in nil end nil)) + (getit (in) + (do ((line (line in) (line in))) + ((eq line end)) + (let ((s (make-string-input-stream line)) + (cols nil)) + (do ((elm (element s) (element s))) + ((eq elm end)) + (push elm cols)) + (push (reverse cols) rows))))) + (if (streamp in) + (getit in) + (with-open-file (in in :direction :input) + (getit in)))) + (convert (reverse rows) class))) Modified: src/linalg/level3-linalg-generic.lisp ============================================================================== --- src/linalg/level3-linalg-generic.lisp (original) +++ src/linalg/level3-linalg-generic.lisp Sat Sep 26 14:26:49 2009 @@ -47,6 +47,9 @@ (.* (mref a i k) (mref b k j))))))) c)) +(defmethod m/ ((a matrix-base) (b matrix-base)) + (m* a (minv b))) + (defmethod minv ((a matrix-base)) (minv! (copy a))) Modified: src/test/test-methods.lisp ============================================================================== --- src/test/test-methods.lisp (original) +++ src/test/test-methods.lisp Sat Sep 26 14:26:49 2009 @@ -24,7 +24,7 @@ (c %i) (x (dmat (1 2) (3 4))) (y (zmat (1 2) (3 4))) - (w (mat 'matrix-ge (1 2) (3 4))) + (w (mmat 'matrix-ge (1 2) (3 4))) (args (list a b c x y w))) (mapc (lambda (fun) (mapc (lambda (x) @@ -99,7 +99,7 @@ (b (zmat (1 2) (3 5))) (c (dmat (1 2 -1) (3 4 9) (1 1 1))) (d (zmat (1 2 2.1) (3 5 %i) (-%i %i -%i))) - (x (mat 'matrix-ge (1 2 2.1) (3 5 %i) (-%i %i -%i))) + (x (mmat 'matrix-ge (1 2 2.1) (3 5 %i) (-%i %i -%i))) (args (list a b c d x))) (mapc (lambda (x) (simple-non-nil-check #'mtp (list x))) args) (mapc (lambda (x) (simple-non-nil-check #'mct (list x))) args) From jivestgarden at common-lisp.net Sun Sep 27 17:08:56 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sun, 27 Sep 2009 13:08:56 -0400 Subject: [lisplab-cvs] r97 - doc/www Message-ID: Author: jivestgarden Date: Sun Sep 27 13:08:55 2009 New Revision: 97 Log: Updated web page Modified: doc/www/index.html Modified: doc/www/index.html ============================================================================== --- doc/www/index.html (original) +++ doc/www/index.html Sun Sep 27 13:08:55 2009 @@ -1,103 +1,210 @@ - - + - - LISPLAB project - - + + + + +LISPLAB project + -
-

Lisplab

-

A mathematics library for Common Lisp

-
-
-

Introduction

-

- Lisplab is a mathematics library in Common Lisp - released under the GNU General Public License (GPL). - Lisplab is based on code from Matlisp, - but has now moved quite far from the original code mass. -

- The main purpose of Lisplab is to provide a framwork for - mathematical computations. This means that it should be easy - to create and manipulate mathematical objects and have - a consistent naming of methods and classes. - Lisplab is heavily based on CLOS. -

- Lisplab contains -
    -
  • Interfaces to BLAS and LAPACK. -
  • Interface to FFTW. -
  • Numerical integration from QUADPACK and F2CL. -
  • Special functions from SLATEC and F2CL. -
  • Routines for linear algebra, +
    +

    Lisplab

    +

    A mathematics library for Common Lisp

    +
    +

    + Lisplab is a mathematics library in Common Lisp + released under the GNU General Public License (GPL). + Lisplab is based on code from Matlisp, + but has now moved quite far from the original code mass. +

    + The main purpose of Lisplab is to provide a framwork + for mathematical computations. This means that it should be easy + to create and manipulate mathematical objects and that naming + of classes and functions should be consistent and clear. + Lisplab is heavily based on CLOS. +

    + Lisplab contains +
      +
    • Interfaces to BLAS and LAPACK.
    • +
    • Interface to FFTW.
    • +
    • Numerical integration from QUADPACK and F2CL.
    • +
    • Special functions from SLATEC and F2CL.
    • +
    • Routines for linear algebra, postscript output, PGM output, - Fast Fourier Transform (in Common Lisp), infix math, etc. -
    -

    -

    - The part of Lisplab which is most mature is the matrix and linear algebra, - and these should provide a good basis for matrix based modelling. -

    - -

    Documentation

    -

    - The manual is in - - html - and in - - pdf. - There is also - - module documentation, made with - Tinaa. -

    - -

    Mailing Lists

    -

    -

    -

    - -

    Download

    -

    - This project has no stable releases. For latest unstable - code please checkout from Subversion. -

    - -

    Subversion

    -

    - You can get the latest version of the source code from subversion -

    -   svn checkout svn://common-lisp.net/project/lisplab/svn lisplab
    - or browse it - - here. -

    -
    -
    - - + Fast Fourier Transform (native Common Lisp), infix math, etc.
  • +
+

+

+ The part of Lisplab which is most mature is the matrix and linear algebra, + and these should provide a good basis for matrix based modelling. +

+ +

Installing

+

+ Lisplab is installed by asdf. + The external libraries, BLAS, LAPACK, and FFTW must be installed separately. + They make Lisplab more powerful, but it also makes sense to run it + without external libraries. + Lisplab does not depend on any other Common Lisp projects, but will only + compile out-of-the-box for SBCL and + for other Lisps you must expect some hacking. +

+

+ See + + manual for details. +

+ +

Getting started

+ On SBCL, make sure that asdf:*central-registry* + contains lisplab.asd. Then you install it by +
   > (require :lisplab)
and use it by +
   > (use-package :ll-user)
+ When started, you can do +
  LL-USER> (.^ (dmat (1 2) (3 4)) 2)
+  #<MATRIX-DGE  2x2
+    1.0 4.0 
+    9.0 16.0 
+  {B7E3E71}>
Common operations are +
  .+ .- .* ./ .^ 
+  .expt .sqrt .log
+  .sin .cos .tan .asin .acos .atan
+  .sinh .cosh .tanh .asinh .acosh .atanh
+  .besj .besy .besi .besk .besh 
+  .gamma .erf .erfc
+  mref vref 
+  size dim rows cols rank
+  mmap
+  make-matrix-instance
+  dnew dmat dcol drow
+  znew zmat zcol zrow
+  mnew mmat mcol mrow
+  mmax mmin circ-shift pad-shift
+  m* m/ minv mtp mct 
+  eivenvalues eigenvectors 
+  dlmread dlmwrite pswrite pgmwrite
+  export-list import-list
+  fftw1 ifftw1 
+  fftw2 ifftw2 
+  fft-shift ifft-shift
+  rk4 euler
+  w/infix
+ +

Performance

+

+ Performance should be quite good (at least on SBCL) since Lisplab's main + usage has been to solve partial differential equations in physics. +

+

+ The graph below compares matrix inversion scalability between + the Lapack FFI, and two native implementations: one typed and one untyped. + All graphs scale as O(n3), + but we see that the untyped version is hopelessly slow, while the typed + version is a factor 10 slower than Lapack, which is rather good, and means + that it is usable for high performance computing. +

+ + +
+

Documentation

+

+ The manual is in + + html + and in + + pdf. +

+

+ + Module documentation is generated with + Tinaa. +

+ + +

Download

+

+ Tarballs are here. +

+ +

Subversion

+

+ You can + + browse the svn repository or check out the latest development + tree from anonymous svn, +

+  % svn checkout svn://common-lisp.net/project/lisplab/svn lisplab
+

+ +

Mailing Lists

+

+

+

+ +
+

Links

+ Other mathematics resources for Common Lisp + + +
+ + From jivestgarden at common-lisp.net Sun Sep 27 17:49:23 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Sun, 27 Sep 2009 13:49:23 -0400 Subject: [lisplab-cvs] r98 - Message-ID: Author: jivestgarden Date: Sun Sep 27 13:49:22 2009 New Revision: 98 Log: finsish before v010 Modified: Makefile package.lisp Modified: Makefile ============================================================================== --- Makefile (original) +++ Makefile Sun Sep 27 13:49:22 2009 @@ -1,9 +1,17 @@ +TARDIR=lisplab-0.1.0 + # Makefile for admin tasks .PHONY: first, manual, touch, lispclean, clean, distclean first: echo "Please specify target." +tar: + mkdir /var/tmp/$(TARDIR) + -cp -r . /var/tmp/$(TARDIR) + -cd /var/tmp/ && tar czf $(TARDIR).tgz $(TARDIR) + -rm -rf /var/tmp/$(TARDIR) + manual: make -C"doc/manual" all Modified: package.lisp ============================================================================== --- package.lisp (original) +++ package.lisp Sun Sep 27 13:49:22 2009 @@ -128,6 +128,7 @@ "MATRIX-DGE" "MATRIX-ZGE" "FUNCTION-MATRIX" + "MATRIX-SPARSE" "*LISPLAB-PRINT-SIZE*" ;; Matrix level 1 methods "MAKE-MATRIX-INSTANCE" From jivestgarden at common-lisp.net Wed Sep 30 18:25:42 2009 From: jivestgarden at common-lisp.net (=?UTF-8?Q?J=C3=B8rn_Inge_Vestg=C3=A5rden?=) Date: Wed, 30 Sep 2009 14:25:42 -0400 Subject: [lisplab-cvs] r99 - src/matrix Message-ID: Author: jivestgarden Date: Wed Sep 30 14:25:41 2009 New Revision: 99 Log: views Removed: src/matrix/level2-funmat.lisp Modified: lisplab.asd package.lisp src/matrix/level2-constructors.lisp src/matrix/level2-interface.lisp src/matrix/level2-view.lisp Modified: lisplab.asd ============================================================================== --- lisplab.asd (original) +++ lisplab.asd Wed Sep 30 14:25:41 2009 @@ -75,7 +75,7 @@ (:file "level2-matrix-dge") (:file "level2-matrix-zge") (:file "level2-array-functions") - (:file "level2-funmat") + (:file "level2-view") (:file "level2-list") )) Modified: package.lisp ============================================================================== --- package.lisp (original) +++ package.lisp Wed Sep 30 14:25:41 2009 @@ -178,8 +178,6 @@ "VIEW-ROW" "VIEW-COL" "VIEW-MATRIX" - "VIEW-MATRIX-AS-VECTOR" - "VIEW-VECTOR-AS-MATRIX" "VIEW-TRANSPOSE" "MSUM" "MMIN" Modified: src/matrix/level2-constructors.lisp ============================================================================== --- src/matrix/level2-constructors.lisp (original) +++ src/matrix/level2-constructors.lisp Wed Sep 30 14:25:41 2009 @@ -110,7 +110,7 @@ For example: (drange 4 0 1) -> 0 1 2 3, while (drange 4 0 1 0.5) -> 0.5 1.5 2.5 3.5." (let ((x (dnew 0 n 1)) - (dx (./ (.- to from)))) + (dx (./ (.- to from) N))) (dotimes (i n) (setf (vref x i) (.+ from (.* dx (.+ i shift))))) x)) Modified: src/matrix/level2-interface.lisp ============================================================================== --- src/matrix/level2-interface.lisp (original) +++ src/matrix/level2-interface.lisp Wed Sep 30 14:25:41 2009 @@ -94,12 +94,6 @@ (defgeneric view-matrix (matrix dim &optional (type)) (:documentation "Returns a shared structure view of the matrix")) -(defgeneric view-matrix-as-vector (a) - (:documentation "Returs a vector with same (shared) elements as the matrix")) - -(defgeneric view-vector-as-matrix (a rows) - (:documentation "Returns a matrix with the same (shared) elements as the vector")) - (defgeneric view-transpose (a) (:documentation "Returns a transposed matrix with same (shared) elements")) Modified: src/matrix/level2-view.lisp ============================================================================== --- src/matrix/level2-view.lisp (original) +++ src/matrix/level2-view.lisp Wed Sep 30 14:25:41 2009 @@ -19,7 +19,8 @@ (in-package :lisplab) -#+todo-make-this(defmethod view-matrix (matrix shape &optional (type)) + +(defmethod view-matrix (matrix shape &optional (type)) "Outputs a function matrix" (declare (ignore type)) (let* ((rows (car shape)) @@ -28,8 +29,6 @@ (make-instance 'function-matrix :rows rows :cols cols - :size size - :element-type (element-type matrix) :mref #'(lambda (x i j) (declare (ignore x)) (vref matrix (column-major-idx i j rows))) @@ -42,46 +41,43 @@ :set-vref #'(lambda (value x i) (declare (ignore x)) (setf (vref matrix i) value))))) - (defmethod view-row (matrix row) - "Outputs a function matrix." - (make-instance - 'function-matrix - :rows (cols matrix) - :cols 1 - :mref #'(lambda (x i j) - (declare (ignore x j)) - (mref matrix row i)) - :set-mref #'(lambda (value x i j) - (declare (ignore x i)) - (setf (mref matrix row j) value)) - :vref #'(lambda (x i) - (declare (ignore x)) - (mref matrix row i)) - :set-vref #'(lambda (value x i) - (declare (ignore x)) - (setf (mref matrix row i) value)))) + "Outputs a function matrix" + (make-instance 'function-matrix + :rows 1 + :cols (cols matrix) + :mref #'(lambda (x i j) + (declare (ignore x i)) + (mref matrix row j)) + :set-mref #'(lambda (value x i j) + (declare (ignore x j)) + (setf (mref matrix row i) value)) + :vref #'(lambda (x i) + (declare (ignore x)) + (mref matrix row i)) + :set-vref #'(lambda (value x i) + (declare (ignore x)) + (setf (mref matrix row i) value)))) (defmethod view-col (matrix col) - "Outputs a function matrix." - (make-instance - 'function-matrix - :rows (rows matrix) - :cols 1 - :mref #'(lambda (x i j) - (declare (ignore x j)) - (mref matrix i col)) - :set-mref #'(lambda (value x i j) - (declare (ignore x j)) - (setf (mref matrix i col) value)) - :vref #'(lambda (x i) - (declare (ignore x)) - (mref matrix i col)) - :set-vref #'(lambda (value x i) - (declare (ignore x)) - (setf (mref matrix i col) value)))) + "Outputs a function matrix" + (make-instance 'function-matrix + :rows (rows matrix) + :cols 1 + :mref #'(lambda (x i j) + (declare (ignore x j)) + (mref matrix i col)) + :set-mref #'(lambda (value x i j) + (declare (ignore x j)) + (setf (mref matrix i col) value)) + :vref #'(lambda (x i) + (declare (ignore x)) + (mref matrix i col)) + :set-vref #'(lambda (value x i) + (declare (ignore x)) + (setf (mref matrix i col) value)))) -#+todo-make-this(defmethod view-transpose (matrix) +(defmethod view-transpose (matrix) "Outputs a function matrix" (make-instance 'function-matrix :rows (cols matrix) @@ -101,7 +97,3 @@ (declare (ignore x)) (setf (vref matrix i) value)))) - - - -