Changeset 90

Show
Ignore:
Timestamp:
03/22/07 12:07:00 (2 years ago)
Author:
Don Clugston
Message:

Support imaginary scalars and vectors (but not complex numbers).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/mathextra/Blade.d

    r89 r90  
    1313* FEATURES: 
    1414*  - 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
    1717*  - 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). 
    1820*  - When static arrays are used, mismatches in array length are detected at compile time. 
    1921* 
     
    3032*     is possible). 
    3133*  - Doesn't use EBP register -- this would allow an extra vector in expressions. 
    32 *  - Doesn't support imaginary and complex numbers. 
     34*  - Doesn't support complex numbers. 
    3335*  - Need a D and an SSE2 version. 
    3436* 
     
    106108} 
    107109 
     110template 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} 
    108118 
    109119/** 
     
    115125 * If 'knownlength' == 0, it is unknown at compile time. 
    116126 */ 
    117 struct VectorExpr(char[] operations, int knownlength, B...) { 
     127struct VectorExpr(BaseType_, char[] operations, int knownlength, B...) { 
     128private: 
     129    alias BaseType_ BaseType; 
    118130    alias operations ops; 
    119131    alias B ValueTuple; 
     
    121133    alias knownlength len; 
    122134    // 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; 
    125137    } 
    126138    // 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; 
    129141        foreach (i, dummy; b) q.values[i] = b[i]; 
    130142        return q; 
    131143    } 
     144public: 
    132145    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]); 
    136152        } 
    137153    } 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); 
    147166    } 
    148167 
     
    150169  static if (operations=="a") { 
    151170    void opAssign(A)(A expr) { 
     171        static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] = " ~ A.BaseType.stringof ~ "[]"); 
    152172        static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 
    153173        performOperation!(expr.ops, "=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 
    154174    } 
    155175    void opAddAssign(A)(A expr) { 
     176        static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] += " ~ A.BaseType.stringof ~ "[]"); 
    156177        static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 
    157178        performOperation!(expr.ops, "+=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 
    158179    } 
    159180    void opSubAssign(A)(A expr) { 
     181        static assert(CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] -= " ~ A.BaseType.stringof ~ "[]"); 
    160182        static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 
    161183        performOperation!(expr.ops, "-=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 
    162184    } 
    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"); 
    166187        performOperation!("a", "*=", knownlength, real, B[0])(w, values); 
    167188    } 
     
    169190} 
    170191 
    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 real dot(A, B)(A a, B b) 
     192VectorExpr!(X, "a", Q, X[]) Vec(X, int Q)(X[Q] vals) { VectorExpr!(X, "a", Q, X[]) a; a.values[0]=vals; return a; } 
     193VectorExpr!(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. 
     196typeof(A.BaseType*B.BaseType) dot(A, B)(A a, B b) 
    176197{ 
    177198    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); 
    179205} 
    180206 
     
    182208real performOperation(char [] operations, char [] finaloperation, int knownlength, X...)(X expr) 
    183209{ 
    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); 
    189214    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)); 
    195221} 
    196222 
     
    270296template singleType(A) 
    271297{ 
    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"; 
    275301    else static if (is(A == real))   const char [] singleType = "S"; 
    276302    else const char [] singleType = "?"; 
     
    496522      } 
    497523    } 
    498 } else { 
     524} else { // length = 1 
    499525    char [] next; 
    500526    if (typelist[$-1]=='R') 
    501527        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"; 
    503530    mainbody ~=next; firstbody~=next; 
    504531    ++numOnStack; 
     
    563590    auto q = Vec([3.5L, 1.1, 3.8]); 
    564591    auto r = Vec([17.0f, 28.1, 1]); 
     592    auto z = Vec([17.0i, 28.1i, 1i]); 
    565593    q -= ((r+p)*18.0L*314.1L - (p-r))* 35; 
    566594    real d = dot(r, p+r+r); 
    567     writefln(d); 
     595    ireal e = dot(r, z); 
     596    writefln(d, " ", e); 
    568597    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