Changeset 129
- Timestamp:
- 11/06/07 02:44:19 (1 year ago)
- Files:
-
- trunk/blade/Blade.d (modified) (1 diff)
- trunk/blade/BladeRank.d (modified) (6 diffs)
- trunk/blade/SyntaxTree.d (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/Blade.d
r126 r129 275 275 } 276 276 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. 287 void 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 +/ 277 304 278 305 // Categorise the expression, and dispatch to the appropriate code generator. trunk/blade/BladeRank.d
r125 r129 115 115 int exprLength(char [] s) 116 116 { 117 if ( s[0]>='A' && s[0]<='Z')117 if ((s[0]>='A' && s[0]<='Z') || s[0]=='$') 118 118 return 0; 119 119 int i = 0; … … 135 135 } 136 136 137 /** Determine the (tensor) rank of a sub-expression 138 */ 139 int 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 137 149 /** Returns the (tensor) rank of the expression expr. 138 150 * … … 142 154 */ 143 155 int 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 145 176 int x = exprLength(expr); 146 177 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 149 181 char [] op = expr[x+1..y+1]; 150 182 char [] left = expr[0..x+1]; 151 183 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); 154 206 if (op=="+" || op=="-" || op=="=" || op=="+=" || op=="-=") { 155 207 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"); 156 216 return lrank; 157 217 } … … 170 230 171 231 unittest { 172 assert(exprRank("A+( B*C)", [1,1,0])==1);232 assert(exprRank("A+((((++B)+D)--)*C)", [1,0,1, 0])==1); 173 233 assert(exprRank("A+(B*C)", [0,0,0])==0); 174 234 assert(exprRank("A=(B*C)", [2,0,2])==2); … … 176 236 assert(exprRank("D+=((A+C)*B)", [2,0,2,2])==2); 177 237 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); 178 241 } 179 242 … … 212 275 static assert(is(exprElementType!("A+(B*C)", float[], double[], double).ElemType == double)); 213 276 } 277 278 char [] 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 *. 287 char [] 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 326 unittest { 327 assert(exprSimplify("A+=((B++)*(C[B..B]))", [1,0,1])=="A+=((B++)*(C[B..B]))"); 328 } trunk/blade/SyntaxTree.d
r128 r129 263 263 preOp!("--") opSubAssign(T:int=int)(int x){ return null; } 264 264 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; } 267 267 AST!("(" ~ text ~ "(" ~ AllText!(T) ~ "))") opCall(T...)(T){ return null; } 268 268 AST!("((" ~ text ~ "[" ~ AllText!(T) ~ "])=" ~ U.text ~ ")") opIndexAssign(U, T...)(U,T){ return null; } … … 361 361 assert(mixin(mixin_getPrecedence("A[B,$-C/D]=E+F"))=="(A[B,($-(C/D))])=(E+F)"); 362 362 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)"); 366 367 assert(mixin(mixin_getPrecedence("(A+B) in(C^D)"))=="(A+B)in(C^D)"); 367 368 assert(mixin(mixin_getPrecedence("A"))=="A");
