need help printing matrix in lisp - rehash

Discussion of Common Lisp
Post Reply
joeish80829
Posts: 153
Joined: Tue Sep 03, 2013 5:32 am

need help printing matrix in lisp - rehash

Post by joeish80829 » Sat Sep 21, 2013 1:27 pm

here is more informationthe ideas you said didnt work...if this is uncouth pls ignore

to make this simple i call

(defparameter a (create-mat 3 3 +32fc1+))

to create a 3x3 matrix - create-mat is a wrapper for opencv's cvCreateMat

the output from that command at repl is

(defparameter a (create-mat 3 3 +32fc1+))
A
CL-OPENCV> a
#.(SB-SYS:INT-SAP #X7FFFD8000E00)

i/e the variable a is a pointer to the 3x3 matrix

then i run

(defparameter data (cffi:foreign-alloc :float :initial-contents
'(0.0f0 1.0f0 2.0f0 3.0f0 4.0f0 5.0f0 6.0f0 7.0f0 8.0f0)))

to create the data for the matrix - which i next will allocate to the matrix

the output from that command at repl is

CL-OPENCV> (defparameter data (cffi:foreign-alloc :float :initial-contents
'(0.0f0 1.0f0 2.0f0 3.0f0 4.0f0 5.0f0 6.0f0 7.0f0 8.0f0)))
DATA
CL-OPENCV> data
#.(SB-SYS:INT-SAP #X7FFFD8000E40)

i/e the variable a is data pointer to the data ill add to the matrix

then i call..

(set-data a data 12) to add the data to the matrix - set-data is a wrapper for opencv's cvSetData

so now when i run - (get-real-2d is a wrapper for opencv's cvGetReal2d)

(get-real-2d a 0 0) it gets the element of matrix a at row 0 col 0 which is 0.0d0

the output from that command at repl is

CL-OPENCV> (get-real-2d a 0 0)
0.0d0


and now when i run

(get-real-2d a 0 1) it gets the element of matrix a at row 0 col 1 which is is 0.0d0

the output from that command at repl is

CL-OPENCV> (get-real-2d a 0 1)
1.0d0

and when i run this loop

(dotimes (i 3)
(dotimes (j 3)
(format t "~a~%" (get-real-2d a i j))))

the output from that command at repl is

CL-OPENCV> (dotimes (i 3)
(dotimes (j 3)
(format t "~a~%" (get-real-2d a i j))))
0.0d0
1.0d0
2.0d0
3.0d0
4.0d0
5.0d0
6.0d0
7.0d0
8.0d0
NIL

but when i try this method

(dotimes (i 3)
(dotimes (j 3)
(format t "~{~{~a~^ ~}~%~}" (get-real-2d a i j))))


i get error:

The value 0.0d0 is not of type LIST.
[Condition of type TYPE-ERROR]

because the output of 1 run of get-real-2d is just a 1 number float i/e

CL-OPENCV> (get-real-2d a 0 0)
0.0d0

with that info can you help me print the matrix so it looks like this

0.0d0 1.0d0 2.0d0
3.0d0 4.0d0 5.0d0
6.0d0 7.0d0 8.0d0

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: need help printing matrix in lisp - rehash

Post by edgar-rft » Sun Sep 22, 2013 6:23 am

@joeish80829: Please do yourself a favour and learn how to use code tags (Outputting code or fixed width data), you probably will get more and better answers if you're not posting such a mess like your post above. Nobody wants to read unformatted source code. Thank you.

Here is an example of a CL-OPENCV floating-point matrix pretty-printer. The code is a bit antique, maybe somebody with better FORMAT-foo than me can improve it. See CLHS 22.3.3 FORMAT Floating-Point Printers for the related floating-point FORMAT directives.

Code: Select all

(defun print-matrix (matrix rows columns &key (digits 2) (pad 1))
  "Print MATRIX with padded and aligned elements."
  (let ((format-string (format nil "~~,~de" digits))
        (column-width  (make-array columns)) ; initialized with fixnum zeros
        (string-array  (make-array (list rows columns) :initial-element nil)))
    ;; loop 1 - get the column width
    (dotimes (i rows)
      (dotimes (j columns)
        (let ((string (format nil format-string (get-real-2d matrix i j)))
              (width  (aref column-width j)))
          ;; store the string so we don't need to FORMAT it twice
          (setf (aref string-array i j) string)
          ;; update the column-width array
          (setf (aref column-width j) (max width (length string))))))
    ;; loop 2 - print the matrix
    (dotimes (i rows)
      (dotimes (j columns)
        (let ((string (aref string-array i j))
              (width  (aref column-width j)))
          ;; print the formatted matrix element
          (princ string)
          (if (eql j (1- columns))
              ;; after the last element in a row print a line-break
              (terpri)
              ;; if not the last element print whitespace padding
              (princ (make-string (+ pad (- width (length string)))
                                  :initial-element #\Space))))))))
To demonstrate the print-matrix function I'm using a dummy function, so I can use normal Lisp arrays:

Code: Select all

(defun get-real-2d (array row column)
  "Dummy function to access the elements of normal Lisp arrays."
  (aref array row column))
First the example matrix from the post above:

Code: Select all

(defparameter a #2a((0.0d0 1.0d0 2.0d0)
                    (3.0d0 4.0d0 5.0d0)
                    (6.0d0 7.0d0 8.0d0)))

CL-USER> (print-matrix a 3 3)
0.00d+0 1.00d+0 2.00d+0
3.00d+0 4.00d+0 5.00d+0
6.00d+0 7.00d+0 8.00d+0
NIL

CL-USER> (print-matrix a 3 3 :digits 1)
0.0d+0 1.0d+0 2.0d+0
3.0d+0 4.0d+0 5.0d+0
6.0d+0 7.0d+0 8.0d+0
And here a matrix with some real-world floats:

Code: Select all

(defparameter b #2a((3.3563d+50  6.56d+6      2.55460d-154)
                    (2.2542d+242 2.24542d-45  5.0d+7)
                    (6.34956d-3  7.43859d+245 8.3487d-38)))

CL-USER> (print-matrix b 3 3)
3.36d+50  6.56d+6   2.55d-154
2.25d+242 2.25d-45  5.00d+7
6.35d-3   7.44d+245 8.35d-38
NIL

CL-USER> (print-matrix b 3 3 :digits 5 :pad 2)
3.35630d+50   6.56000d+6    2.55460d-154
2.25420d+242  2.24542d-45   5.00000d+7
6.34956d-3    7.43859d+245  8.34870d-38
NIL
:digits n is the number of digits after the dot and :pad n is the number of horizontal space characters between the matrix elements.

Please note that the vertical alignment only works correctly with fixed-width fonts (with proportional fonts it will probably be a mess) and the print-matrix function doesn't test any of its arguments, so with wrong or nonsensical arguments it will probably end up in the debugger.

- edgar

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: need help printing matrix in lisp - rehash

Post by edgar-rft » Sun Sep 22, 2013 6:12 pm

Assuming that the alien array can only be accessed one element at a time and reading 22.3.3.2 Tilde E: Exponential Floating-Point several times again I found that if the exponent is formatted to a constant width of three digits the print-matrix function can be shortened to:

Code: Select all

(defun print-matrix (matrix rows columns &key (digits 2) (pad 1))
  "Print MATRIX with padded and aligned elements."
  (let ((format-string (format nil "~~,~d,3e" digits)))
    (dotimes (i rows)
      (dotimes (j columns)
        (format t format-string (get-real-2d matrix i j))
        (if (eql j (1- columns))
            (terpri)
            (princ (make-string pad :initial-element #\Space)))))))
Using the same dummy function as above:

Code: Select all

(defun get-real-2d (array row column)
  "Dummy function to access the elements in the Lisp arrays."
  (aref array row column))
Here are the results:

Code: Select all

(defparameter a #2a((0.0d0 1.0d0 2.0d0)
                    (3.0d0 4.0d0 5.0d0)
                    (6.0d0 7.0d0 8.0d0)))

CL-USER> (print-matrix a 3 3)
0.00d+000 1.00d+000 2.00d+000
3.00d+000 4.00d+000 5.00d+000
6.00d+000 7.00d+000 8.00d+000
NIL

Code: Select all

(defparameter b #2a((3.3563d+50  6.56d+6      2.55460d-154)
                    (2.2542d+242 2.24542d-45  5.0d+7)
                    (6.34956d-3  7.43859d+245 8.3487d-38)))

CL-USER> (print-matrix b 3 3)
3.36d+050 6.56d+006 2.55d-154
2.25d+242 2.25d-045 5.00d+007
6.35d-003 7.44d+245 8.35d-038
NIL
- edgar

Goheeca
Posts: 271
Joined: Thu May 10, 2012 12:54 pm
Contact:

Re: need help printing matrix in lisp - rehash

Post by Goheeca » Sun Sep 22, 2013 11:47 pm

It can be improved not to generate a format string:

Code: Select all

(defun print-matrix (matrix rows columns &key (digits 2) (pad 1)
                     &aux (pad-string (make-string pad :initial-element #\Space)))
  "Print MATRIX with padded and aligned elements."
  (dotimes (i rows)
    (dotimes (j columns)
      (format t "~,v,3e" digits (get-real-2d matrix i j))
      (if (eql j (1- columns))
          (terpri)
          (princ pad-string)))))
cl-2dsyntax is my attempt to create a Python-like reader. My mirror of CLHS (and the dark themed version). Temporary mirrors of aferomentioned: CLHS and a dark version.

Post Reply