Overflow.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. var NonwideningOperation = {
  6. None: 0,
  7. Neg: 1,
  8. Ld: 2,
  9. ConvNum: 3,
  10. Count: 4
  11. };
  12. var bools = [false, true];
  13. // Test helper constants and variables
  14. var indent = 0;
  15. var nonwideningOperation = -1;
  16. var minTreeDepth = (53 - 32) >> 1;
  17. var maxTreeDepth = (53 - 32 + 1) << 1;
  18. var midTreeDepth = (minTreeDepth + maxTreeDepth) >> 1;
  19. for(var treeDepth = minTreeDepth;
  20. treeDepth <= maxTreeDepth;
  21. treeDepth += treeDepth <= midTreeDepth ? treeDepth - (minTreeDepth - 1) : ((maxTreeDepth - treeDepth) >> 1) + 1) {
  22. for(var treeBranches = 1; treeBranches <= 8; treeBranches <<= 1) {
  23. for(var useNegativeNumbersIndex = 0; useNegativeNumbersIndex < bools.length; ++useNegativeNumbersIndex) {
  24. var useNegativeNumbers = bools[useNegativeNumbersIndex];
  25. echo("generateAndRun(" + treeDepth + ", " + treeBranches + ", " + useNegativeNumbers + ");");
  26. generateAndRun(treeDepth, treeBranches, useNegativeNumbers);
  27. }
  28. }
  29. }
  30. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  31. // Test helpers
  32. function generateAndRun(treeDepth, treeBranches, useNegativeNumbers) {
  33. var low_i32 = -0x80000001;
  34. var high_i32 = 0x7fffffff;
  35. var ui32 = 0xffffffff;
  36. var f = "";
  37. f += echos("(function test() {", 1);
  38. {
  39. f += echos("echo(inner(" + toHex(useNegativeNumbers ? low_i32 : high_i32) + "));");
  40. f += echos("function inner(a) {", 1);
  41. {
  42. f += echos("a |= 0;");
  43. f += echos("var r = 0;");
  44. buildTree(treeDepth, treeBranches).traverse(function visit(node) {
  45. nonwideningOperation = (nonwideningOperation + 1) % NonwideningOperation.Count;
  46. var nodeName = varName(node.number);
  47. var dst =
  48. nonwideningOperation === NonwideningOperation.None || nonwideningOperation === NonwideningOperation.ConvNum
  49. ? nodeName
  50. : tempName(node.number);
  51. var parentNodeName = node.parent ? varName(node.parent.number) : "a";
  52. if(nonwideningOperation === NonwideningOperation.Neg)
  53. parentNodeName = "-" + parentNodeName;
  54. else if(nonwideningOperation === NonwideningOperation.ConvNum)
  55. parentNodeName = "+" + parentNodeName;
  56. var right =
  57. node.parent && nonwideningOperation !== NonwideningOperation.Neg && (node.number & 3) === 0
  58. ? useNegativeNumbers ? low_i32 : ui32
  59. : parentNodeName;
  60. f += echos("var " + dst + " = " + parentNodeName + " + " + right + " + 1;");
  61. if(nonwideningOperation === NonwideningOperation.Neg)
  62. f += echos("var " + nodeName + " = -" + dst + ";");
  63. else if(nonwideningOperation === NonwideningOperation.Ld)
  64. f += echos("var " + nodeName + " = " + dst + ";");
  65. if(node.left || node.right)
  66. return;
  67. f += echos("r ^= " + nodeName + ";");
  68. });
  69. f += echos("return r;");
  70. }
  71. f += echos("}", -1);
  72. }
  73. f += echos("});", -1);
  74. f = f.substring(0, f.length - 1);
  75. echo(f);
  76. f = eval(f);
  77. f();
  78. echo();
  79. function buildTree(depth, branches, numberContainer, parent) {
  80. function TreeNode(number, parent) {
  81. this.number = number;
  82. this.parent = parent ? parent : null;
  83. this.left = null;
  84. this.right = null;
  85. }
  86. TreeNode.prototype.traverse = function (visit) {
  87. visit(this);
  88. if(this.left)
  89. this.left.traverse(visit);
  90. if(this.right)
  91. this.right.traverse(visit);
  92. };
  93. if(depth <= 0)
  94. throw new Error("Invalid tree depth");
  95. if(branches <= 0)
  96. throw new Error("Invalid number of branches");
  97. if((branches & branches - 1) !== 0)
  98. throw new Error("Number of branches must be a power of 2");
  99. if(!numberContainer)
  100. numberContainer = [0];
  101. else if(numberContainer[0] < 0)
  102. throw new Error("Invalid node number");
  103. var node = new TreeNode(numberContainer[0]++, parent);
  104. if(--depth !== 0) {
  105. var branch = branches !== 1;
  106. if(branch)
  107. branches >>= 1;
  108. node.left = buildTree(depth, branches, numberContainer, node);
  109. if(branch)
  110. node.right = buildTree(depth, branches, numberContainer, node);
  111. }
  112. return node;
  113. }
  114. function varName(number) {
  115. return "v" + number;
  116. }
  117. function tempName(number) {
  118. return "t" + number;
  119. }
  120. }
  121. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  122. function toHex(n) {
  123. if(typeof n !== "number")
  124. return n;
  125. return n >= 0 ? "0x" + n.toString(16) : "-0x" + (-n).toString(16);
  126. }
  127. function echos(s, changeIndent) {
  128. if(changeIndent && changeIndent < 0)
  129. indent += changeIndent * 4;
  130. if(s && s !== "") {
  131. var spaces = "";
  132. for(var i = 0; i < indent; ++i)
  133. spaces += " ";
  134. s = spaces + s + "\n";
  135. }
  136. else if(s === "")
  137. s = "\n";
  138. else
  139. s = "";
  140. if(changeIndent && changeIndent > 0)
  141. indent += changeIndent * 4;
  142. return s;
  143. }
  144. function echo() {
  145. var doEcho;
  146. if(this.WScript)
  147. doEcho = function (s) { this.WScript.Echo(s); };
  148. else if(this.document)
  149. doEcho = function (s) {
  150. var div = this.document.createElement("div");
  151. div.innerText = s;
  152. this.document.body.appendChild(div);
  153. };
  154. else
  155. doEcho = function (s) { this.print(s); };
  156. echo = function () {
  157. var s = "";
  158. for(var i = 0; i < arguments.length; ++i)
  159. s += arguments[i];
  160. doEcho(s);
  161. };
  162. echo.apply(this, arguments);
  163. }