Changeset 90
- Timestamp:
- 03/22/07 12:07:00 (2 years ago)
- Files:
-
- trunk/mathextra/Blade.d (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/mathextra/Blade.d
r89 r90 13 13 * FEATURES: 14 14 * - Supports any mix of vector addition, subtraction, dot product, and multiplication 15 * by a real scalar.16 * - 80-bit precision is used whenever possible (and does not reduce execution speed).15 * by a real or pure imaginary scalar. 16 * - 80-bit precision is used whenever possible. 17 17 * - Supports mixed-length operations (eg, real[] + double[] + float[]). 18 * - Supports both real and imaginary vectors, and detects type mismatches between them. 19 * (Complex numbers are not yet supported). 18 20 * - When static arrays are used, mismatches in array length are detected at compile time. 19 21 * … … 30 32 * is possible). 31 33 * - Doesn't use EBP register -- this would allow an extra vector in expressions. 32 * - Doesn't support imaginary andcomplex numbers.34 * - Doesn't support complex numbers. 33 35 * - Need a D and an SSE2 version. 34 36 * … … 106 108 } 107 109 110 template CompatibleVectors(A, B) 111 { 112 static if(is (A:real) && is(B: real) 113 || is (A:ireal) && is(B: ireal) 114 || is (A:creal) && is(B: creal)) 115 const bool CompatibleVectors=true; 116 else const bool CompatibleVectors=false; 117 } 108 118 109 119 /** … … 115 125 * If 'knownlength' == 0, it is unknown at compile time. 116 126 */ 117 struct VectorExpr(char[] operations, int knownlength, B...) { 127 struct VectorExpr(BaseType_, char[] operations, int knownlength, B...) { 128 private: 129 alias BaseType_ BaseType; 118 130 alias operations ops; 119 131 alias B ValueTuple; … … 121 133 alias knownlength len; 122 134 // Append another tuple described by 'second', with operation 'op' 123 template JoinResult( char [] op, char [] second, A...) {124 alias VectorExpr!( joinExpressions(op, operations, second), knownlength, B, A) JoinResult;135 template JoinResult(NewType, char [] op, char [] second, A...) { 136 alias VectorExpr!(NewType, joinExpressions(op, operations, second), knownlength, B, A) JoinResult; 125 137 } 126 138 // Construct a vector expression, with the given arguments. 127 static VectorExpr!( operations, knownlength, B) opCall(B b) {128 VectorExpr!( operations, knownlength, B) q;139 static VectorExpr!(BaseType, operations, knownlength, B) opCall(B b) { 140 VectorExpr!(BaseType, operations, knownlength, B) q; 129 141 foreach (i, dummy; b) q.values[i] = b[i]; 130 142 return q; 131 143 } 144 public: 132 145 static if (operations.length>1 && operations[$-2]=='*') { 133 // Already a scalar multiply, so constant fold it. 134 VectorExpr!(operations, knownlength, B) opMul(real x) { 135 return VectorExpr!(operations, knownlength, B)(values[0..$-1], x*values[$-1]); 146 // Optimisation: already a scalar multiply, so constant fold it. 147 VectorExpr!(BaseType, operations, knownlength, B) opMul(real x) { 148 return VectorExpr!(BaseType, operations, knownlength, B)(values[0..$-1], x*values[$-1]); 149 } 150 VectorExpr!(typeof(BaseType*1.0fi), operations, knownlength, B) opMul(ireal x) { 151 return VectorExpr!(typeof(BaseType*1.0fi), operations, knownlength, B)(values[0..$-1], x.im*values[$-1]); 136 152 } 137 153 } else { 138 JoinResult!("*", "a", real) opMul(real x) { 139 return JoinResult!("*", "a", real)(values, x); 140 } 141 } 142 JoinResult!("+", C.ops, C.ValueTuple) opAdd(C)(C x) { 143 return JoinResult!("+", C.ops, C.ValueTuple)(values, x.values); 144 } 145 JoinResult!("-", C.ops, C.ValueTuple) opSub(C)(C x) { 146 return JoinResult!("-", C.ops, C.ValueTuple)(values, x.values); 154 JoinResult!(BaseType, "*", "a", real) opMul(real x) { 155 return JoinResult!(BaseType, "*", "a", real)(values, x); 156 } 157 JoinResult!(typeof(BaseType*1.0fi), "*", "a", real) opMul(ireal x) { 158 return JoinResult!(typeof(BaseType*1.0fi), "*", "a", real)(values, x.im); 159 } 160 } 161 JoinResult!(typeof(BaseType+C.BaseType), "+", C.ops, C.ValueTuple) opAdd(C)(C x) { 162 return JoinResult!(typeof(BaseType+C.BaseType), "+", C.ops, C.ValueTuple)(values, x.values); 163 } 164 JoinResult!(typeof(BaseType-C.BaseType), "-", C.ops, C.ValueTuple) opSub(C)(C x) { 165 return JoinResult!(typeof(BaseType-C.BaseType), "-", C.ops, C.ValueTuple)(values, x.values); 147 166 } 148 167 … … 150 169 static if (operations=="a") { 151 170 void opAssign(A)(A expr) { 171 static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] = " ~ A.BaseType.stringof ~ "[]"); 152 172 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 153 173 performOperation!(expr.ops, "=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 154 174 } 155 175 void opAddAssign(A)(A expr) { 176 static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] += " ~ A.BaseType.stringof ~ "[]"); 156 177 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 157 178 performOperation!(expr.ops, "+=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 158 179 } 159 180 void opSubAssign(A)(A expr) { 181 static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] -= " ~ A.BaseType.stringof ~ "[]"); 160 182 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 161 183 performOperation!(expr.ops, "-=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 162 184 } 163 void opMulAssign(A)(A w) { // Use a template, because we don't want to generate this code 164 // unless it's actually used. 165 static assert(is(A: real)); 185 void opMulAssign(A)(A w) { // Use a template to avoid unnecessary code generation 186 static assert(is (A: real), "Vector type mismatch in " ~ BaseType.stringof ~ "[] *= real"); 166 187 performOperation!("a", "*=", knownlength, real, B[0])(w, values); 167 188 } … … 169 190 } 170 191 171 172 VectorExpr!( "a", Q, X[]) Vec(X, int Q)(X[Q] vals) { VectorExpr!("a", Q, X[]) a; a.values[0]=vals; return a; }173 VectorExpr!("a", 0, X[]) Vec(X)(X[] vals) { VectorExpr!("a", 0, X[]) a; a.values[0]=vals; return a; } 174 175 realdot(A, B)(A a, B b)192 VectorExpr!(X, "a", Q, X[]) Vec(X, int Q)(X[Q] vals) { VectorExpr!(X, "a", Q, X[]) a; a.values[0]=vals; return a; } 193 VectorExpr!(X, "a", 0, X[]) Vec(X)(X[] vals) { VectorExpr!(X, "a", 0, X[]) a; a.values[0]=vals; return a; } 194 195 // Returns ireal if one of A or B is real, and the other is imaginary. 196 typeof(A.BaseType*B.BaseType) dot(A, B)(A a, B b) 176 197 { 177 198 static assert (a.len==0 || b.len==0 || a.len==b.len); 178 return performOperation!(joinExpressions(".", A.ops, B.ops), ".", a.len==0? b.len:a.len, A.ValueTuple, B.ValueTuple)(a.values, b.values); 199 static if (is(A.BaseType: ireal) && is(B.BaseType:ireal)) 200 const MUL = -1; 201 else static if (is(typeof(A.BaseType*B.BaseType): ireal)) 202 const MUL = 1i; 203 else const MUL = 1; 204 return MUL * performOperation!(joinExpressions(".", A.ops, B.ops), ".", a.len==0? b.len:a.len, A.ValueTuple, B.ValueTuple)(a.values, b.values); 179 205 } 180 206 … … 182 208 real performOperation(char [] operations, char [] finaloperation, int knownlength, X...)(X expr) 183 209 { 184 pragma(msg, finaloperation ~ " " ~ operations); 185 const char [] tupstr = vectorTupleToString!(X); 186 const char [] post = makePostfixForX87(operations, tupstr); 187 pragma(msg, post); 188 pragma(msg, tupstr); 210 const char [] tupstr = vectorTupleToString!(X); 211 version(BladeDebug) { 212 pragma(msg, finaloperation ~ " " ~ operations ~ 213 "\nPostfix: " ~ makePostfixForX87(operations, tupstr) ~ "\nTuple: " ~ tupstr); 189 214 static if (knownlength!=0) pragma(msg, "Length is known!"); 190 const char [] qqq = makeAsmX87(tupstr, makePostfixForX87(operations, tupstr), finaloperation); 191 const char [] qqq2 = makeAsmX87(tupstr, makePostfix(operations), finaloperation); 192 pragma(msg, qqq); 193 194 mixin(makeAsmX87(vectorTupleToString!(X), makePostfixForX87(operations, tupstr), finaloperation)); 215 216 const char [] qqq = makeAsmX87(tupstr, makePostfixForX87(operations, tupstr), finaloperation); 217 pragma(msg, "Generated code:"\n ~ qqq); 218 } 219 220 mixin(makeAsmX87(tupstr, makePostfixForX87(operations, tupstr), finaloperation)); 195 221 } 196 222 … … 270 296 template singleType(A) 271 297 { 272 static if (is(A == real[]) ) const char [] singleType = "R";273 else static if (is(A == double[]) ) const char [] singleType = "D";274 else static if (is(A == float[]) ) const char [] singleType = "F";298 static if (is(A == real[])|| is (A==ireal[])) const char [] singleType = "R"; 299 else static if (is(A == double[])||is(A == idouble[])) const char [] singleType = "D"; 300 else static if (is(A == float[])|| is(A==ifloat[])) const char [] singleType = "F"; 275 301 else static if (is(A == real)) const char [] singleType = "S"; 276 302 else const char [] singleType = "?"; … … 496 522 } 497 523 } 498 } else { 524 } else { // length = 1 499 525 char [] next; 500 526 if (typelist[$-1]=='R') 501 527 next = " fld real ptr [" ~ vectorRegister[0] ~ "];\n"; 502 else next = " fld " ~ indexedVector(typelist, operations[0]) ~ ";\n"; 528 else next = " fld "~ operandSize(typelist[$-1]) ~ " [" 529 ~ vectorRegister[0] ~ " + " ~ vectorSize(typelist[$-1]) ~ "*ESI];\n"; 503 530 mainbody ~=next; firstbody~=next; 504 531 ++numOnStack; … … 563 590 auto q = Vec([3.5L, 1.1, 3.8]); 564 591 auto r = Vec([17.0f, 28.1, 1]); 592 auto z = Vec([17.0i, 28.1i, 1i]); 565 593 q -= ((r+p)*18.0L*314.1L - (p-r))* 35; 566 594 real d = dot(r, p+r+r); 567 writefln(d); 595 ireal e = dot(r, z); 596 writefln(d, " ", e); 568 597 p = r - q*2.0; 569 p*=5.6L; // currently fails 570 } 598 p*=5.6L; 599 z = (r*3.1i + r*5.0i)*7.1; 600 z*=3.1; 601 }
