6 (defparameter smarkup::*document-thesis* nil)
7 (smarkup::setup-headings)
12 "Copyright 2006, Cyrus Harmon. All Rights Reserved.")
13 (:title "clem: A common-lisp matrix package")
14 (:author "Cyrus L. Harmon")
16 "(\"asdf:/ch-bib/lisp\" \"asdf:/ch-bib/bio\")")
17 (:bibtex-style "Science"))
18 (:html-metadata (:htmlcss "simple.css") )
21 "(asdf:operate 'asdf:load-op 'clem)"
22 "(setf smarkup::*baseline-skip* \"14pt\")"
23 "(setf smarkup::*par-skip* \"0pt\")")
28 (:p "CLEM is an open-source Common Lisp library for the
29 representation and manipulation of matrices. CLEM is designed to
30 be a flexible and extensible system for the representation of
31 arbitrary 2-dimensional matrices."))
35 (:p "The Common Lisp language"
36 (:bibcite "steele1990common")
37 " offers a rich, dynamic environment for programming and
38 data analysis. Common Lisp contains a powerful object system, the
39 Common Lisp Object System (CLOS)"
40 (:bibcite "keene1989object")
41 ", and most modern implementations support a protocol for
42 the generation not just of new classes and objects, but to extend
43 the object system itself using the Meta-object Protocol"
44 (:bibcite "kiczales1991art")
47 (:p "CLEM uses CLOS and the Meta-object protocol (MOP) to define a"
48 (:code "standard-matrix-class")
49 " that serves as the metaclass for classes that represent
50 matrices with elements of specific types. The typed matrices can
51 represent matrices containing values of specific types in the
52 Common Lisp type system, starting with type "
54 " as the most general data type, and becoming more restrictive by using more specific types such"
55 (:code "double-float")
59 (:code "(unsigned-byte 8)")
60 ". By using the most specific type that can represent the values of a given matrix, the lisp system can optimize for better performance and memory usage requirements. For example, a "
62 " will use 1 bit per matrix element, rather than 32-bits on 32-bit systems for a "
68 (:h2 "Matrix Representation")
70 (:p "Common Lisp provides a rich built-in array type which serves as
71 the storage for CLEM matrices. Given that Common Lisp has built-in
72 arrays, why do we need CLEM and what value is provided by creating a
73 set of classses around arrays? First, the Common Lisp arrays have a
74 limited set of operations defined on them. While there is a built-in
75 (scalar) addition operator, there is no built-in way to perform an
76 element-wise addition of two arrays. CLEM addresses these by defining
77 a set of generic functions that operate on matrices that provide a
78 number of commonly used matrix operations such as matrix
79 arithmetic. Second, there is no way to define methods on arrays based
80 on their element types. Therefore, we define subclasses of matrix
81 whose underlying arrays are specialized to distinct types. We can
82 then define methods to operate specifically on these subclasses,
83 affording the opportunity to treat, say, floating point and integer
84 matrices differently and to provide declarations to the compiler
85 based on the array element type, which can, in Common Lisp
86 implementations with sufficiently smart compilers, lead to much
87 improved performance.")
89 (:h1 "Defining CLEM Classes and Making CLEM Instances")
91 (:h2 "Creating CLEM Instances with make-instance")
93 (:p "The following code creates a 16-row by 16-column matrix of type"
94 (:code "double-float-matrix")
95 " and assigns it to the dynamic variable"
100 (make-instance 'clem:double-float-matrix :rows 16 :cols 16))"
103 (:p "The default is to only show the first 7 and the last rows
104 and columns of each matrix. The number of rows and columns can
105 be changed by setting the "
106 (:code "*matrix-print-row-limit*")
108 (:code "*matrix-print-col-limit*")
111 (:h2 "standard-matrix-class")
112 (:h2 "CLEM Matrix Types")
114 (:h3 "Number matrices")
116 (:p "The most general class of numerical matrix is the number matrix.")
118 (:h3 "Integer Matrices")
120 (:h3 "Floating-point Matrices")
122 (:h3 "Complex-value Matrices")
124 (:h1 "Working with CLEM Matrices")
126 (:h2 "Matrix Dimensions and Values")
128 (:h2 "Typed matrix operations")
130 (:h2 "Matrix Copying")
134 (:h1 "Matrix Arithmetic")
136 (:h2 "Matrix Addition and Subtraction")
138 (:h2 "Matrix Multiplication")
140 (:h2 "Hadamard Product")
142 (:h2 "Scalar Arithmetic")
144 (:h2 "Other Mathematical Functions")
146 (:p "Discuss mat-log, mat-abs, min, and max.")
148 (:h1 "Matrix Operations")
150 (:h2 "Matrix Inversion")
152 (:h2 "Matrix Normalization")
154 (:h2 "Discrete Convolution")
158 (:h3 "Gradient Magnitude")
160 (:h3 "Gaussian Blur")
162 (:h2 "Affine Transformations")
164 (:h3 "Interpolation")
166 (:h2 "Morphological Operations")
168 (:h3 "Dilation and Erosion")
174 (:h1 "CLEM Implementation Details")
176 (:h2 "Type-specific matrix functions")
178 (:p "The general strategy has been to 1) make things work and
179 then make them work quickly. To this end, I have been writing
180 functions for matrix operations in a general manner first and
181 then recoding type-specific versions to make certain operations
182 go faster. This is done via liberal use of macros to generate
183 type-specific functions and methods for matrix operations that
184 go much faster than the general versions.")
186 (:p "The convention is that a generic function such as sum-range
187 will have a generic version that works with all matrices and
188 type specific versions thaqt work with specific matrices. g In
189 order to support these functions there may be internal methods,
190 prefixed with a %, that implement certain type-specific
191 functionality. Macros that generate the code used for the
192 type-specific methods will be prefixed with a %%. In theory,
193 the %%-macros can be called from other code that need to
194 generate in-place code where the overhead of the method-call to
195 the %-method would be too expensive. This convention is not yet
196 widely enforced and certainly untested. Hopefully this situation
199 (:h2 "Hacking the SBCL compiler to improve performance")