;; data matrix (define-record-type matrix (fields matrix-b type data-type rows columns elements data-size storage-size matrix-v)) ;; bytevector -> matrix (define decode-matrix (lambda (mtx) (if (not (matrix-b? mtx)) (error "decode-matrix" "illegal data" mtx) #f) (let* ((type (matrix-b-type mtx)) (data-type (matrix-b-data-type mtx)) (rows (matrix-b-rows mtx)) (columns (matrix-b-columns mtx)) (elements (matrix-b-elements mtx)) (data-size (matrix-b-data-size mtx)) (storage-size (matrix-b-storage-size mtx)) (matrix-v (matrix-b->matrix-v mtx))) (make-matrix mtx type data-type rows columns elements data-size storage-size matrix-v)))) ;; matrix -> bytevector (define encode-matrix (lambda (mtx) (if (not (matrix? mtx)) (error "encode-matrix" "illegal data" mtx) #f) (let ((type (string->utf8 (matrix-type mtx))) (data-type (encode-i32 (matrix-data-type mtx))) (data-type-size (data-type-size (matrix-data-type mtx))) (rows (encode-i32 (matrix-rows mtx))) (columns (encode-i32 (matrix-columns mtx))) (elements (matrix-elements mtx)) (data-size (matrix-data-size mtx)) (storage-size (matrix-storage-size mtx)) (matrix-b (make-bytevector (matrix-storage-size mtx) 0)) (matrix-v (matrix-matrix-v mtx)) (encoder (data-type-encoder (matrix-data-type mtx)))) (let loop ((i 0)) (if (< i elements) (let* ((v (encoder (vector-ref matrix-v i))) (k (bytevector-length v))) (bytevector-copy! v 0 matrix-b i k) (loop (+ i data-type-size))) #f)) (flatten-bytevectors (list type data-type rows columns matrix-b))))) ;; #[a] -> int -> int -> #[a] (define vector-copy (lambda (v i j) (let* ((n (- j i)) (r (make-vector n))) (let loop ((k 0)) (when (< k n) (vector-set! r k (vector-ref v (+ i k))) (loop (+ k 1)))) r))) ;; matrix -> #[datum] (define matrix-row (lambda (m n) (let* ((r (matrix-rows m)) (c (matrix-columns m)) (i (* n c))) (if (>= n r) (error "matrix-row" "domain error" n r) (vector-copy (matrix-matrix-v m) i (+ i c)))))) ;; matrix -> #[datum] (define matrix-column (lambda (m n) (let* ((nr (matrix-rows m)) (nc (matrix-columns m)) (v (matrix-matrix-v m)) (c (make-vector nr))) (letrec ((build (lambda (i) (if (= i nr) c (begin (vector-set! c i (vector-ref v (+ n (* i nc)))) (build (+ i 1))))))) (if (>= n nc) (error "matrix-column" "domain error" n nc) (build 0))))))