[lisplab-cvs] r171 - trunk/src/matrix
Jørn Inge Vestgården
jivestgarden at common-lisp.net
Thu May 20 19:47:07 UTC 2010
Author: jivestgarden
Date: Thu May 20 15:47:06 2010
New Revision: 171
Log:
optimized and fixed .expt
Modified:
trunk/src/matrix/level2-matrix-dge.lisp
trunk/src/matrix/store-operators.lisp
Modified: trunk/src/matrix/level2-matrix-dge.lisp
==============================================================================
--- trunk/src/matrix/level2-matrix-dge.lisp (original)
+++ trunk/src/matrix/level2-matrix-dge.lisp Thu May 20 15:47:06 2010
@@ -148,7 +148,7 @@
(.sub . -_dfa-df)
(.mul . *_dfa-df)
(.div . /_dfa-df)
- (.expt . ^_dfa-df)
+ ;; (.expt . ^_dfa-df)
(.max . max_dfa-df)
(.min . min_dfa-df)))
@@ -176,7 +176,7 @@
(.sub . -_df-dfa)
(.mul . *_df-dfa)
(.div . /_df-dfa)
- (.expt . ^_df-dfa)
+ ;; (.expt . ^_df-dfa)
(.max . max_df-dfa)
(.min . min_df-dfa)))
@@ -204,7 +204,7 @@
(.sub . -_dfa-dfa)
(.mul . *_dfa-dfa)
(.div . /_dfa-dfa)
- (.expt . ^_dfa-dfa)
+ ;; (.expt . ^_dfa-dfa)
(.max . max_dfa-dfa)
(.min . min_dfa-dfa)))
@@ -225,6 +225,85 @@
(expand-generic-function-dfa-dfa-map)
+;;; The expt is an exception, since negative input can give complex exponent
+;;; and since the general case is slow.
+
+(defun all-integer-elements-p (a)
+ "Helper function for .expt"
+ (declare (type-blas-store a))
+ (dotimes (i (length a))
+ (multiple-value-bind (div mod) (ftruncate (aref a i))
+ (declare (ignore div))
+ (unless (zerop mod)
+ (return-from all-integer-elements-p nil))))
+ t)
+
+(defmethod .expt ((a matrix-base-dge) (b matrix-base-dge))
+ (cond ((>= (mmin a) 0d0)
+ (let ((c (mcreate a)))
+ (^_dfa>=0-dfa (matrix-store a) (matrix-store b) (matrix-store c))
+ c))
+ ((all-integer-elements-p (matrix-store b))
+ (let ((c (mcreate a)))
+ (^_dfa-dfa (matrix-store a) (matrix-store b) (matrix-store c))
+ c))
+ (t (let ((c (mcreate* a :element-type :z))
+ (a2 (mcreate* a :element-type :z))
+ (b2 (mcreate* a :element-type :z)))
+ ;; There should be some better way to upgrade the element type of a matrix
+ ;; while keeping the contents.
+ (copy-contents a a2)
+ (copy-contents b b2)
+ ;; This could in theory be a litle more clever since if all exponents
+ ;; are even, the output is still real. However, recognizing even integers
+ ;; from float input is risky.
+ (^_cdfa-cdfa (matrix-store a2) (matrix-store b2) (matrix-store c))
+ c))))
+
+(defmethod .expt ((a matrix-base-dge) (b real))
+ "There is a lot of fuzz going on in here. The reason is because
+the important special cases of exponents -3,-2,-1,0,1,2,3 are a factor 10 faster
+than the general case on SBCL. Furthermor, output can be complex for non-integer exponent."
+ (multiple-value-bind (div mod) (truncate b)
+ (if (= 0 mod)
+ (let ((c (mcreate a)))
+ (case div
+ (-3 (^_dfa--3 (matrix-store a) (matrix-store c)))
+ (-2 (^_dfa--2 (matrix-store a) (matrix-store c)))
+ (-1 (^_dfa--1 (matrix-store a) (matrix-store c)))
+ (0 (mfill c 1))
+ (1 (copy-contents a c))
+ (2 (^_dfa-+2 (matrix-store a) (matrix-store c)))
+ (3 (^_dfa-+3 (matrix-store a) (matrix-store c)))
+ (t (^_dfa-df (matrix-store a) (coerce div 'double-float) (matrix-store c))))
+ c)
+ (let ((min (mmin a)))
+ (if (>= min 0)
+ (let ((c (mcreate a)))
+ (^_dfa>=0-df (matrix-store a) (coerce b 'double-float) (matrix-store c))
+ c)
+ (let ((c (mcreate* a :element-type :z))
+ (a2 (mcreate* a :element-type :z)))
+ (copy-contents a a2)
+ (^_cdfa-cdf (matrix-store a2)
+ (coerce b '(complex double-float))
+ (matrix-store c))
+ c))))))
+
+(defmethod .expt ((a real) (b matrix-base-dge) )
+ (if (>= a 0)
+ (let ((c (mcreate b)))
+ (^_df>=0-dfa (coerce a 'double-float) (matrix-store b) (matrix-store c))
+ c)
+ (if (all-integer-elements-p (matrix-store b))
+ (let ((c (mcreate b)))
+ (^_df-dfa (coerce a 'double-float) (matrix-store b) (matrix-store c))
+ c)
+ (let ((c (mcreate* b :element-type :z))
+ (b2 (mcreate* b :element-type :z)))
+ (copy-contents b b2)
+ (^_cdf-cdfa (coerce a '(complex double-float)) (matrix-store b2) (matrix-store c))
+ c))))
(define-constant +generic-function-dfa-to-dfa-map+ ;really bad name
Modified: trunk/src/matrix/store-operators.lisp
==============================================================================
--- trunk/src/matrix/store-operators.lisp (original)
+++ trunk/src/matrix/store-operators.lisp Thu May 20 15:47:06 2010
@@ -132,6 +132,50 @@
(type double-float a))
(map-into c (lambda (x) (expt a x)) b))
+(defun ^_dfa>=0-dfa (a b c)
+ (declare (type (simple-array (double-float 0d0) (*)) a b c))
+ (map-into c #'expt a b))
+
+(defun ^_df>=0-dfa (a b c)
+ (declare (type type-blas-store b c)
+ (type (double-float 0d0) a))
+ (map-into c (lambda (x) (expt a x)) b))
+
+(defun ^_dfa>=0-df (a b c)
+ (declare (type (simple-array (double-float 0d0) (*)) a c)
+ (type double-float b))
+ (map-into c (lambda (x) (expt x b)) a))
+
+(defun ^_dfa-+2 (a c)
+ (declare (type type-blas-store a c))
+ (dotimes (i (length a))
+ (setf (aref c i) (expt (aref a i) 2)))
+ c)
+
+(defun ^_dfa-+3 (a c)
+ (declare (type type-blas-store a c))
+ (dotimes (i (length a))
+ (setf (aref c i) (expt (aref a i) 3)))
+ c)
+
+(defun ^_dfa--1 (a c)
+ (declare (type type-blas-store a c))
+ (dotimes (i (length a))
+ (setf (aref c i) (expt (aref a i) -1)))
+ c)
+
+(defun ^_dfa--2 (a c)
+ (declare (type type-blas-store a c))
+ (dotimes (i (length a))
+ (setf (aref c i) (expt (aref a i) -2)))
+ c)
+
+(defun ^_dfa--3 (a c)
+ (declare (type type-blas-store a c))
+ (dotimes (i (length a))
+ (setf (aref c i) (expt (aref a i) -3)))
+ c)
+
(defun max_dfa-dfa (a b c)
(declare (type type-blas-store a b c))
(map-into c #'max a b))
More information about the lisplab-cvs
mailing list