If you have a vector of length m and each vector element contains an
array of dimension '(n p), how would you form this into an array
of dimension '(m n p)
Here is some code to build a vector of length vecsize where each
vector contains an array of dimension '(2 4). The next step is to
write the array-join and I cant figure it out.
; Jørn Inge
; http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/d44a7c5c6b3276d8/b0a5f72e4a061991#b0a5f72e4a061991
(defun set-array! (a f)
(let ((result (make-array (array-total-size a) :displaced-to a)))
(map-into result f result)
a))
(defconstant vecsize 3)
(setf inners (loop for i from 0 below vecsize collect (make-array '(2
4))))
(loop for a in inners do (set-array! a (lambda (x) (random 50.0))))
(setf outer (make-array (list vecsize) :initial-contents inners))
redick.metaperl.com wrote:
> If you have a vector of length m and each vector element contains an
> array of dimension '(n p), how would you form this into an array
> of dimension '(m n p)
>
> Here is some code to build a vector of length vecsize where each
> vector contains an array of dimension '(2 4). The next step is to
> write the array-join and I cant figure it out.
Have to cons a new (m n p) array and copy elements of items into it
I fear. You *could* then just explicitly loop over indices and
repeatedly (setf (aref...) ...)... But far more fun to do it without
doing that though... ;-)
; (Note I assume first item in vector is representative below...)
; 1. Simple displacement, fill-pointer and vector-push
(defun merged-array-from-vec-of-arrays1 (vector)
(loop
with element-type = (array-element-type (aref vector 0))
with merged-array =
(make-array (cons (length vector)
(array-dimensions (aref vector 0)))
:element-type element-type)
with flattened-merged-array =
(make-array (array-total-size merged-array)
:displaced-to merged-array
:element-type element-type
:fill-pointer 0)
for item across vector
do (loop for element across
(make-array (array-total-size item)
:displaced-to item
:element-type element-type)
do (vector-push element flattened-merged-array))
finally (return merged-array)))
; 2. Offset displacement making a (1D) "stencil", map-into,
; otherwise similar to 1.
(defun merged-array-from-vec-of-arrays (vector)
(loop
with element-type = (array-element-type (aref vector 0))
with merged-array =
(make-array (cons (length vector)
(array-dimensions (aref vector 0)))
:element-type element-type)
with item-size = (array-total-size (aref vector 0))
with rmidx = 0
for item across vector
do (let ((stencil (make-array item-size
:displaced-to merged-array
:displaced-index-offset rmidx
:element-type element-type)))
(map-into stencil #'identity
(make-array item-size
:displaced-to item
:element-type element-type))
(incf rmidx item-size))
finally (return merged-array)))
On Dec 17, 2:59 pm, David Golden <············@oceanfree.net> wrote:
> redick.metaperl.com wrote:
> > If you have a vector of length m and each vector element contains an
> > array of dimension '(n p), how would you form this into an array
> > of dimension '(m n p)
>
> > Here is some code to build a vector of length vecsize where each
> > vector contains an array of dimension '(2 4). The next step is to
> > write the array-join and I cant figure it out.
>
> Have to cons a new (m n p) array and copy elements of items into it
> I fear. You *could* then just explicitly loop over indices and
> repeatedly (setf (aref...) ...)... But far more fun to do it without
> doing that though... ;-)
Here is the implementation of that approach. It depends on a few
functions in the redick distro - http://hg.metaperl.com/redick?cmd=summary;style=gitweb
(defun array-join (a)
"Input: ARRAY a - an array whose innermost dimension contains
arrays
(instead of the usual case of containing elements)
Output: ARRAY target-array with that innermost dimension spread out
over
more dimesions so that the innermost dimension now only has atoms."
(let* ((current-dimensions (array-dimensions a))
(inner-dimensions (array-dimensions (aref a 0)))
(target-dimensions (append current-dimensions inner-dimensions))
(target-array (make-array target-dimensions))
(target-array-indices (x-prod (mapcar #'iota target-dimensions)))
(split-point (length current-dimensions))
)
(progn
(loop for tai in target-array-indices
for (outer-i inner-i) =
(multiple-value-list (sequence-partition tai split-point))
do (let* ((outer-val (aref a (car outer-i))) ;;; HACKISH
(inner-val (apply #'aref outer-val inner-i)))
(setf (apply #'aref target-array tai) inner-val)
))
target-array))
)