All,

1.  I frequently have a need to extract a SUB-ARRAY from an ARRAY.
    In Matlab parlance I would have written something like 
    A(:,1:4:30,:) for a RANK 3 array.

2.  The code, SUB-ARRAY, works but is woefully slow.  

    a.  My attempts at various DECLARE options resulted in no change.
    b.  My attempts at re-writting the SUB-ARRAY selection code only
        make things worse by a factor of 5 or more.

3.  If anyone has some pointers as to what I might try, I'd sure appreciate
    it.  The details are below.

tnx in advance

mike

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; The basic function is below.  My test case is an 
;; (ARRAY (COMPLEX SINGLE-FLOAT) (201 360 18))
;; (SUB-ARRAY ARRAY :ALL (ISEQ 0 10 359) :ALL) results in
;; 
;;      Consed    |   Calls   |    Secs   | Sec/Call  | Bytes/C.  | Name:
;;    -----------------------------------------------------------------------
;;      1,042,152 |         1 |    50.650 |  50.65000 | 1,042,152 | SUB-ARRAY
;;      5,209,984 |   130,248 |     0.810 |   0.00001 |        40 | AREF
;;      5,338,584 |         1 |     0.040 |   0.04000 | 5,338,584 | CARTESIAN-PRODUCT
;;             80 |         1 |     0.000 |   0.00000 |        80 | 
TRANSLATE-INDEX-SPECS
;;          1,752 |         2 |     0.000 |   0.00000 |       876 | ISEQ
;;    -------------------------------------------------------------------
;;     11,592,552 |   130,253 |    51.500 |           |           | Total

   
(defun sub-array (array &rest index-specs)
  "
  SYNTAX
  ======
  (SUB-ARRAY ARRAY INDEX0-SPEC INDEX1-SPEC ... )

  INPUT
  -----
  ARRAY      An ARRAY of rank N
  INDEX-SPEC There must be one INDEX-SPEC for each dimension of ARRAY
             One of the following:
             (ISEQ START STEP STOP)
             :ALL    Expands to (ISEQ 0 1 (ARRAY-DIMENSION ARRAY I))
             :EVEN   Expands to (ISEQ 0 2 (ARRAY-DIMENSION ARRAY I))
             :ODD    Expands to (ISEQ 1 2 (ARRAY-DIMENSION ARRAY I))

  OUTPUT
  ------
  ARRY    A new array made up of the specified entries of ARRAY."

  ;; Idiot check
  (unless (= (array-rank array) (length index-specs))
    (error "Insufficient INDEX-SPECIFICATION for given ARRAY."))

  (multiple-value-bind (array-indexes array-dims)
      (apply #'translate-index-specs array index-specs)

    (let* (
         (new-array (make-array array-dims
                                :element-type (array-element-type array)))
         ;; and create a displaced array
         (new-array-displaced (make-array (array-total-size new-array)
                                          :element-type (array-element-type array)
                                          :displaced-to new-array)))

      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                               
   
      ;; now populate and return the new-array
      ;; I FEEL THAT THE PROBLEM HAS TO BE RIGHT HERE
      ;; I've tried eliminating the APPLY and using
      ;; ROW-MAJOR-AREF on an array displaced to ARRAY...but no help
      (dotimes (n (array-total-size new-array) new-array)
        (setf (aref new-array-displaced n)
              (apply #'aref array (nth n array-indexes)))))))


Reply via email to