Changeset 97
- Timestamp:
- 04/12/07 17:20:00 (1 year ago)
- Files:
-
- trunk/blade/Blade.d (modified) (20 diffs)
- trunk/blade/BladeArticle.txt (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/blade/Blade.d
r96 r97 86 86 // 'abstract syntax tree' constructed from multiple templates. Instead, 87 87 // the expression is constructed as a normal, human-readable text string 88 // (for example, "#a+(#b*#c-#d)"). 88 // (for example, "#a+(#b*#c-#d)"). The expression arguments (vectors or scalars) 89 // are represented by a # symbol followed by an alphabetic character, beginning 90 // at #a. 89 91 // This string is a template parameter for a struct, which 90 92 // contains a tuple of all the arguments used in the expression. … … 122 124 123 125 // Check for type mismatches when performing vector assignment. 124 template CompatibleVectors(A, B)126 template AssignableVectors(A, B) 125 127 { 126 128 static if(is (A:real) && is(B: real) 127 129 || is (A:ireal) && is(B: ireal) 128 130 || is (A:creal) && is(B: creal)) 129 const bool CompatibleVectors=true;130 else const bool CompatibleVectors=false;131 const bool AssignableVectors=true; 132 else const bool AssignableVectors=false; 131 133 } 132 134 … … 171 173 } else { 172 174 // trick: typeof(C*C) converts imag to real, but leaves real & complex unchanged. 173 JoinResult!(typeof(BaseType*C), "*", "#a", typeof(C*C *1.0L)) opMul(C)(C x) {175 JoinResult!(typeof(BaseType*C), "*", "#a", typeof(C*C)) opMul(C)(C x) { 174 176 static assert(is(C: real) || is(C:ireal) || is(C:creal), "Can only multiply by scalars"); 175 177 static if (is(C: ireal)) { 176 return JoinResult!(typeof(BaseType*C), "*", "#a", real)(values, x.im); 177 } else static if (is(C: real)) { 178 return JoinResult!(BaseType, "*", "#a", real)(values, x); 179 } else { 178 return JoinResult!(typeof(BaseType*C), "*", "#a", typeof(C*C))(values, x.im); 179 } else 180 180 return JoinResult!(typeof(BaseType*C), "*", "#a", C)(values, x); 181 }182 181 } 183 182 } … … 193 192 static if (operations=="#a") { 194 193 void opAssign(A)(A expr) { 195 static assert( CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] = " ~ A.BaseType.stringof ~ "[]");194 static assert(AssignableVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] = " ~ A.BaseType.stringof ~ "[]"); 196 195 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 197 196 performOperation!(void, expr.ops, "=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 198 197 } 199 198 void opAddAssign(A)(A expr) { 200 static assert( CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] += " ~ A.BaseType.stringof ~ "[]");199 static assert(AssignableVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] += " ~ A.BaseType.stringof ~ "[]"); 201 200 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 202 201 performOperation!(void, expr.ops, "+=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 203 202 } 204 203 void opSubAssign(A)(A expr) { 205 static assert( CompatibleVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] -= " ~ A.BaseType.stringof ~ "[]");204 static assert(AssignableVectors!(BaseType,A.BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] -= " ~ A.BaseType.stringof ~ "[]"); 206 205 static assert(len==0 || expr.len == 0 || len == expr.len, "Vector lengths must match"); 207 206 performOperation!(void, expr.ops, "-=", len==0? expr.len : len, expr.ValueTuple, B[0])(expr.values, values); 208 207 } 209 void opMulAssign(A)(A w) { // Use a template to avoid unnecessary code generation210 static assert( (is (BaseType: creal) && is(A:ireal) || is(A:creal)) || is (A: real), "Vector type mismatch in " ~ BaseType.stringof ~ "[] *= " ~ A.stringof);208 void opMulAssign(A)(A w) { // *= is not allowed to change the vector type. 209 static assert(is (typeof(BaseType*A) : BaseType), "Vector type mismatch in " ~ BaseType.stringof ~ "[] *= " ~ A.stringof); 211 210 performOperation!(void, "#a", "*=", knownlength, A, B[0])(w, values); 212 211 } … … 227 226 228 227 // Dot product of two vectors. 229 // Returns ireal if one of A or B is real, and the other is imaginary.228 // Note: Returns ireal if one of A or B is real, and the other is imaginary. 230 229 typeof(A.BaseType*B.BaseType) dot(A, B)(A a, B b) 231 230 { … … 276 275 // of the types in the tuple. 277 276 277 // Create a single-character string representing the type A. 278 278 template singleType(A) 279 279 { 280 static if (is(A == real[]) || is(A==ireal[])) const char [] singleType = "R"; 281 else static if (is(A == creal[]) || is(A==cdouble[])||is(A==cfloat[])) const char [] singleType = "Z"; 280 static if (is(A == real[]) || is(A == ireal[])) const char [] singleType = "R"; 282 281 else static if (is(A == double[])|| is(A == idouble[]))const char [] singleType = "D"; 283 else static if (is(A == float[]) || is(A==ifloat[])) const char [] singleType = "F"; 284 else static if (is(A == real) || is (A == ireal)) const char [] singleType = "S"; 285 else static if (is(A == creal)) const char [] singleType = "C"; 282 else static if (is(A == float[]) || is(A == ifloat[])) const char [] singleType = "F"; 283 else static if (is(A == creal[]) || is(A == cdouble[]) || is(A==cfloat[])) const char [] singleType = "Z"; 284 285 else static if (is(A == real) || is (A == ireal)) const char [] singleType = "r"; 286 else static if (is(A == double) || is (A == idouble)) const char [] singleType = "d"; 287 else static if (is(A == float) || is (A == ifloat)) const char [] singleType = "f"; 288 else static if (is(A : creal)) const char [] singleType = "z"; 286 289 else const char [] singleType = "?"; 287 290 } … … 376 379 } 377 380 378 // Converts an infix string into postfix. 381 // Converts an infix string into postfix. Also strips off the # symbols. 379 382 // Apply x87-specific optimisations during the conversion. 380 383 char [] makePostfixForX87(char [] operations, char [] typelist) … … 397 400 // result of a multiply. Since + is commutative, we can achieve this 398 401 // by calculating the value with the multiply, before the other one. 402 // Note that there a few cases that could still be improved, eg with 403 // ((a*b)+(c*d))+(e*f), all three multiplies could be performed 404 // before any of the additions. This would require stack rotation 405 // operations (can't be done with simple postfix), greatly increasing the 406 // complexity of the mini-compiler.). 399 407 if (operations[x+1]=='+') { 400 408 if (second[$-1]=='*' && first[$-1]!='*') { … … 402 410 } 403 411 } 404 // We can also do the same thing with -, but we need to use fsubr405 // instead of fsub. 412 // We can also do the same thing with -, but we'll need to use fsubr 413 // instead of fsub. We use _ to mean reversed subtraction. 406 414 if (operations[x+1]=='-') { 407 415 if (second[$-1]=='*' && first[$-1]!='*') { … … 449 457 } 450 458 451 int scalarNum(char [] typelist, char var)459 int realScalarNum(char [] typelist, char var) 452 460 { 453 461 int k=0; 454 462 for (int i=0; i<var-'a'; ++i) { 455 if (typelist[i]==' S') ++k;463 if (typelist[i]=='r') ++k; 456 464 } 457 465 return k; … … 462 470 { 463 471 switch(var) { 472 case 'r': 464 473 case 'R': return "real ptr "; 474 case 'd': 465 475 case 'D': return "double ptr "; 476 case 'f': 466 477 case 'F': return "float ptr "; 467 478 } … … 503 514 // Does it contain any types we can't deal with? 504 515 foreach(ch; typelist) { 505 // can only do float, double, and 80-bit vectors and scalars.506 if (ch!='R' && ch!='D' && ch!='F' && ch!=' S') return false;516 // can only do float, double, and 80-bit vectors, and scalars. 517 if (ch!='R' && ch!='D' && ch!='F' && ch!='r' && ch!='d' && ch!='s') return false; 507 518 } 508 519 // BUG: should also check if it will overflow the FPU stack … … 520 531 // Does it contain any types we can't deal with? 521 532 foreach(ch; typelist) { 522 // can only do double vectors and scalars.523 if (ch!='D' && ch!=' S') return false;533 // can only do double vectors and double scalars. 534 if (ch!='D' && ch!='d') return false; 524 535 } 525 536 return false; // not yet implemented … … 563 574 } 564 575 576 char [] opToSSE2(char op) 577 { 578 switch (op) { 579 case '*': 580 case '.': return "mulpd"; 581 case '+': return "addpd"; 582 case '-': return "subpd"; 583 case '_': return "**BUG**"; // Non-existent! 584 } 585 } 586 587 char [] opToSSE(char op) 588 { 589 switch (op) { 590 case '*': 591 case '.': return "mulps"; 592 case '+': return "addps"; 593 case '-': return "subps"; 594 case '_': return "**BUG**"; // Non-existent! 595 } 596 } 597 598 565 599 char [] generateCodeForAsmSSE2(int knownlength, char [] typelist, char [] operations, char [] finaloperation) 566 600 { 601 // Use ESI as the index register. 567 602 char [] result="asm {"\n 568 603 ~"L1: \n" 569 604 ~ " movapd XMM1, [ESI+EAX];"\n 570 605 ~ " mulpd XMM1, XMM2;"\n 571 ~ " addpd XMM1, [EDI+E AX];"\n572 ~ " movapd [EDI+E AX], XMM1;"\n573 ~ " add E AX, 16;"\n606 ~ " addpd XMM1, [EDI+ESI];"\n 607 ~ " movapd [EDI+ESI], XMM1;"\n 608 ~ " add ESI, 16;"\n 574 609 ~ " js L1;"\n 575 610 ~ "}"\n; … … 615 650 char [] incrementRealVectors=""; 616 651 617 // Create local variables for everything (avoid bug #1028)652 // Create local variables for pointers to vectors (avoid bug #1125) 618 653 int vecnum = 0; 619 654 for (int i=0; i< typelist.length;++i) { 620 if (typelist[i]=='S'){ 621 result~= " real var" ~ itoa(i) ~ " = expr[" ~ itoa(i) ~ "];\n"; 622 } else { 655 if (isVector(typelist[i])){ 623 656 result~= " auto vec" ~ itoa(i) ~ " = expr[" ~itoa(i) ~"].ptr;\n"; 624 657 if (typelist[i]=='R') { … … 628 661 } 629 662 } 630 result ~= " int veclength = expr[" ~itoa(findFirstVector(typelist)) ~"].length;\n"; 663 if (knownlength==0) { 664 result ~= " int veclength = expr[" ~itoa(findFirstVector(typelist)) ~"].length;\n"; 665 } 631 666 632 667 bool isDotProduct = (operations[$-1]=='.'); … … 652 687 } 653 688 ++numvecs; 654 } else {655 result ~= " fld real ptr var"~ itoa(i) ~";\n";689 } else if (typelist[i]=='r') { 690 result ~= " fld real ptr expr["~ itoa(i) ~"];\n"; 656 691 ++numconsts; 657 692 ++numScalarsOnStack; … … 669 704 ++numScalarsOnStack; 670 705 // load multiplier for *= 671 result ~= " fld double ptr var0;\n";706 result ~= " fld double ptr expr[0];\n"; 672 707 } 673 708 int done=0; … … 712 747 mainbody ~= next; firstbody ~= next; 713 748 done +=2; 714 } else { // multiply by scalar. Note that there's an extra item on the stack when we're in the body of the loop. 715 firstbody ~= " fmul ST, ST(" ~ itoa(numOnStack + numScalarsOnStack - scalarNum(typelist, operations[done]-'a')) ~ "); //var" ~ itoa(operations[done]-'a') ~ \n; 716 mainbody ~= " fmul ST, ST(" ~ itoa(1 + numOnStack + numScalarsOnStack - scalarNum(typelist, operations[done]-'a')) ~ "); //var" ~ itoa(operations[done]-'a') ~ \n; 717 // NOTE: For scalar float or double values, we can multiply directly, saving one slot on the FP stack. 718 // next = " " ~ opToX87(operations[done+1]) ~ " double ptr var" ~ itoa(operations[done]-'a') ~";\n"; 719 // mainbody ~= next; firstbody ~= next; 749 } else { // multiply by scalar. 750 if (typelist[operations[done]-'a']=='r') { 751 // Multiply by real scalar, which is already on the stack. Note that there's an extra item on the stack when we're in the body of the loop. 752 firstbody ~= " fmul ST, ST(" ~ itoa(numOnStack + numScalarsOnStack - realScalarNum(typelist, operations[done]-'a')) ~ "); //var" ~ itoa(operations[done]-'a') ~ \n; 753 mainbody ~= " fmul ST, ST(" ~ itoa(1 + numOnStack + numScalarsOnStack - realScalarNum(typelist, operations[done]-'a')) ~ "); //var" ~ itoa(operations[done]-'a') ~ \n; 754 } else { 755 // For scalar float or double values, we can multiply directly, saving one slot on the FP stack. 756 next = " fmul " ~ operandSize(typelist[operations[done]-'a']) ~ "expr[" ~ itoa(operations[done]-'a') ~"];\n"; 757 mainbody ~= next; firstbody ~= next; 758 } 720 759 done +=2; 721 760 } … … 811 850 writefln(d, " ", e); 812 851 assert(d==2267.625); 813 q*=2.1 L;852 q*=2.1; 814 853 815 854 /*
