1 ;; amatrix.lisp -- implement Maxima matrix via underlying Lisp array
2 ;; copyright 2007 by Robert Dodier
3 ;; I release this file under the terms of the GNU General Public License.
5 (setf (get '$amatrix
'$present
) t
)
7 (declare-top (unspecial x
))
9 (defun $amatrixmap
(f &rest m
)
11 ((nr ($nrows
(car m
)))
13 (m1 (mfuncall '$make_matrix nr nc
))
14 (a1 (get ($
@-function m1
'$storage
) 'storage_array
)))
22 ((a0 (get ($
@-function m0
'$storage
) 'storage_array
))
23 (ij (mfuncall '$compute_index0 m0 i j
)))
26 (x (mapply1 f args f nil
)))
27 (setf (aref a1
(mfuncall '$compute_index0 m1 i j
)) x
))))
30 (putprop '$amatrix
'amatrix-assign
'mset_extension_operator
)
32 (defun amatrix-assign (e x
)
34 ((my-amatrix-name (caar e
))
35 (my-amatrix (symbol-value (caar e
))))
39 ((= ($nrows my-amatrix
) 1)
40 (amatrix-assign1 my-amatrix-name my-amatrix
1 (meval (cadr e
)) x
))
41 ((= ($ncols my-amatrix
) 1)
42 (amatrix-assign1 my-amatrix-name my-amatrix
(meval (cadr e
)) 1 x
))
44 (merror "amatrix assignment: given one subscript, but expected two"))))
46 (amatrix-assign1 (caar e
) (symbol-value (caar e
)) (meval (cadr e
)) (meval (caddr e
)) x
))
48 (merror "amatrix assignment: expected one or two subscripts")))))
50 (defun amatrix-assign1 (lhs aa i j x
)
51 (when (> (get ($
@-function aa
'$storage
) 'refcount
) 1)
53 (putprop a
1 'refcount
)
54 (putprop a
(mfuncall '$copy_array
(get ($
@-function aa
'$storage
) 'storage_array
)) 'storage_array
)
55 (decf (get ($
@-function aa
'$storage
) 'refcount
))
56 (mrecord-assign `(($
@) ,lhs $storage
) a
)))
58 ((and (integerp i
) (integerp j
))
59 (amatrix-assign1-row-column aa i j x
))
60 ((and (eq i
'$all
) (integerp j
))
61 (amatrix-assign1-all-column aa j x
))
62 ((and (integerp i
) (eq j
'$all
))
63 (amatrix-assign1-row-all aa i x
))
64 ((and (eq i
'$all
) (eq j
'$all
))
65 (amatrix-assign1-all-all aa x
))
66 ((and ($listp i
) (integerp j
))
67 (amatrix-assign1-list-integer aa i j x
))
68 ((and (integerp i
) ($listp j
))
69 (amatrix-assign1-integer-list aa i j x
))
70 ((and ($listp i
) (eq j
'$all
))
71 (amatrix-assign1-list-all aa i x
))
72 ((and (eq i
'$all
) ($listp j
))
73 (amatrix-assign1-all-list aa j x
))
74 ((and ($listp i
) ($listp j
))
75 (amatrix-assign1-list-list aa i j x
))
77 `((mset) ((,aa array
) ,i
,j
) ,x
))))
79 (defun amatrix-assign1-row-column (aa i j x
)
81 ((a (get ($
@-function aa
'$storage
) 'storage_array
))
82 (ij (1- (mfuncall '$compute_index1 aa i j
))))
83 (setf (aref a ij
) x
)))
85 (defun amatrix-assign1-all-column (aa j x
)
86 (let ((m ($
@-function aa
'$nr
)))
88 ;; MIGHT WANT TO ENSURE THAT X HAS SAME NUMBER OF ROWS AS AA AND EXACTLY ONE COLUMN
90 (amatrix-assign1-row-column aa
(1+ i
) j
(mfuncall '$get_element x
(1+ i
) 1)))
92 (amatrix-assign1-row-column aa
(1+ i
) j x
))))
95 (defun amatrix-assign1-row-all (aa i x
)
96 (let ((n ($
@-function aa
'$nc
)))
98 ;; MIGHT WANT TO ENSURE THAT X HAS EXACTLY ONE ROW AND SAME NUMBER OF COLUMNS AS AA
100 (amatrix-assign1-row-column aa i
(1+ j
) (mfuncall '$get_element x
1 (1+ j
))))
102 (amatrix-assign1-row-column aa i
(1+ j
) x
))))
105 (defun amatrix-assign1-all-all (aa x
)
107 ((m ($
@-function aa
'$nr
))
108 (n ($
@-function aa
'$nc
)))
110 ;; MIGHT WANT TO ENSURE THAT X HAS SAME NUMBER OF ROWS AND COLUMNS AS AA
113 (amatrix-assign1-row-column aa
(1+ i
) (1+ j
) (mfuncall '$get_element x
(1+ i
) (1+ j
)))))
116 (amatrix-assign1-row-column aa
(1+ i
) (1+ j
) x
)))))
119 (defun amatrix-assign1-list-integer (aa l j x
)
120 (amatrix-assign1-list-list aa l
`((mlist) ,j
) x
))
122 (defun amatrix-assign1-integer-list (aa i l x
)
123 (amatrix-assign1-list-list aa
`((mlist) ,i
) l x
))
125 (defun amatrix-assign1-list-all (aa l x
)
128 (n ($
@-function aa
'$nc
)))
130 ;; MIGHT WANT TO ENSURE THAT X HAS SAME NUMBER OF ROWS AND COLUMNS AS AA
133 (amatrix-assign1-row-column aa
(nth (1+ i
) l
) (1+ j
) (mfuncall '$get_element x
(1+ i
) (1+ j
)))))
136 (amatrix-assign1-row-column aa
(nth (1+ i
) l
) (1+ j
) x
)))))
139 (defun amatrix-assign1-all-list (aa l x
)
141 ((m ($
@-function aa
'$nr
))
144 ;; MIGHT WANT TO ENSURE THAT X HAS SAME NUMBER OF ROWS AND COLUMNS AS AA
147 (amatrix-assign1-row-column aa
(1+ i
) (nth (1+ j
) l
) (mfuncall '$get_element x
(1+ i
) (1+ j
)))))
150 (amatrix-assign1-row-column aa
(1+ i
) (nth (1+ j
) l
) x
)))))
153 (defun amatrix-assign1-list-list (aa l1 l2 x
)
158 ;; MIGHT WANT TO ENSURE THAT X HAS SAME NUMBER OF ROWS AND COLUMNS AS AA
161 (amatrix-assign1-row-column
165 (mfuncall '$get_element x
(1+ i
) (1+ j
)))))
168 (amatrix-assign1-row-column
175 ;; UNFINISHED STUFF. SORRY, I'M WORKING ON IT.
177 (defun amatrix-assign1-amatrix-column (aa ai j x
) (declare (ignore aa ai j x
)))
179 (defun amatrix-assign1-row-amatrix (aa i aj x
) (declare (ignore aa i aj x
)))
181 (defun amatrix-assign1-amatrix-amatrix (aa ai aj x
) (declare (ignore aa ai aj x
)))
183 (defun amatrix-assign1-boolean-column (aa b j x
) (declare (ignore aa b j x
)))
185 (defun amatrix-assign1-row-boolean (aa i b x
) (declare (ignore aa i b x
)))
187 (defun amatrix-assign1-boolean-boolean (aa b1 b2 x
) (declare (ignore aa b1 b2 x
)))
189 (displa-def $amatrix dim-$amatrix
)
191 ; CALL SIMPLIFYA IN DIM-$NEWMATRIX BECAUSE DIM-$MATRIX NEEDS TO SEE SIMP FLAG ... SIGH
193 (defun dim-$amatrix
(form result
)
195 ((nr ($
@-function form
'$nr
))
196 (r0 ($
@-function form
'$r0
))
197 (rinc ($
@-function form
'$rinc
))
198 (nc ($
@-function form
'$nc
))
199 (c0 ($
@-function form
'$c0
))
200 (cinc ($
@-function form
'$cinc
))
201 (storage ($
@-function form
'$storage
)))
211 (arrayp (get storage
'storage_array
)))
212 (if (or (= nr
0) (= nc
0))
213 (dimension-function '(($amatrix simp
)) result
)
217 `((lambda) ((mlist) i j
) (mfuncall '$get_element
,form i j
))
218 ($
@-function form
'$nr
)
219 ($
@-function form
'$nc
))
222 (dimension-function form result
))))
225 (and (not ($atom a
)) (eq ($op a
) '$amatrix
)))
237 (defun $amatrix_multiply
(m1 m2
)
238 (let ((nc1 ($ncols m1
)) (nr2 ($nrows m2
)))
240 ((and (integerp nc1
) (integerp nr2
))
241 (if (eql ($ncols m1
) ($nrows m2
))
246 (a1 (get ($
@-function m1
'$storage
) 'storage_array
))
247 (a1-inc ($
@-function m1
'$cinc
))
249 (a2 (get ($
@-function m2
'$storage
) 'storage_array
))
250 (a2-inc ($
@-function m2
'$rinc
)))
251 (setf (get aa
'storage_array
) (make-array (* nr nc
) :initial-element
0))
255 ((a1-base (mfuncall '$compute_index0 m1 i
0))
256 (a2-base (mfuncall '$compute_index0 m2
0 j
)))
258 (aref (get aa
'storage_array
) (+ i
(* j nr
)))
259 (dot nn a1 a1-base a1-inc a2 a2-base a2-inc
)))))
260 `(($amatrix
) ,nr
0 1 ,nc
0 ,nr
,aa
0))
261 (merror "amatrix_multiply: inconformable operands")))
263 `((mnctimes) ,m1
,m2
)))))
265 (defun dot (n a a0 ainc b b0 binc
)
266 (let ((ai a0
) (bi b0
) (sum 0))
269 sum
(+ sum
(* (aref a ai
) (aref b bi
)))