Changeset 129

Show
Ignore:
Timestamp:
11/06/07 02:44:19 (1 year ago)
Author:
Don Clugston
Message:

BladeRank? now works for unary operators. First steps to constant folding/vector expression simplification.

Files:

Legend:

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

    r126 r129  
    275275} 
    276276 
     277/+ 
     278// Simplify a vector expression 
     279//  - Use slicing distributive law: A[B..C] for expressions A,B,C 
     280//     where B and C are both rank 0, and A is rank 1, the slice can 
     281//     be moved to every vector inside A. 
     282//  - Convert A[]*B into B*A[] (only where * is commutative, 
     283//      not valid for quaternions). 
     284// Use associativity of *: A*(B*C[]) == (A*B)*C[] 
     285// Convert -A*B into +(-A)*B whenever possible. 
     286// Combine all scalars into a single scalar. 
     287void simplify(inout AbstractSyntaxTree tree) 
     288{ 
     289    // Part 1: simplifications which only change the expression string. 
     290    for (int i=0; i<tree.expression.length; ++i) { 
     291         int x = i+exprLength(expression[i..$]); 
     292         if (x==tree.expression.length) continue; 
     293         if (tree.expression[x+1]=='[') { // potentially a slice 
     294            int y = x + 1 + exprLength(tree.expression[x+1..$-1]) 
     295            if (y+2<tree.expression.length && tree.expression[y..y+1]=="..") { 
     296                // it's a slice 
     297            } 
     298              
     299         }         
     300    } 
     301    // Part 2: simplifications which change the types 
     302} 
     303+/ 
    277304 
    278305// Categorise the expression, and dispatch to the appropriate code generator. 
  • trunk/blade/BladeRank.d

    r125 r129  
    115115int exprLength(char [] s) 
    116116{ 
    117     if (s[0]>='A' && s[0]<='Z') 
     117    if ((s[0]>='A' && s[0]<='Z') || s[0]=='$') 
    118118        return 0; 
    119119    int i = 0; 
     
    135135} 
    136136 
     137/** Determine the (tensor) rank of a sub-expression 
     138*/ 
     139int subexprRank(char [] expr, int [] rank) 
     140{ 
     141    if (expr.length==1) { 
     142        if (expr=="$") return 0; 
     143        return rank[expr[0]-'A']; 
     144    } 
     145    // strip off the parentheses 
     146    return exprRank(expr[1..$-1], rank); 
     147} 
     148 
    137149/** Returns the (tensor) rank of the expression expr. 
    138150 * 
     
    142154 */ 
    143155int exprRank(char [] expr, int [] rank) 
    144 
     156{     
     157    // BUG: also need to deal with comma, ?:, &&, ||, is, !is, in,  
     158    // unary &, unary ! 
     159         
     160    // Deal with ++ and --. 
     161    if (expr.length>2 && (expr[0..2]=="++" || expr[0..2]=="--")) { 
     162        int r = subexprRank(expr[2..$], rank); 
     163        assert(r==0, "Can only use ++ and -- on scalars"); 
     164        return r; 
     165    } 
     166    if (expr.length>2 && (expr[$-2..$]=="++" || expr[$-2..$]=="--")) { 
     167//        assert(0, expr[0..$-2]); 
     168        int r = subexprRank(expr[0..$-2], rank); 
     169        assert(r==0, "Can only use ++ and -- on scalars"); 
     170        return r; 
     171    } 
     172    // Deal with unary operators 
     173    if (expr[0]=='+' || expr[0]=='-') return subexprRank(expr[1..$], rank); 
     174//    if (expr[0]=='~' || expr[0]=='*') { return 0; } 
     175     
    145176    int x = exprLength(expr); 
    146177    int y = x+1; 
    147     if (expr[x+2]=='=') ++y; // deal with op=. 
    148      
     178    // Deal with shifts, op=, and NCEG operators 
     179    while (expr[y+1]=='<' || expr[y+1]=='>' || expr[y+1]=='=') ++y;     
     180 
    149181    char [] op = expr[x+1..y+1];     
    150182    char [] left = expr[0..x+1]; 
    151183    char [] right = expr[y+1..$]; 
    152     int lrank = (left.length==1)?  rank[left[0]-'A'] : exprRank(left[1..$-1], rank); 
    153     int rrank = (right.length==1)?  rank[right[0]-'A'] : exprRank(right[1..$-1], rank); 
     184    if (expr[x+1]=='[') right = expr[y+1..$-1]; // drop off the ']'. 
     185    int lrank = subexprRank(left, rank); 
     186    if (op=="[") { 
     187        assert(lrank>0, "Cannot index a scalar"); 
     188        int z = exprLength(right); 
     189        if (z+1 == right.length) { 
     190            // indexing  --  reduces the rank by 1. 
     191            int rrank = subexprRank(right, rank); 
     192            assert(rrank == 0, "Vector can only be indexed by a scalar"); 
     193            return lrank - 1; 
     194        } else { 
     195            // slicing -- does not change the rank 
     196            assert(z+3 < right.length && right[z+1..z+3]=="..", ".. expected" ~ right); 
     197            char [] start = right[0..z+1];  
     198            char [] end = right[z+3..$]; 
     199            int startrank = subexprRank(start, rank); 
     200            int endrank = subexprRank(end, rank); 
     201            assert(startrank==0 && endrank==0, "Vector can only be sliced by a scalar");             
     202            return lrank;             
     203        } 
     204    } 
     205    int rrank = subexprRank(right, rank); 
    154206    if (op=="+" || op=="-" || op=="=" || op=="+=" || op=="-=") { 
    155207        assert(lrank==rrank, "Rank error in expression"); 
     208        return lrank; 
     209    } 
     210    if (op=="~") { // concatentating scalars and vectors, or vectors and matrices, is permitted 
     211        assert(lrank==rrank || lrank==(rrank+1) || rrank==(lrank+1), "Rank error in expression"); 
     212        return (lrank>rrank)? lrank: rrank; 
     213    } 
     214    if (op=="~=") { // can do vector~=scalar, but not scalar~=vector. 
     215        assert(lrank==rrank || lrank==(rrank+1), "Rank error in expression"); 
    156216        return lrank; 
    157217    } 
     
    170230 
    171231unittest { 
    172     assert(exprRank("A+(B*C)", [1,1,0])==1); 
     232    assert(exprRank("A+((((++B)+D)--)*C)", [1,0,1, 0])==1); 
    173233    assert(exprRank("A+(B*C)", [0,0,0])==0); 
    174234    assert(exprRank("A=(B*C)", [2,0,2])==2); 
     
    176236    assert(exprRank("D+=((A+C)*B)", [2,0,2,2])==2); 
    177237    assert(exprRank("D+=((A&C)*B)", [0,1,0,1])==1); 
     238    assert(exprRank("A+=(A[B..C])", [3,0,0])==3); 
     239    assert(exprRank("C+=(A[B])", [3,0,2])==2); 
     240    assert(exprRank("C~=(((A[B])[B])~C)", [3,0,2])==2); 
    178241} 
    179242 
     
    212275static assert(is(exprElementType!("A+(B*C)", float[], double[], double).ElemType == double)); 
    213276} 
     277 
     278char [] subexprSimplify(char [] expr, int [] rank) 
     279{ 
     280    if (expr.length==1) return expr; 
     281    // strip off the parentheses before simplifying 
     282    return "(" ~ exprSimplify(expr[1..$-1], rank) ~ ")"; 
     283} 
     284 
     285// TODO: Rewrite the expression, taking advantage of distributivity of [] and 
     286// associativity of *. 
     287char [] exprSimplify(char [] expr, int [] rank) 
     288{     
     289    // BUG: also need to deal with comma, ?:, &&, ||, is, !is, in,  
     290    // unary &, unary ! 
     291         
     292    // Deal with ++ and --. 
     293    if (expr.length>2 && (expr[0..2]=="++" || expr[0..2]=="--")) { 
     294        return expr[0..2] ~ subexprSimplify(expr[2..$], rank); 
     295    } 
     296    if (expr.length>2 && (expr[$-2..$]=="++" || expr[$-2..$]=="--")) { 
     297        return subexprSimplify(expr[0..$-2], rank) ~ expr[$-2..$]; 
     298    } 
     299    // Deal with unary operators 
     300    if (expr[0]=='+' || expr[0]=='-') return subexprSimplify(expr[1..$], rank); 
     301    
     302    int x = exprLength(expr); 
     303    int y = x+1; 
     304    // Deal with shifts, op=, and NCEG operators 
     305    while (expr[y+1]=='<' || expr[y+1]=='>' || expr[y+1]=='=') ++y;     
     306 
     307    char [] op = expr[x+1..y+1];     
     308    char [] left = expr[0..x+1]; 
     309    char [] right = expr[y+1..$]; 
     310    if (expr[x+1]=='[') right = expr[y+1..$-1]; // drop off the ']'. 
     311    int lrank = subexprRank(left, rank); 
     312    if (op=="[") { 
     313        // TODO: 
     314        // We know that 'right' is a 100% scalar. We only need to deal with 'left' 
     315        // We already know that left is a vector or matrix. 
     316        // where I, J, K are scalars: 
     317        // (X*I)[K]  -->  I*(X[K])   where X is any tensor expression 
     318        // (I*X)[K]  -->  I*(X[K]) 
     319        //  
     320        return subexprSimplify(left, rank) ~ "[" ~ right ~ "]"; 
     321    } 
     322    //TODO: 
     323    return subexprSimplify(left, rank) ~ op ~ subexprSimplify(right, rank); 
     324} 
     325 
     326unittest { 
     327     assert(exprSimplify("A+=((B++)*(C[B..B]))", [1,0,1])=="A+=((B++)*(C[B..B]))"); 
     328} 
  • trunk/blade/SyntaxTree.d

    r128 r129  
    263263    preOp!("--") opSubAssign(T:int=int)(int x){ return null; }   
    264264 
    265     AST!(text ~ "[" ~ T.text ~ ".." ~ U.text ~"]") opSlice(T, U)(T x, U y){ return null; } 
    266     AST!(text ~ "[" ~ AllText!(T) ~ "]") opIndex(T...)(T x){ return null; } 
     265    AST!("(" ~ text ~ "[" ~ T.text ~ ".." ~ U.text ~"])") opSlice(T, U)(T x, U y){ return null; } 
     266    AST!("(" ~ text ~ "[" ~ AllText!(T) ~ "])") opIndex(T...)(T x){ return null; } 
    267267    AST!("(" ~ text ~ "(" ~ AllText!(T) ~ "))") opCall(T...)(T){ return null; } 
    268268    AST!("((" ~ text ~ "[" ~ AllText!(T) ~ "])=" ~ U.text ~ ")") opIndexAssign(U, T...)(U,T){ return null; } 
     
    361361    assert(mixin(mixin_getPrecedence("A[B,$-C/D]=E+F"))=="(A[B,($-(C/D))])=(E+F)"); 
    362362    assert(mixin(mixin_getPrecedence("A[B]=E+F"))=="(A[B])=(E+F)"); 
    363     assert(mixin(mixin_getPrecedence("A[$]=E+F"))=="(A[$])=(E+F)"); 
    364     assert(mixin(mixin_getPrecedence("G-=A[B][C..B^D][D]*E+F"))=="G-=((A[B][C..(B^D)][D]*E)+F)"); 
    365     assert(mixin(mixin_getPrecedence("E=A[B,C/D]*F"))=="E=(A[B,(C/D)]*F)"); 
     363    assert(mixin(mixin_getPrecedence("A+=B[E]"))=="A+=(B[E])"); 
     364    assert(mixin(mixin_getPrecedence("A[$]=A[E]+F"))=="(A[$])=((A[E])+F)"); 
     365    assert(mixin(mixin_getPrecedence("G-=A[B][C..B^D][D]*E+F"))=="G-=(((((A[B])[C..(B^D)])[D])*E)+F)"); 
     366    assert(mixin(mixin_getPrecedence("E=A[B,C/D]*F"))=="E=((A[B,(C/D)])*F)"); 
    366367    assert(mixin(mixin_getPrecedence("(A+B)  in(C^D)"))=="(A+B)in(C^D)"); 
    367368    assert(mixin(mixin_getPrecedence("A"))=="A");