DoubleArray.st
branchjv
changeset 19035 06aeb1259ba6
parent 18120 e3a375d5f6a8
parent 19031 b8bbe1983d3a
child 20343 0719a15ae26d
--- a/DoubleArray.st	Fri Jan 15 06:50:38 2016 +0100
+++ b/DoubleArray.st	Sat Jan 16 06:58:29 2016 +0100
@@ -11,6 +11,8 @@
 "
 "{ Package: 'stx:libbasic' }"
 
+"{ NameSpace: Smalltalk }"
+
 AbstractNumberVector variableDoubleSubclass:#DoubleArray
 	instanceVariableNames:''
 	classVariableNames:''
@@ -83,8 +85,6 @@
 "
 ! !
 
-
-
 !DoubleArray class methodsFor:'queries'!
 
 elementByteSize
@@ -96,21 +96,157 @@
     "Created: / 15-09-2011 / 14:12:46 / cg"
 ! !
 
-
-
 !DoubleArray methodsFor:'queries'!
 
 defaultElement
     ^ Float zero
 ! !
 
+!DoubleArray methodsFor:'vector arithmetic'!
+
+dot: aFloatVector
+    "Return the dot product of the receiver and the argument.
+     Raises an error, if the argument is not of the same size as the receiver."
+
+    | mySize result |
+
+%{
+    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0))
+     && (__ClassInstPtr(__qClass(aFloatVector))->c_ninstvars == __mkSmallInteger(0))) {
+        INT __mySize = __doubleArraySize(self);
+        double __result = 0.0;
+        double *__p1 = __DoubleArrayInstPtr(self)->d_element;
+
+        if (__mySize > 0) {
+            if (__isFloats(aFloatVector)) {
+                INT __otherSize = __floatArraySize(aFloatVector);
+
+                if (__mySize == __otherSize) {
+                    float *__p2 = __FloatArrayInstPtr(aFloatVector)->f_element;
+                    INT __i;
+                    /* how about inline-mmx-asm for this ... */
+                    for (__i=0; __i<__mySize; __i++) {
+                        __result += (__p1[__i] * __p2[__i]);
+                    }
+                    RETURN (__MKFLOAT(__result));
+                }
+            } else if (__isDoubles(aFloatVector)) {
+                INT __otherSize = __doubleArraySize(aFloatVector);
+
+                if (__mySize == __otherSize) {
+                    double *__p2 = __DoubleArrayInstPtr(aFloatVector)->d_element;
+                    INT __i;
+                    /* how about inline-mmx-asm for this ... */
+                    for (__i=0; __i<__mySize; __i++) {
+                        __result += (__p1[__i] * __p2[__i]);
+                    }
+                    RETURN (__MKFLOAT(__result));
+                }
+            }
+        }
+    }
+%}.
+    ^ super dot:aFloatVector
+
+    "
+     |v|
+
+     v := #(2.0 2.0 1.0) asFloatArray.
+     v dot:v.
+    "
+    "
+     |v1 v2|
+
+     v1 := FloatArray new:10000 withAll:2.
+     v2 := FloatArray new:10000 withAll:3.
+     Time millisecondsToRun:[
+        10000 timesRepeat:[
+          v1 dot:v2.
+        ]
+     ]
+    "
+
+    "Created: / 29-05-2007 / 13:13:39 / cg"
+!
+
+hornerMultiplyAndAdd:x
+    "primitive support for horner's-method computation of polynomials.
+     The vector is interpreted as providing the factors for a polynomial,
+        an*x^n + (an-1)*x^(n-1) + ... + a2(x) + a1
+     where the ai are the elements of the Array.
+     The highest rank factor is at the first position, the 0-rank constant at last.
+     This is inlined c-code, which may get compiled to fast machine code,
+     using multiply-and-add or vector instructions, if the CPU/Compiler support them."
+
+    | mySize result |
+
+%{
+    double __x;
+
+    if (__isFloat(x)) {
+        __x = __floatVal(x);
+    } else if (__isShortFloat(x)) {
+        __x = (double)__shortFloatVal(x);
+    } else if (__isSmallInteger(x)) {
+        __x = (double)(__intVal(x));
+    } else {
+        goto getOutOfHere;
+    }
+
+    if (__ClassInstPtr(__qClass(self))->c_ninstvars == __mkSmallInteger(0)) {
+        INT __mySize = __doubleArraySize(self);
+        double *__elements = __DoubleArrayInstPtr(self)->d_element;
+        double __result = __elements[0];
+
+        if (__mySize > 1) {
+            INT __i;
+            /* how about inline-mmx-asm for this ... */
+            for (__i=1; __i<__mySize; __i++) {
+                __result = (__result * __x) + __elements[__i];
+            }
+        }
+        RETURN (__MKFLOAT(__result));
+    }
+getOutOfHere: ;    
+%}.
+    ^ super hornerMultiplyAndAdd:x
+
+    "
+     |v|
+     v := #(2.0 3.0 4.0) asDoubleArray.
+     v  hornerMultiplyAndAdd:10.
+    
+     |v|
+     v := Array new:100 withAll:2.0.
+     v hornerMultiplyAndAdd:10
+
+     |v|
+     v := Array new:100 withAll:2.0.
+     Time millisecondsToRun:[
+        10000 timesRepeat:[ v hornerMultiplyAndAdd:10]
+     ]
+
+     |v|
+     v := FloatArray new:100 withAll:2.
+     Time millisecondsToRun:[
+        10000 timesRepeat:[ v hornerMultiplyAndAdd:10]
+     ]
+
+     |v|
+     v := DoubleArray new:100 withAll:2.
+     Time millisecondsToRun:[
+        10000 timesRepeat:[ v hornerMultiplyAndAdd:10]
+     ]
+    "
+! !
+
 !DoubleArray class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/DoubleArray.st,v 1.24 2014-09-23 20:24:21 cg Exp $'
+    ^ '$Header$'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/DoubleArray.st,v 1.24 2014-09-23 20:24:21 cg Exp $'
+    ^ '$Header$'
 ! !