From: Akshay S. <ak...@us...> - 2012-12-25 20:48:00
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "matlisp". The branch, extensible has been created at 376399e23fbbb868c8eb3ef80ee8bc9c65c5d98e (commit) - Log ----------------------------------------------------------------- commit 376399e23fbbb868c8eb3ef80ee8bc9c65c5d98e Author: Akshay Srinivasan <aks...@gm...> Date: Tue Dec 25 14:39:13 2012 -0600 o Got rid of the "counterclass" hashtable. Everything now resides in *tensor-class-optimization*, and in the symbol-plist associated with tensor class name. o Ported some L-1 routines to the new architecture. diff --git a/matlisp.asd b/matlisp.asd index 61cf5b1..d573c09 100644 --- a/matlisp.asd +++ b/matlisp.asd @@ -133,20 +133,22 @@ (:file "swap") (:file "copy" :depends-on ("tensor-maker")) - (:file "scal" + #+nil(:file "scal" :depends-on ("copy" "tensor-maker")) - (:file "realimag" + #+nil(:file "realimag" :depends-on ("copy")) - (:file "dot" + #+nil(:file "dot" :depends-on ("realimag")) - (:file "axpy" + #+nil(:file "axpy" :depends-on ("copy" "scal")) - (:file "trans" + #+nil(:file "trans" :depends-on ("scal" "copy")))) + #+nil (:module "matlisp-level-2" :pathname "level-2" :depends-on ("matlisp-base" "matlisp-classes" "foreign-core" "matlisp-level-1") :components ((:file "gemv"))) + #+nil (:module "matlisp-level-3" :pathname "level-3" :depends-on ("matlisp-base" "matlisp-classes" "foreign-core" "matlisp-level-1") @@ -155,11 +157,13 @@ :pathname "lapack" :depends-on ("matlisp-base" "matlisp-classes" "matlisp-level-1" "matlisp-level-2" "matlisp-level-3") :components ((:file "gesv"))) + #+nil (:module "matlisp-sugar" :pathname "sugar" :depends-on ("matlisp-base" "matlisp-classes" "matlisp-level-1" "matlisp-level-2" "matlisp-level-3") :components ((:file "mplusminus") (:file "mtimesdivide"))) + #+nil (:module "matlisp-reader" :pathname "reader" :components ((:file "infix"))))) diff --git a/src/base/blas-helpers.lisp b/src/base/blas-helpers.lisp index 86391ca..0092bf9 100644 --- a/src/base/blas-helpers.lisp +++ b/src/base/blas-helpers.lisp @@ -28,8 +28,7 @@ (defun consecutive-store-p (tensor) (declare (type standard-tensor tensor)) - (mlet* (((sort-std std-perm) (let-typed ((strd (strides tensor) :type index-store-vector)) - (very-quickly (sort-permute (copy-seq (strides tensor)) #'<))) + (mlet* (((sort-std std-perm) (very-quickly (sort-permute (copy-seq (strides tensor)) #'<)) :type (index-store-vector permutation)) (perm-dims (permute (dimensions tensor) std-perm) :type index-store-vector)) (very-quickly diff --git a/src/base/standard-tensor.lisp b/src/base/standard-tensor.lisp index 0691120..e27d9d8 100644 --- a/src/base/standard-tensor.lisp +++ b/src/base/standard-tensor.lisp @@ -121,29 +121,6 @@ (error 'tensor-not-vector :rank (rank old)))) ;; -(defvar *tensor-counterclass* (make-hash-table) - " - Contains the CLOS counterpart classes of every tensor class. - This is used to change the tensor class automatically to a matrix - and vector") - -(defun get-tensor-counterclass (clname) - (declare (type symbol clname)) - (let ((opt (gethash clname *tensor-counterclass*))) - (cond - ((null opt) nil) - ((symbolp opt) - (get-tensor-counterclass opt)) - (t (values opt clname))))) - -(defun (setf get-tensor-counterclass) (value clname) - (setf (gethash clname *tensor-counterclass*) value)) - -(setf (get-tensor-counterclass 'standard-tensor) - '(:matrix standard-matrix - :vector standard-vector)) - -;; (defvar *tensor-class-optimizations* (make-hash-table) " Contains a either: @@ -170,8 +147,14 @@ o class-name (symbol) of the superclass whose optimizations are to be made use of.") -(defun get-tensor-class-optimization (clname) +(definline get-tensor-class-optimization (clname) (declare (type symbol clname)) + (symbol-plist clname)) + +(definline get-tensor-object-optimization (obj) + (symbol-plist (class-name (class-of obj)))) + +(defun get-tensor-class-optimization-hashtable (clname) (let ((opt (gethash clname *tensor-class-optimizations*))) (cond ((null opt) nil) @@ -180,7 +163,10 @@ (t (values opt clname))))) (defun (setf get-tensor-class-optimization) (value clname) - (setf (gethash clname *tensor-class-optimizations*) value)) + (setf (gethash clname *tensor-class-optimizations*) value + (symbol-plist clname) (if (symbolp value) + (get-tensor-class-optimization-hashtable clname) + value))) ;; Akshay: I have no idea what this does, or why we want it ;; (inherited from standard-matrix.lisp @@ -366,9 +352,6 @@ ()) (defclass ,vector (standard-vector ,tensor-class) ()) - (setf (get-tensor-counterclass ',tensor-class) (list :matrix ',matrix :vector ',vector) - (get-tensor-counterclass ',matrix) ',tensor-class - (get-tensor-counterclass ',vector) ',tensor-class) ;;Store refs (defmethod tensor-store-ref ((tensor ,tensor-class) idx) (declare (type index-type idx)) @@ -381,7 +364,10 @@ (,value-writer value store idx))) ;; (let ((hst (list - :field-type ',element-type + :tensor ',tensor-class + :matrix ',matrix + :vector ',vector + :element-type ',element-type :f+ ',f+ :f- ',f- :finv+ ',finv+ @@ -397,9 +383,11 @@ :store-allocator ',store-allocator :coercer ',coercer :coercer-unforgiving ',coercer-unforgiving - :element-type ',element-type :store-type ',store-element-type))) - (setf (get-tensor-class-optimization ',tensor-class) hst)))) + (setf (get-tensor-class-optimization ',tensor-class) hst + (get-tensor-class-optimization ',matrix) ',tensor-class + (get-tensor-class-optimization ',vector) ',tensor-class) + (setf (symbol-plist ',tensor-class) hst)))) ;; (defgeneric tensor-ref (tensor subscripts) @@ -499,11 +487,9 @@ (declare (type standard-tensor ten)) (= (slot-value ten 'rank) 1)) -(defun square-p (tensor) - (let* ((rank (rank tensor)) - (sym (gensym)) - (lst (make-list rank :initial-element sym))) - (apply #'tensor-type-p (list tensor lst)))) +(definline square-p (tensor) + (let-typed ((dims (dimensions tensor) :type index-store-vector)) + (lvec-foldr #'(lambda (a b) (if (eq a b) a nil)) dims))) ;;---------------------------------------------------------------;; @@ -585,8 +571,9 @@ (make-instance (let ((nrnk (length ndim))) (if (> nrnk 2) (class-name (class-of tensor)) - (let ((cocl (get-tensor-counterclass (class-name (class-of tensor))))) - (assert cocl nil 'tensor-cannot-find-counter-class :tensor-class (class-name (class-of tensor))) - (ecase nrnk (2 (getf cocl :matrix)) (1 (getf cocl :vector)))))) + (let ((cocl (getf (symbol-plist (class-name (class-of tensor))) (ecase nrnk (2 :matrix) (1 :vector))))) + (assert cocl nil 'tensor-cannot-find-optimization :tensor-class (class-name (class-of tensor))) + cocl))) :parent-tensor tensor :store (store tensor) :head nhd :dimensions (make-index-store ndim) :strides (make-index-store nstd))))))) + diff --git a/src/classes/complex-tensor.lisp b/src/classes/complex-tensor.lisp index 3bb2f58..97e6656 100644 --- a/src/classes/complex-tensor.lisp +++ b/src/classes/complex-tensor.lisp @@ -12,8 +12,39 @@ (deftype complex-type () "Complex number with Re, Im parts in complex-base-type." '(cl:complex complex-base-type)) -;; +;;Field operations +(definline complex-type.f+ (a b) + (declare (type complex-type a b)) + (+ a b)) + +(definline complex-type.f- (a b) + (declare (type complex-type a b)) + (- a b)) + +(definline complex-type.finv+ (a) + (declare (type complex-type a)) + (- a)) + +(definline complex-type.fid+ () + #c(0.0d0 0.0d0)) + +(definline complex-type.f* (a b) + (declare (type complex-type a b)) + (* a b)) + +(definline complex-type.f/ (a b) + (declare (type complex-type a b)) + (/ a b)) + +(definline complex-type.finv* (a) + (declare (type complex-type a)) + (/ a)) + +(definline complex-type.fid* () + #c(1.0d0 0.0d0)) + +;;Store operations (definline allocate-complex-store (size) " (allocate-complex-store size) @@ -36,24 +67,56 @@ (defun coerce-complex-base (x) (restart-case (coerce-complex-base-unforgiving x) (use-value (value) (coerce-complex-base value)))) - ;; -(defclass complex-tensor (standard-tensor) - ((store :type complex-store-vector) - (element-type :initform 'complex-type)) - (:documentation "Tensor class with complex elements.")) - -(defclass complex-matrix (standard-matrix complex-tensor) - () - (:documentation "Matrix class with complex elements.")) - -(defclass complex-vector (standard-vector complex-tensor) - () - (:documentation "Vector class with complex elements.")) +(definline complex-type.reader (tstore idx) + (declare (type complex-store-vector tstore) + (type index-type idx)) + (complex (aref tstore (* 2 idx)) + (aref tstore (1+ (* 2 idx))))) + +(definline complex-type.value-writer (value store idx) + (declare (type complex-store-vector store) + (type index-type idx) + (type complex-type value)) + (setf (aref store (* 2 idx)) (realpart value) + (aref store (1+ (* 2 idx))) (imagpart value))) + +(definline complex-type.reader-writer (fstore fidx tstore tidx) + (declare (type complex-store-vector fstore tstore) + (type index-type fidx tidx)) + (setf (aref tstore (* 2 tidx)) (aref fstore (* 2 fidx)) + (aref tstore (1+ (* 2 tidx))) (aref fstore (1+ (* 2 fidx))))) + +(definline complex-type.swapper (fstore fidx tstore tidx) + (declare (type complex-store-vector fstore tstore) + (type index-type fidx tidx)) + (rotatef (aref tstore (* 2 tidx)) (aref fstore (* 2 fidx))) + (rotatef (aref tstore (1+ (* 2 tidx))) (aref fstore (1+ (* 2 fidx))))) +;; -(setf (get-tensor-counterclass 'complex-tensor) '(:matrix complex-matrix :vector complex-vector) - (get-tensor-counterclass 'complex-matrix) 'complex-tensor - (get-tensor-counterclass 'complex-vector) 'complex-tensor) +(define-tensor (complex-tensor complex-type complex-base-type complex-store-vector + (:documentation "Tensor class with complex elements.")) + :matrix complex-matrix :vector complex-vector + ;; + :f+ complex-type.f+ + :f- complex-type.f- + :finv+ complex-type.finv+ + :fid+ complex-type.fid+ + :f* complex-type.f* + :f/ complex-type.f/ + :finv* complex-type.finv* + :fid* complex-type.fid* + ;; + :store-allocator allocate-complex-store + :coercer coerce-complex + :coercer-unforgiving coerce-complex-unforgiving + ;; + :matrix complex-matrix :vector complex-vector + ;; + :reader complex-type.reader + :value-writer complex-type.value-writer + :reader-writer complex-type.reader-writer + :swapper complex-type.swapper) ;; (defmethod initialize-instance ((tensor complex-tensor) &rest initargs) @@ -64,31 +127,7 @@ (setf (store tensor) (allocate-complex-store size) (store-size tensor) size))) (call-next-method)) -;; -(tensor-store-defs (complex-tensor complex-type complex-base-type) - :store-allocator allocate-complex-store - :coercer coerce-complex-unforgiving - :reader - (lambda (tstore idx) - (complex (aref tstore (* 2 idx)) - (aref tstore (1+ (* 2 idx))))) - :value-writer - (lambda (value store idx) - (setf (aref store (* 2 idx)) (realpart value) - (aref store (1+ (* 2 idx))) (imagpart value))) - :reader-writer - (lambda (fstore fidx tstore tidx) - (setf (aref tstore (* 2 tidx)) (aref fstore (* 2 fidx)) - (aref tstore (1+ (* 2 tidx))) (aref fstore (1+ (* 2 fidx))))) - :swapper - (lambda (fstore fidx tstore tidx) - (progn - (rotatef (aref tstore (* 2 tidx)) (aref fstore (* 2 fidx))) - (rotatef (aref tstore (1+ (* 2 tidx))) (aref fstore (1+ (* 2 fidx))))))) - -(setf (get-tensor-class-optimization 'complex-matrix) 'complex-tensor - (get-tensor-class-optimization 'complex-vector) 'complex-tensor) ;; (defmethod print-element ((tensor complex-tensor) element stream) diff --git a/src/classes/matrix.lisp b/src/classes/matrix.lisp index dc7999c..78ea722 100644 --- a/src/classes/matrix.lisp +++ b/src/classes/matrix.lisp @@ -32,7 +32,7 @@ Purpose ======= Return T if X is a row matrix (number of columns is 1)" - (tensor-type-p matrix '(1 *))) + (tensor-typep matrix '(1 *))) (definline col-matrix-p (matrix) " @@ -43,7 +43,7 @@ Purpose ======= Return T if X is a column matrix (number of rows is 1)" - (tensor-type-p matrix '(* 1))) + (tensor-typep matrix '(* 1))) (definline row-or-col-matrix-p (matrix) " diff --git a/src/classes/real-tensor.lisp b/src/classes/real-tensor.lisp index 7e22544..8b0a9ec 100644 --- a/src/classes/real-tensor.lisp +++ b/src/classes/real-tensor.lisp @@ -74,7 +74,8 @@ Allocates real storage. Default initial-element = 0d0.") (use-value (value) (coerce-real value)))) ;; -(define-tensor (real-tensor real-type real-type real-store-vector) +(define-tensor (real-tensor real-type real-type real-store-vector + (:documentation "Tensor class with real double elements.")) :matrix real-matrix :vector real-vector ;; :f+ real-type.f+ @@ -106,9 +107,6 @@ Allocates real storage. Default initial-element = 0d0.") (slot-value tensor 'store-size) size))) (call-next-method)) -(setf (get-tensor-class-optimization 'real-matrix) 'real-tensor - (get-tensor-class-optimization 'real-vector) 'real-tensor) - ;; (defmethod (setf tensor-ref) ((value number) (tensor real-tensor) subscripts) (let ((sto-idx (store-indexing subscripts tensor))) diff --git a/src/conditions.lisp b/src/conditions.lisp index 5fdbfed..87a526a 100644 --- a/src/conditions.lisp +++ b/src/conditions.lisp @@ -204,13 +204,6 @@ (when (slots-boundp c 'argument 'argument-stride) (format stream "Stride of argument ~A must be >= 0, initialized with ~A." (argument c) (stride c)))))) -(define-condition tensor-cannot-find-counter-class (tensor-error) - ((tensor-class :reader tensor-class :initarg :tensor-class)) - (:documentation "Cannot find the counter-class list of the given tensor class") - (:report (lambda (c stream) - (when (slots-boundp c 'tensor-class) - (format stream "Cannot find the counter-class list of the given tensor class: ~a." (tensor-class c)))))) - (define-condition tensor-cannot-find-optimization (tensor-error) ((tensor-class :reader tensor-class :initarg :tensor-class)) (:documentation "Cannot find optimization information for the given tensor class") diff --git a/src/level-1/copy.lisp b/src/level-1/copy.lisp index 96f2786..4e5b665 100644 --- a/src/level-1/copy.lisp +++ b/src/level-1/copy.lisp @@ -32,20 +32,13 @@ ;;Be very careful when using functions generated by this macro. ;;Indexes can be tricky and this has no safety net ;;Use only after checking the arguments for compatibility. - (let* ((opt (get-tensor-class-optimization tensor-class))) + (let* ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (from to) (declare (type ,tensor-class from to)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (strd-p (when call-fortran? (blas-copyable-p from to)))) - (cond - ((and strd-p call-fortran?) - (,blas-func (number-of-elements from) - (store from) (first strd-p) - (store to) (second strd-p) - (head from) (head to))) - (t - (let ((f-sto (store from)) + ,(let + ((lisp-routine + `(let ((f-sto (store from)) (t-sto (store to))) (declare (type ,(linear-array-type (getf opt :store-type)) f-sto t-sto)) (very-quickly @@ -56,7 +49,19 @@ with (linear-sums (f-of (strides from) (head from)) (t-of (strides to) (head to))) - do ,(funcall (getf opt :reader-writer) 'f-sto 'f-of 't-sto 't-of))))))) + do (,(getf opt :reader-writer) f-sto f-of t-sto t-of)))))) + (if blas-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (strd-p (when call-fortran? (blas-copyable-p from to)))) + (cond + ((and strd-p call-fortran?) + (,blas-func (number-of-elements from) + (store from) (first strd-p) + (store to) (second strd-p) + (head from) (head to))) + (t + ,lisp-routine))) + lisp-routine)) to))) (defmacro generate-typed-num-copy! (func (tensor-class blas-func fortran-lb)) @@ -64,32 +69,36 @@ ;;Indexes can be tricky and this has no safety net ;;(you don't see a matrix-ref do you ?) ;;Use only after checking the arguments for compatibility. - (let* ((opt (get-tensor-class-optimization tensor-class))) + (let* ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (num-from to) (declare (type ,tensor-class to) (type ,(getf opt :element-type) num-from)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (min-stride (when call-fortran? (consecutive-store-p to)))) - (cond - ((and call-fortran? min-stride) - (let ((num-array (,(getf opt :store-allocator) 1))) - (declare (type ,(linear-array-type (getf opt :store-type)) num-array)) - ,(funcall (getf opt :value-writer) 'num-from 'num-array 0) - (,blas-func (number-of-elements to) - num-array 0 - (store to) min-stride - 0 (head to)))) - (t - (let-typed + ,(let + ((lisp-routine + `(let-typed ((t-sto (store to) :type ,(linear-array-type (getf opt :store-type)))) (very-quickly (mod-dotimes (idx (dimensions to)) with (linear-sums (t-of (strides to) (head to))) - do ,(funcall (getf opt :value-writer) 'num-from 't-sto 't-of))))))) - to))) - + do (,(getf opt :value-writer) num-from t-sto t-of)))))) + (if blas-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (min-stride (when call-fortran? (consecutive-store-p to)))) + (cond + ((and call-fortran? min-stride) + (let ((num-array (,(getf opt :store-allocator) 1))) + (declare (type ,(linear-array-type (getf opt :store-type)) num-array)) + (,(getf opt :value-writer) num-from num-array 0) + (,blas-func (number-of-elements to) + num-array 0 + (store to) min-stride + 0 (head to)))) + (t + ,lisp-routine))) + lisp-routine)) + to))) ;;Real (generate-typed-copy! real-typed-copy! @@ -163,11 +172,10 @@ with the same elements. This is a copy of the tensor. " (declare (type standard-tensor tensor)) - (let* ((dims (dimensions tensor)) - (ret (make-array (lvec->list dims) - :element-type (if-ret (getf (get-tensor-class-optimization (class-name (class-of tensor))) :element-type) - (error 'tensor-cannot-find-optimization :tensor-class (class-name (class-of tensor))))))) - (declare (type index-store-vector dims)) + (let*-typed ((dims (dimensions tensor) :type index-store-vector) + (ret (make-array (lvec->list dims) + :element-type (or (getf (get-tensor-object-optimization tensor) :element-type) + (error 'tensor-cannot-find-optimization :tensor-class (class-name (class-of tensor))))))) (let ((lst (make-list (rank tensor)))) (very-quickly (mod-dotimes (idx dims) @@ -175,10 +183,10 @@ ret))) (defmethod copy! :before ((x standard-tensor) (y array)) - (assert (subtypep (element-type x) + (assert (subtypep (getf (get-tensor-object-optimization x) :element-type) (array-element-type y)) nil 'invalid-type - :given (element-type x) + :given (getf (get-tensor-object-optimization x) :element-type) :expected (array-element-type y)) (assert (and (= (rank x) (array-rank y)) @@ -211,9 +219,9 @@ ;; (defmethod copy! :before ((x array) (y standard-tensor)) (assert (subtypep (array-element-type x) - (element-type y)) + (getf (get-tensor-object-optimization y) :element-type)) nil 'invalid-type - :given (array-element-type x) :expected (element-type y)) + :given (array-element-type x) :expected (getf (get-tensor-object-optimization y) :element-type)) (assert (and (= (array-rank x) (rank y)) (dolist (ele (mapcar #'= (array-dimensions x) (lvec->list (dimensions y))) t) diff --git a/src/level-1/scal.lisp b/src/level-1/scal.lisp index 0aea8b7..223f78a 100644 --- a/src/level-1/scal.lisp +++ b/src/level-1/scal.lisp @@ -29,20 +29,13 @@ (in-package #:matlisp) (defmacro generate-typed-scal! (func (tensor-class fortran-func fortran-lb)) - (let* ((opt (get-tensor-class-optimization tensor-class))) + (let* ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (from to) (declare (type ,tensor-class from to)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (strd-p (when call-fortran? (blas-copyable-p from to)))) - (cond - ((and strd-p call-fortran?) - (,fortran-func (number-of-elements from) - (store from) (first strd-p) - (store to) (second strd-p) - (head from) (head to))) - (t - (let ((f-sto (store from)) + ,(let + ((lisp-routine + `(let ((f-sto (store from)) (t-sto (store to))) (declare (type ,(linear-array-type (getf opt :store-type)) f-sto t-sto)) (very-quickly @@ -50,49 +43,59 @@ with (linear-sums (f-of (strides from) (head from)) (t-of (strides to) (head to))) - do (let*-typed ((val-f ,(funcall (getf opt :reader) 'f-sto 'f-of) :type ,(getf opt :element-type)) - (val-t ,(funcall (getf opt :reader) 't-sto 't-of) :type ,(getf opt :element-type)) + do (let*-typed ((val-f (,(getf opt :reader) f-sto f-of) :type ,(getf opt :element-type)) + (val-t (,(getf opt :reader) t-sto t-of) :type ,(getf opt :element-type)) (mul (* val-f val-t) :type ,(getf opt :element-type))) - ,(funcall (getf opt :value-writer) 'mul 't-sto 't-of)))))))) + (,(getf opt :value-writer) mul t-sto t-of))))))) + (if fortran-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (strd-p (when call-fortran? (blas-copyable-p from to)))) + (cond + ((and strd-p call-fortran?) + (,fortran-func (number-of-elements from) + (store from) (first strd-p) + (store to) (second strd-p) + (head from) (head to))) + (t + ,lisp-routine))) + lisp-routine)) to))) (defmacro generate-typed-num-scal! (func (tensor-class blas-func fortran-lb)) - (let ((opt (get-tensor-class-optimization tensor-class))) + (let ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (alpha to) (declare (type ,tensor-class to) (type ,(getf opt :element-type) alpha)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (min-stride (when call-fortran? (consecutive-store-p to)))) - (cond - ((and call-fortran? min-stride) - (,blas-func (number-of-elements to) alpha (store to) min-stride (head to))) - (t - (let ((t-sto (store to))) + ,(let + ((lisp-routine + `(let ((t-sto (store to))) (declare (type ,(linear-array-type (getf opt :store-type)) t-sto)) (very-quickly (mod-dotimes (idx (dimensions to)) with (linear-sums (t-of (strides to) (head to))) - do (let ((scal-val (* ,(funcall (getf opt :reader) 't-sto 't-of) alpha))) - ,(funcall (getf opt :value-writer) 'scal-val 't-sto 't-of)))))))) + do (let ((scal-val (* (,(getf opt :reader) t-sto t-of) alpha))) + (,(getf opt :value-writer) scal-val t-sto t-of))))))) + (if blas-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (min-stride (when call-fortran? (consecutive-store-p to)))) + (cond + ((and call-fortran? min-stride) + (,blas-func (number-of-elements to) alpha (store to) min-stride (head to))) + (t + ,lisp-routine))) + lisp-routine)) to))) (defmacro generate-typed-div! (func (tensor-class fortran-func fortran-lb)) - (let* ((opt (get-tensor-class-optimization tensor-class))) + (let* ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (from to) (declare (type ,tensor-class from to)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (strd-p (when call-fortran? (blas-copyable-p from to)))) - (cond - ((and strd-p call-fortran?) - (,fortran-func (number-of-elements from) - (store from) (first strd-p) - (store to) (second strd-p) - (head from) (head to))) - (t - (let ((f-sto (store from)) + ,(let + ((lisp-routine + `(let ((f-sto (store from)) (t-sto (store to))) (declare (type ,(linear-array-type (getf opt :store-type)) f-sto t-sto)) (very-quickly @@ -100,10 +103,22 @@ with (linear-sums (f-of (strides from) (head from)) (t-of (strides to) (head to))) - do (let*-typed ((val-f ,(funcall (getf opt :reader) 'f-sto 'f-of) :type ,(getf opt :element-type)) - (val-t ,(funcall (getf opt :reader) 't-sto 't-of) :type ,(getf opt :element-type)) + do (let*-typed ((val-f (,(getf opt :reader) f-sto f-of) :type ,(getf opt :element-type)) + (val-t (,(getf opt :reader) t-sto t-of) :type ,(getf opt :element-type)) (mul (/ val-f val-t) :type ,(getf opt :element-type))) - ,(funcall (getf opt :value-writer) 'mul 't-sto 't-of)))))))) + (,(getf opt :value-writer) mul t-sto t-of))))))) + (if fortran-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (strd-p (when call-fortran? (blas-copyable-p from to)))) + (cond + ((and strd-p call-fortran?) + (,fortran-func (number-of-elements from) + (store from) (first strd-p) + (store to) (second strd-p) + (head from) (head to))) + (t + ,lisp-routine))) + lisp-routine)) to))) (defmacro generate-typed-num-div! (func (tensor-class fortran-func fortran-lb)) @@ -112,24 +127,29 @@ `(definline ,func (alpha to) (declare (type ,tensor-class to) (type ,(getf opt :element-type) alpha)) - (let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) - (min-stride (when call-fortran? (consecutive-store-p to)))) - (cond - ((and call-fortran? min-stride) - (let ((num-array (,(getf opt :store-allocator) 1))) - (declare (type ,(linear-array-type (getf opt :store-type)) num-array)) - (let-typed ((id (,(getf opt :coercer) 1) :type ,(getf opt :element-type))) - ,(funcall (getf opt :value-writer) `id 'num-array 0)) - (,fortran-func (number-of-elements to) num-array 0 (store to) min-stride (head to)))) - (t - (let ((t-sto (store to))) + ,(let + ((lisp-routine + `(let ((t-sto (store to))) (declare (type ,(linear-array-type (getf opt :store-type)) t-sto)) (very-quickly (mod-dotimes (idx (dimensions to)) with (linear-sums (t-of (strides to) (head to))) - do (let-typed ((scal-val (/ alpha ,(funcall (getf opt :reader) 't-sto 't-of)) :type ,(getf opt :element-type))) - ,(funcall (getf opt :value-writer) 'scal-val 't-sto 't-of)))))))) + do (let-typed ((scal-val (/ alpha (,(getf opt :reader) t-sto t-of)) :type ,(getf opt :element-type))) + (,(getf opt :value-writer) scal-val t-sto t-of))))))) + (if fortran-func + `(let* ((call-fortran? (> (number-of-elements to) ,fortran-lb)) + (min-stride (when call-fortran? (consecutive-store-p to)))) + (cond + ((and call-fortran? min-stride) + (let ((num-array (,(getf opt :store-allocator) 1))) + (declare (type ,(linear-array-type (getf opt :store-type)) num-array)) + (let-typed ((id (,(getf opt :coercer) 1) :type ,(getf opt :element-type))) + (,(getf opt :value-writer) id num-array 0)) + (,fortran-func (number-of-elements to) num-array 0 (store to) min-stride (head to)))) + (t + ,lisp-routine))) + lisp-routine)) to))) ;;Real diff --git a/src/level-1/swap.lisp b/src/level-1/swap.lisp index f2eb094..9de6966 100644 --- a/src/level-1/swap.lisp +++ b/src/level-1/swap.lisp @@ -32,25 +32,30 @@ ;;Be very careful when using functions generated by this macro. ;;Indexes can be tricky and this has no safety net ;;Use only after checking the arguments for compatibility. - (let* ((opt (get-tensor-class-optimization tensor-class))) + (let* ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) `(definline ,func (x y) (declare (type ,tensor-class x y)) - (let* ((call-fortran? (> (number-of-elements x) ,fortran-lb)) - (strd-p (when call-fortran? (blas-copyable-p x y)))) - (cond - ((and strd-p call-fortran?) - (,blas-func (number-of-elements x) (store x) (first strd-p) (store y) (second strd-p) (head x) (head y))) - (t - (let ((f-sto (store x)) + ,(let + ((lisp-routine + `(let ((f-sto (store x)) (t-sto (store y))) - (declare (type ,(linear-array-type (getf opt :store-type)) f-sto t-sto)) - (very-quickly - (mod-dotimes (idx (dimensions x)) - with (linear-sums - (f-of (strides x) (head x)) - (t-of (strides y) (head y))) - do ,(funcall (getf opt :swapper) 'f-sto 'f-of 't-sto 't-of))))))) + (declare (type ,(linear-array-type (getf opt :store-type)) f-sto t-sto)) + (very-quickly + (mod-dotimes (idx (dimensions x)) + with (linear-sums + (f-of (strides x) (head x)) + (t-of (strides y) (head y))) + do (,(getf opt :swapper) f-sto f-of t-sto t-of)))))) + (if blas-func + `(let* ((call-fortran? (> (number-of-elements x) ,fortran-lb)) + (strd-p (when call-fortran? (blas-copyable-p x y)))) + (cond + ((and strd-p call-fortran?) + (,blas-func (number-of-elements x) (store x) (first strd-p) (store y) (second strd-p) (head x) (head y))) + (t + ,lisp-routine))) + lisp-routine)) y))) (generate-typed-swap! real-typed-swap! diff --git a/src/level-1/tensor-maker.lisp b/src/level-1/tensor-maker.lisp index 6f7cb3b..4ce8f18 100644 --- a/src/level-1/tensor-maker.lisp +++ b/src/level-1/tensor-maker.lisp @@ -1,10 +1,8 @@ (in-package #:matlisp) (defmacro make-tensor-maker (func-name (tensor-class)) - (let ((opt (get-tensor-class-optimization tensor-class)) - (cocl (get-tensor-counterclass tensor-class))) + (let ((opt (get-tensor-class-optimization-hashtable tensor-class))) (assert opt nil 'tensor-cannot-find-optimization :tensor-class tensor-class) - (assert cocl nil 'tensor-cannot-find-counter-class :tensor-class tensor-class) `(progn (declaim (ftype (function (&rest t) ,tensor-class) ,func-name)) (defun ,func-name (&rest args) @@ -14,7 +12,7 @@ (ss (very-quickly (lvec-foldl #'(lambda (x y) (the index-type (* x y))) vdim))) (store (,(getf opt :store-allocator) ss)) (rnk (length vdim))) - (make-instance (case rnk (2 ',(getf cocl :matrix)) (1 ',(getf cocl :vector)) (t ',tensor-class)) + (make-instance (case rnk (2 ',(getf opt :matrix)) (1 ',(getf opt :vector)) (t ',tensor-class)) :store store :dimensions vdim))) (make-from-array (arr) (declare (type (array * *) arr)) @@ -26,7 +24,7 @@ (mod-dotimes (idx (dimensions ret)) with (linear-sums (of-r (strides ret) (head ret))) - do ,(funcall (getf opt :value-writer) `(,(getf opt :coercer) (apply #'aref arr (lvec->list! idx lst))) 'st-r 'of-r)) + do (,(getf opt :value-writer) (,(getf opt :coercer) (apply #'aref arr (lvec->list! idx lst))) st-r of-r)) ret)) (make-from-list (lst) (let* ((ret (make-dims (list-dimensions lst))) @@ -36,7 +34,7 @@ (list-loop (idx ele lst) with (linear-sums (of-r (strides ret) (head ret))) - do ,(funcall (getf opt :value-writer) `(,(getf opt :coercer) ele) 'st-r 'of-r)) + do (,(getf opt :value-writer) (,(getf opt :coercer) ele) st-r of-r)) ret))) (let ((largs (length args))) (if (= largs 1) commit ff3082257b6f984b30131dd170f011eacd78f7e6 Author: Akshay Srinivasan <aks...@gm...> Date: Sun Dec 23 17:16:26 2012 -0600 o Extended tensor-class-optimization with slots for underlying Field properties. o Moved lots of stuff to define-tensor macro diff --git a/src/base/standard-tensor.lisp b/src/base/standard-tensor.lisp index 9899186..0691120 100644 --- a/src/base/standard-tensor.lisp +++ b/src/base/standard-tensor.lisp @@ -48,10 +48,6 @@ :accessor number-of-elements :type index-type :documentation "Total number of elements in the tensor.") - (element-type - :accessor element-type - :type symbol - :documentation "Element type of the tensor") ;; (parent-tensor :accessor parent-tensor @@ -83,6 +79,7 @@ (defclass standard-matrix (standard-tensor) ((rank :accessor rank + :allocation :class :type index-type :initform 2 :documentation "For a matrix, rank = 2.")) @@ -91,7 +88,7 @@ ;; (defmethod initialize-instance :after ((matrix standard-matrix) &rest initargs) (declare (ignore initargs)) - (mlet* + (let-typed ((rank (rank matrix) :type index-type)) (unless (= rank 2) (error 'tensor-not-matrix :rank rank :tensor matrix)))) @@ -105,6 +102,7 @@ (defclass standard-vector (standard-tensor) ((rank :accessor rank + :allocation :class :type index-type :initform 1 :documentation "For a vector, rank = 1.")) @@ -149,10 +147,21 @@ (defvar *tensor-class-optimizations* (make-hash-table) " Contains a either: - o A property list containing: + o A property list containing: + :field-type -> Field type + :f+ (a b) -> a + b + :f- (a b) -> a + (- b) + :finv+ (a) -> -a + :fid+ () -> + identity + :f* (a b) -> a * b + :f/ (a b) -> a * b^{-1} + :finv* (a) -> 1/a + :fid* () -> * identity + + :coercer (ele) -> Coerced to store-type, with error checking + :coercer-unforgiving (ele) -> Coerced to store-type, no error checking + :store-allocator (n) -> Allocates a store of size n - :coercer (ele) -> Coerced to store-type - :element-type :store-type :reader (store idx) => result :value-writer (value store idx) => (store idx) <- value @@ -340,40 +349,57 @@ (unless (< -1 idx (store-size tensor)) (error 'tensor-store-index-out-of-bounds :index idx :store-size (store-size tensor) :tensor tensor)))) -(defmacro tensor-store-defs ((tensor-class element-type store-element-type) &key store-allocator coercer reader value-writer reader-writer swapper) - (let ((tensym (gensym "tensor"))) - (assert store-allocator) - (assert coercer) - (assert (eq (first reader-writer) 'lambda)) - (assert swapper) - `(progn - ,(destructuring-bind (lbd args &rest body) reader - (assert (eq lbd 'lambda)) - (destructuring-bind (tstore idx) args - `(defmethod tensor-store-ref ((,tensym ,tensor-class) ,idx) - (declare (type index-type ,idx)) - (let ((,tstore (store ,tensym))) - (declare (type ,(linear-array-type store-element-type) ,tstore)) - ,@body)))) - ,(destructuring-bind (lbd args &rest body) value-writer - (assert (eq lbd 'lambda)) - (destructuring-bind (value tstore tidx) args - `(defmethod (setf tensor-store-ref) (,value (,tensym ,tensor-class) ,tidx) - (declare (type index-type ,tidx) - (type ,element-type ,value)) - (let ((,tstore (store ,tensym))) - (declare (type ,(linear-array-type store-element-type) ,tstore)) - ,@body)))) - (let ((hst (list - :reader (macrofy ,reader) - :value-writer (macrofy ,value-writer) - :reader-writer (macrofy ,reader-writer) - :swapper (macrofy ,swapper) - :store-allocator ',store-allocator - :coercer ',coercer - :element-type ',element-type - :store-type ',store-element-type))) - (setf (get-tensor-class-optimization ',tensor-class) hst))))) +(defmacro define-tensor + ((tensor-class element-type store-element-type store-type &rest class-decls) &key + f+ f- finv+ fid+ f* f/ finv* fid* + matrix vector + store-allocator coercer coercer-unforgiving reader value-writer reader-writer swapper) + ;;Error checking + (assert (and f+ f- finv+ fid+ f* f/ finv* fid* store-allocator coercer coercer-unforgiving matrix vector reader value-writer reader-writer swapper)) + ;; + `(progn + ;;Class definitions + (defclass ,tensor-class (standard-tensor) + ((store :type ,store-type)) + ,@class-decls) + (defclass ,matrix (standard-matrix ,tensor-class) + ()) + (defclass ,vector (standard-vector ,tensor-class) + ()) + (setf (get-tensor-counterclass ',tensor-class) (list :matrix ',matrix :vector ',vector) + (get-tensor-counterclass ',matrix) ',tensor-class + (get-tensor-counterclass ',vector) ',tensor-class) + ;;Store refs + (defmethod tensor-store-ref ((tensor ,tensor-class) idx) + (declare (type index-type idx)) + (let-typed ((store (store tensor) :type ,store-type)) + (,reader store idx))) + (defmethod (setf tensor-store-ref) (value (tensor ,tensor-class) idx) + (declare (type index-type idx) + (type ,element-type value)) + (let-typed ((store (store tensor) :type ,store-type)) + (,value-writer value store idx))) + ;; + (let ((hst (list + :field-type ',element-type + :f+ ',f+ + :f- ',f- + :finv+ ',finv+ + :fid+ ',fid+ + :f* ',f* + :f/ ',f/ + :finv* ',finv* + :fid* ',fid* + :reader ',reader + :value-writer ',value-writer + :reader-writer ',reader-writer + :swapper ',swapper + :store-allocator ',store-allocator + :coercer ',coercer + :coercer-unforgiving ',coercer-unforgiving + :element-type ',element-type + :store-type ',store-element-type))) + (setf (get-tensor-class-optimization ',tensor-class) hst)))) ;; (defgeneric tensor-ref (tensor subscripts) @@ -420,11 +446,11 @@ ;; -(defun tensor-type-p (tensor subscripts) +(defun tensor-typep (tensor subscripts) " Syntax ====== - (tensor-type-p tensor subscripts) + (tensor-typep tensor subscripts) Purpose ======= @@ -434,14 +460,14 @@ Examples ======== Checking for a vector: - > (tensor-type-p ten '(*)) + > (tensor-typep ten '(*)) Checking for a matrix with 2 columns: - > (tensor-type-p ten '(* 2)) + > (tensor-typep ten '(* 2)) Also does symbolic association; checking for a square matrix: - > (tensor-type-p ten '(a a)) + > (tensor-typep ten '(a a)) " (declare (type standard-tensor tensor)) (mlet* (((rank dims) (slot-values tensor '(rank dimensions)) diff --git a/src/classes/real-tensor.lisp b/src/classes/real-tensor.lisp index e7b8602..7e22544 100644 --- a/src/classes/real-tensor.lisp +++ b/src/classes/real-tensor.lisp @@ -7,8 +7,61 @@ (deftype real-store-vector (&optional (size '*)) "The type of the storage structure for a REAL-MATRIX" `(simple-array real-type (,size))) -;; +;;Field definitions +(definline real-type.f+ (a b) + (declare (type real-type a b)) + (+ a b)) + +(definline real-type.f- (a b) + (declare (type real-type a b)) + (- a b)) + +(definline real-type.finv+ (a) + (declare (type real-type a)) + (- a)) + +(definline real-type.fid+ () + 0.0d0) + +(definline real-type.f* (a b) + (declare (type real-type a b)) + (* a b)) + +(definline real-type.f/ (a b) + (declare (type real-type a b)) + (/ a b)) + +(definline real-type.finv* (a) + (declare (type real-type a)) + (/ a)) + +(definline real-type.fid* () + 1.0d0) + +;;Store definitions +(definline real-type.reader (tstore idx) + (declare (type index-type idx) + (type real-store-vector tstore)) + (aref tstore idx)) + +(definline real-type.value-writer (value store idx) + (declare (type index-type idx) + (type real-store-vector store) + (type real-type value)) + (setf (aref store idx) value)) + +(definline real-type.reader-writer (fstore fidx tstore tidx) + (declare (type index-type fidx tidx) + (type real-store-vector fstore tstore)) + (setf (aref tstore tidx) (aref fstore fidx))) + +(definline real-type.swapper (fstore fidx tstore tidx) + (declare (type index-type fidx tidx) + (type real-store-vector fstore tstore)) + (rotatef (aref tstore tidx) (aref fstore fidx))) + +;; (make-array-allocator allocate-real-store 'real-type 0d0 "(allocate-real-store size [initial-element]) Allocates real storage. Default initial-element = 0d0.") @@ -21,22 +74,28 @@ Allocates real storage. Default initial-element = 0d0.") (use-value (value) (coerce-real value)))) ;; -(defclass real-tensor (standard-tensor) - ((store :type real-store-vector) - (element-type :initform 'real-type)) - (:documentation "Tensor class with real elements.")) - -(defclass real-matrix (standard-matrix real-tensor) - () - (:documentation "A class of matrices with real elements.")) - -(defclass real-vector (standard-vector real-tensor) - () - (:documentation "A class of vector with real elements.")) - -(setf (get-tensor-counterclass 'real-tensor) '(:matrix real-matrix :vector real-vector) - (get-tensor-counterclass 'real-matrix) 'real-tensor - (get-tensor-counterclass 'real-vector) 'real-tensor) +(define-tensor (real-tensor real-type real-type real-store-vector) + :matrix real-matrix :vector real-vector + ;; + :f+ real-type.f+ + :f- real-type.f- + :finv+ real-type.finv+ + :fid+ real-type.fid+ + :f* real-type.f* + :f/ real-type.f/ + :finv* real-type.finv* + :fid* real-type.fid* + ;; + :store-allocator allocate-real-store + :coercer coerce-real + :coercer-unforgiving coerce-real-unforgiving + ;; + :matrix real-matrix :vector real-vector + ;; + :reader real-type.reader + :value-writer real-type.value-writer + :reader-writer real-type.reader-writer + :swapper real-type.swapper) ;; (defmethod initialize-instance ((tensor real-tensor) &rest initargs) @@ -47,23 +106,6 @@ Allocates real storage. Default initial-element = 0d0.") (slot-value tensor 'store-size) size))) (call-next-method)) -;; -(tensor-store-defs (real-tensor real-type real-type) - :store-allocator allocate-real-store - :coercer coerce-real-unforgiving - :reader - (lambda (tstore idx) - (aref tstore idx)) - :value-writer - (lambda (value store idx) - (setf (aref store idx) value)) - :reader-writer - (lambda (fstore fidx tstore tidx) - (setf (aref tstore tidx) (aref fstore fidx))) - :swapper - (lambda (fstore fidx tstore tidx) - (rotatef (aref tstore tidx) (aref fstore fidx)))) - (setf (get-tensor-class-optimization 'real-matrix) 'real-tensor (get-tensor-class-optimization 'real-vector) 'real-tensor) ----------------------------------------------------------------------- hooks/post-receive -- matlisp |