<?xml version="1.0"?>
<paste-with-annotations>
  <paste>
    <number>
      <integer>82956</integer>
    </number>
    <user>
      <string>tmh</string>
    </user>
    <title>
      <string>leo2007 - Destructive Matrix OP</string>
    </title>
    <contents>
      <string>;;; Something like this
(define-test destructive-matrix-op
  (let* ((matrix (generate-matrix ...)))
    (destructive-matrix-op matrix ...)
    (assert-numerical-equal
     exact-matrix matrix)))

;;; As a design note, most destructive operations still return the
;;; modified object. So, it would be good if DESTRUCTIVE-MATRIX-OP
;;; return the matrix.
</string>
    </contents>
    <universal-time>
      <integer>3455621820</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string>Common Lisp</string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </paste>
  <annotation>
    <number>
      <integer>5</integer>
    </number>
    <user>
      <string>tmh</string>
    </user>
    <title>
      <string>leo2007 : MAP-MATRIX and MAP-INTO-MATRIX</string>
    </title>
    <contents>
      <string>;;; Lightly tested; needs to be factored; generally models MAP and MAP-INTO
(defun %validate-dimensions (matrix matrices)
  &quot;Return the dimensions validating that all are equal.&quot;
  (if (= 2 (array-rank matrix))
      (let ((dimensions (array-dimensions matrix)))
        (dolist (mat matrices dimensions)
          (unless (equal dimensions (array-dimensions mat))
            (error &quot;Unequal matrix dimensions.&quot;))))
      (error &quot;Matrix rank, ~S, does not equal 2.&quot;
             (array-rank matrix))))

;;; FIXME : The result element type should be set to the most general
;;; type of all of the matrices according to UPGRADED-ARRAY-ELEMENT-TYPE
(defun map-matrix (function matrix &amp;rest matrices)
  &quot;Apply FUNCTION on the elements of matrix.&quot;
  (declare (optimize debug))
  (if matrices
      ;; The function accepts more than one matrix.
      (destructuring-bind (rows columns)
          (%validate-dimensions matrix matrices)
        (let ((arglist (make-list (length matrices)))
              (result  (make-array (list rows columns)
                                   :element-type
                                   (array-element-type matrix))))
          (dotimes (i0 rows result)
            (dotimes (i1 columns)
              (setf
               (aref result i0 i1)
               (apply function
                      (aref matrix i0 i1)
                      (map-into arglist
                                (lambda (mat) (aref mat i0 i1))
                                matrices)))))))
      ;; The function accepts one matrix.
      (destructuring-bind (rows columns)
          (array-dimensions matrix)
        (let ((result (make-array (list rows columns)
                                  :element-type
                                  (array-element-type matrix))))
          (dotimes (i0 rows result)
            (dotimes (i1 columns)
              (setf
               (aref result i0 i1)
               (funcall function (aref matrix i0 i1)))))))))

(defun map-into-matrix (result-matrix function &amp;rest matrices)
  &quot;Apply FUNCTION on the elements of matrix MAT.&quot;
  (if matrices
      ;; The result is built from other matrices.
      (destructuring-bind (rows columns)
          (%validate-dimensions result-matrix matrices)
        (let ((arglist (make-list (length matrices))))
          (dotimes (i0 rows result-matrix)
            (dotimes (i1 columns)
              (setf
               (aref result-matrix i0 i1)
               (apply function
                      (map-into arglist
                                (lambda (mat) (aref mat i0 i1))
                                matrices)))))))
      ;; The result is built from a function.
      (destructuring-bind (rows columns)
          (array-dimensions result-matrix)
        (dotimes (i0 rows result-matrix)
          (dotimes (i1 columns)
            (setf
             (aref result-matrix i0 i1)
             (funcall function)))))))

;;; FIXME : There are some opportunities for abstraction,
;;;         but you get what you pay for.</string>
    </contents>
    <universal-time>
      <integer>3455629013</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </annotation>
  <annotation>
    <number>
      <integer>4</integer>
    </number>
    <user>
      <string>leo2007</string>
    </user>
    <title>
      <string>untitled</string>
    </title>
    <contents>
      <string>(defun map-matrix (function first-matrix &amp;rest more-matrixes)
  &quot;Apply FUNCTION on the elements of matrix.&quot;
  (let ((result (make-array (array-dimensions first-matrix))))
    (handler-case
        (loop for i below (array-total-size first-matrix)
           do (setf (row-major-aref result i)
                    (apply function
                           (row-major-aref first-matrix i)
                           (mapcar (lambda (m)
                                     (row-major-aref m i))
                                   more-matrixes)))
           finally (return result))
      (error nil
        (format t &quot;Matrix size does not match or too few arguments&quot;)
        (return-from map-matrix nil)))))

(defun map-matrix! (function result-matrix &amp;rest more-matrixes)
  &quot;Apply FUNCTION on the elements of matrix MAT.&quot;
  (handler-case
      (loop for i below (array-total-size result-matrix)
         do (setf (row-major-aref result-matrix i)
                  (apply function
                         (row-major-aref result-matrix i)
                         (mapcar (lambda (m)
                                   (row-major-aref m i))
                                 more-matrixes)))
         finally (return result-matrix))
    (error nil 
      (format t &quot;Matrix size does not match or too few arguments&quot;)
      (return-from map-matrix! nil))))
</string>
    </contents>
    <universal-time>
      <integer>3455623341</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </annotation>
  <annotation>
    <number>
      <integer>3</integer>
    </number>
    <user>
      <string>tmh</string>
    </user>
    <title>
      <string>leo2007 - Use MAKE-ARRAY</string>
    </title>
    <contents>
      <string>(define-test map-matrix!-test
  (let ((matrix (make-array '(2 2) :initial-contents
                            '((1 2)
                              (3 4)))))
    (map-matrix! #'sin matrix)
    (assert-numerical-equal
     #2A((0.841470985 0.909297427)
         (0.141120001 -0.756802495))
     matrix)))</string>
    </contents>
    <universal-time>
      <integer>3455622558</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </annotation>
  <annotation>
    <number>
      <integer>2</integer>
    </number>
    <user>
      <string>leo2007</string>
    </user>
    <title>
      <string>untitled</string>
    </title>
    <contents>
      <string>(define-test map-matrix!-test
  (let ((matrix #2A((1 2) (3 4))))
    (map-matrix! #'sin matrix)
    (assert-numerical-equal
     #2A((0.841470985 0.909297427)
         (0.141120001 -0.756802495))
     matrix)))</string>
    </contents>
    <universal-time>
      <integer>3455622441</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </annotation>
  <annotation>
    <number>
      <integer>1</integer>
    </number>
    <user>
      <string>leo2007</string>
    </user>
    <title>
      <string>untitled</string>
    </title>
    <contents>
      <string>MONTE-CARLO-TEST&gt; (run-tests)
MAP-MATRIX!-TEST: 1 assertions passed, 0 failed.
MAP-MATRIX-TEST: 1 assertions passed, 0 failed.
MATRIX-TEST: 8 assertions passed, 0 failed.
TOTAL: 10 assertions passed, 0 failed, 0 execution errors.
; No value
MONTE-CARLO-TEST&gt; (run-tests)
MAP-MATRIX!-TEST: MATRIX failed: 
Expected #2A((0.84147096 0.9092974) (0.14112 -0.7568025)) 
but saw #2A((0.7456241 0.78907233) (0.14065208 -0.68660027))
MAP-MATRIX!-TEST: 0 assertions passed, 1 failed.
MAP-MATRIX-TEST: 1 assertions passed, 0 failed.
MATRIX-TEST: 8 assertions passed, 0 failed.
TOTAL: 9 assertions passed, 1 failed, 0 execution errors.
</string>
    </contents>
    <universal-time>
      <integer>3455622079</integer>
    </universal-time>
    <channel>
      <string>#lisp</string>
    </channel>
    <colorization-mode>
      <string></string>
    </colorization-mode>
    <maybe-spam>
      <null/>
    </maybe-spam>
    <is-unicode>
      <keyword>TRUE</keyword>
    </is-unicode>
    <deletion-requested>
      <null/>
    </deletion-requested>
    <deletion-requested-email>
      <null/>
    </deletion-requested-email>
    <expiration-time>
      <null/>
    </expiration-time>
  </annotation>
</paste-with-annotations>
