2011-05-21 9 views

Respuesta

11

Utilice un sharpsign-punto para insertar la clase de objeto depende de la implementación en lectura-tiempo:

(defmethod foo ((v #.(class-of (make-array 0 :element-type '(unsigned-byte 8))))) 
    :unsigned-byte-8-array) 

El sharpsign-dot lector macro evalúa el formulario de lectura-tiempo, la determinación de la clase de la matriz. El método estará especializado en la clase que utiliza la implementación de Common Lisp para la matriz.

4

en cuenta que el argumento :ELEMENT-TYPE-MAKE-ARRAY hace algo especial y su comportamiento exacto puede ser un poco sorprendente.

Al usarlo, le está diciendo a Common Lisp que el ARRAY debería poder almacenar elementos de ese tipo de elemento o alguno de sus subtipos.

sistema Lisp The Common entonces devuelve un vector que puede almacenar estos elementos. Puede ser una matriz especializada o una matriz que también puede almacenar elementos más generales.

Aviso: no es una declaración de tipo y que no necesariamente se comprueba en tiempo de compilación o en tiempo de ejecución.

La función UPGRADED-ARRAY-ELEMENT-TYPE le dice a qué elemento se puede actualizar una matriz.

LispWorks 64 bits:

CL-USER 10 > (upgraded-array-element-type '(unsigned-byte 8)) 
(UNSIGNED-BYTE 8) 

CL-USER 11 > (upgraded-array-element-type '(unsigned-byte 4)) 
(UNSIGNED-BYTE 4) 

CL-USER 12 > (upgraded-array-element-type '(unsigned-byte 12)) 
(UNSIGNED-BYTE 16) 

Así, LispWorks de 64 bits tiene arreglos especiales para 4 y 8 elementos bits. Para elementos de 12 bits, asigna una matriz que puede almacenar elementos de hasta 16 bits.

Generamos una matriz que puede almacenar diez números de hasta 12 bits de:

CL-USER 13 > (make-array 10 
         :element-type '(unsigned-byte 12) 
         :initial-element 0) 
#(0 0 0 0 0 0 0 0 0 0) 

Vamos a comprobar su tipo:

CL-USER 14 > (type-of *) 
(SIMPLE-ARRAY (UNSIGNED-BYTE 16) (10)) 

Es una simple matriz (no ajustable, ningún puntero de relleno) Puede almacenar elementos del tipo (UNSIGNED-BYTE 16) y sus subtipos. Tiene una longitud de 10 y tiene una dimensión.

0

En una función normal se puede utilizar etypecase hacer el envío:

El siguiente código no es autónomo sino que debe dar una idea de cómo implementar una función que hace operaciones de punto-sabia aun cuando el para las matrices 3D:

(.* (make-array 3 :element-type 'single-float 
       :initial-contents '(1s0 2s0 3s0)) 
    (make-array 3 :element-type 'single-float 
       :initial-contents '(2s0 2s0 3s0))) 

Aquí está el código:

(def-generator (point-wise (op rank type) :override-name t) 
    (let ((name (format-symbol ".~a-~a-~a" op rank type))) 
    (store-new-function name) 
    `(defun ,name (a b &optional (b-start (make-vec-i))) 
     (declare ((simple-array ,long-type ,rank) a b) 
       (vec-i b-start) 
       (values (simple-array ,long-type ,rank) &optional)) 
     (let ((result (make-array (array-dimensions b) 
           :element-type ',long-type))) 
     ,(ecase rank 
      (1 `(destructuring-bind (x) 
        (array-dimensions b) 
       (let ((sx (vec-i-x b-start))) 
        (do-region ((i) (x)) 
        (setf (aref result i) 
          (,op (aref a (+ i sx)) 
           (aref b i))))))) 
      (2 `(destructuring-bind (y x) 
        (array-dimensions b) 
       (let ((sx (vec-i-x b-start)) 
         (sy (vec-i-y b-start))) 
        (do-region ((j i) (y x)) 
        (setf (aref result j i) 
          (,op (aref a (+ j sy) (+ i sx)) 
           (aref b j i))))))) 
      (3 `(destructuring-bind (z y x) 
        (array-dimensions b) 
       (let ((sx (vec-i-x b-start)) 
         (sy (vec-i-y b-start)) 
         (sz (vec-i-z b-start))) 
        (do-region ((k j i) (z y x)) 
        (setf (aref result k j i) 
         (,op (aref a (+ k sz) (+ j sy) (+ i sx)) 
          (aref b k j i)))))))) 
     result)))) 
#+nil 
(def-point-wise-op-rank-type * 1 sf) 

(defmacro def-point-wise-functions (ops ranks types) 
    (let ((specific-funcs nil) 
     (generic-funcs nil)) 
    (loop for rank in ranks do 
     (loop for type in types do 
       (loop for op in ops do 
        (push `(def-point-wise-op-rank-type ,op ,rank ,type) 
         specific-funcs)))) 
    (loop for op in ops do 
     (let ((cases nil)) 
      (loop for rank in ranks do 
       (loop for type in types do 
        (push `((simple-array ,(get-long-type type) ,rank) 
          (,(format-symbol ".~a-~a-~a" op rank type) 
           a b b-start)) 
          cases))) 
      (let ((name (format-symbol ".~a" op))) 
      (store-new-function name) 
      (push `(defun ,name (a b &optional (b-start (make-vec-i))) 
         (etypecase a 
         ,@cases 
         (t (error "The given type can't be handled with a generic 
       point-wise function.")))) 
        generic-funcs)))) 
    `(progn ,@specific-funcs 
      ,@generic-funcs))) 

(def-point-wise-functions (+ - * /) (1 2 3) (ub8 sf df csf cdf))