/js/src/jit-test/tests/basic/createMandelSet.js

https://github.com/wisec/DOMinator · JavaScript · 242 lines · 199 code · 22 blank · 21 comment · 29 complexity · 431fe0887481ebbe576e77bddeadb6c7 MD5 · raw file

  1. // |jit-test| slow;
  2. // XXXbz I would dearly like to wrap it up into a function to avoid polluting
  3. // the global scope, but the function ends up heavyweight, and then we lose on
  4. // the jit.
  5. load(libdir + "mandelbrot-results.js");
  6. //function testMandelbrotAll() {
  7. // Configuration options that affect which codepaths we follow.
  8. var doImageData = true;
  9. var avoidSparseArray = true;
  10. // Control of iteration numbers and sizing. We'll do
  11. // scaler * colorNames.length iterations or so before deciding that we
  12. // don't escape.
  13. const scaler = 5;
  14. const numRows = 600;
  15. const numCols = 600;
  16. const colorNames = [
  17. "black",
  18. "green",
  19. "blue",
  20. "red",
  21. "purple",
  22. "orange",
  23. "cyan",
  24. "yellow",
  25. "magenta",
  26. "brown",
  27. "pink",
  28. "chartreuse",
  29. "darkorange",
  30. "crimson",
  31. "gray",
  32. "deeppink",
  33. "firebrick",
  34. "lavender",
  35. "lawngreen",
  36. "lightsalmon",
  37. "lime",
  38. "goldenrod"
  39. ];
  40. const threshold = (colorNames.length - 1) * scaler;
  41. // Now set up our colors
  42. var colors = [];
  43. // 3-part for loop (iterators buggy, we will add a separate test for them)
  44. for (var colorNameIdx = 0; colorNameIdx < colorNames.length; ++colorNameIdx) {
  45. //for (var colorNameIdx in colorNames) {
  46. colorNameIdx = parseInt(colorNameIdx);
  47. colors.push([colorNameIdx, colorNameIdx, colorNameIdx, 0]);
  48. }
  49. // Storage for our point data
  50. var points;
  51. var scratch = {};
  52. var scratchZ = {};
  53. function complexMult(a, b) {
  54. var newr = a.r * b.r - a.i * b.i;
  55. var newi = a.r * b.i + a.i * b.r;
  56. scratch.r = newr;
  57. scratch.i = newi;
  58. return scratch;
  59. }
  60. function complexAdd(a, b) {
  61. scratch.r = a.r + b.r;
  62. scratch.i = a.i + b.i;
  63. return scratch;
  64. }
  65. function abs(a) {
  66. return Math.sqrt(a.r * a.r + a.i * a.i);
  67. }
  68. function escapeAbsDiff(normZ, absC) {
  69. var absZ = Math.sqrt(normZ);
  70. return normZ > absZ + absC;
  71. }
  72. function escapeNorm2(normZ) {
  73. return normZ > 4;
  74. }
  75. function fuzzyColors(i) {
  76. return Math.floor(i / scaler) + 1;
  77. }
  78. function moddedColors(i) {
  79. return (i % (colorNames.length - 1)) + 1;
  80. }
  81. function computeEscapeSpeedObjects(real, imag) {
  82. var c = { r: real, i: imag }
  83. scratchZ.r = scratchZ.i = 0;
  84. var absC = abs(c);
  85. for (var i = 0; i < threshold; ++i) {
  86. scratchZ = complexAdd(c, complexMult(scratchZ, scratchZ));
  87. if (escape(scratchZ.r * scratchZ.r + scratchZ.i * scratchZ.i,
  88. absC)) {
  89. return colorMap(i);
  90. }
  91. }
  92. return 0;
  93. }
  94. function computeEscapeSpeedOneObject(real, imag) {
  95. // fold in the fact that we start with 0
  96. var r = real;
  97. var i = imag;
  98. var absC = abs({r: real, i: imag});
  99. for (var j = 0; j < threshold; ++j) {
  100. var r2 = r * r;
  101. var i2 = i * i;
  102. if (escape(r2 + i2, absC)) {
  103. return colorMap(j);
  104. }
  105. i = 2 * r * i + imag;
  106. r = r2 - i2 + real;
  107. }
  108. return 0;
  109. }
  110. function computeEscapeSpeedDoubles(real, imag) {
  111. // fold in the fact that we start with 0
  112. var r = real;
  113. var i = imag;
  114. var absC = Math.sqrt(real * real + imag * imag);
  115. for (var j = 0; j < threshold; ++j) {
  116. var r2 = r * r;
  117. var i2 = i * i;
  118. if (escape(r2 + i2, absC)) {
  119. return colorMap(j);
  120. }
  121. i = 2 * r * i + imag;
  122. r = r2 - i2 + real;
  123. }
  124. return 0;
  125. }
  126. var computeEscapeSpeed = computeEscapeSpeedDoubles;
  127. var escape = escapeNorm2;
  128. var colorMap = fuzzyColors;
  129. function addPointOrig(pointArray, n, i, j) {
  130. if (!points[n]) {
  131. points[n] = [];
  132. points[n].push([i, j, 1, 1]);
  133. } else {
  134. var point = points[n][points[n].length-1];
  135. if (point[0] == i && point[1] == j - point[3]) {
  136. ++point[3];
  137. } else {
  138. points[n].push([i, j, 1, 1]);
  139. }
  140. }
  141. }
  142. function addPointImagedata(pointArray, n, col, row) {
  143. var slotIdx = ((row * numCols) + col) * 4;
  144. pointArray[slotIdx] = colors[n][0];
  145. pointArray[slotIdx+1] = colors[n][1];
  146. pointArray[slotIdx+2] = colors[n][2];
  147. pointArray[slotIdx+3] = colors[n][3];
  148. }
  149. function createMandelSet() {
  150. var realRange = { min: -2.1, max: 1 };
  151. var imagRange = { min: -1.5, max: 1.5 };
  152. var addPoint;
  153. if (doImageData) {
  154. addPoint = addPointImagedata;
  155. points = new Array(4*numCols*numRows);
  156. if (avoidSparseArray) {
  157. for (var idx = 0; idx < 4*numCols*numRows; ++idx) {
  158. points[idx] = 0;
  159. }
  160. }
  161. } else {
  162. addPoint = addPointOrig;
  163. points = [];
  164. }
  165. var realStep = (realRange.max - realRange.min)/numCols;
  166. var imagStep = (imagRange.min - imagRange.max)/numRows;
  167. for (var i = 0, curReal = realRange.min;
  168. i < numCols;
  169. ++i, curReal += realStep) {
  170. for (var j = 0, curImag = imagRange.max;
  171. j < numRows;
  172. ++j, curImag += imagStep) {
  173. var n = computeEscapeSpeed(curReal, curImag);
  174. addPoint(points, n, i, j)
  175. }
  176. }
  177. var result;
  178. if (doImageData) {
  179. if (colorMap == fuzzyColors) {
  180. result = mandelbrotImageDataFuzzyResult;
  181. } else {
  182. result = mandelbrotImageDataModdedResult;
  183. }
  184. } else {
  185. result = mandelbrotNoImageDataResult;
  186. }
  187. return points.toSource() == result;
  188. }
  189. const escapeTests = [ escapeAbsDiff ];
  190. const colorMaps = [ fuzzyColors, moddedColors ];
  191. const escapeComputations = [ computeEscapeSpeedObjects,
  192. computeEscapeSpeedOneObject,
  193. computeEscapeSpeedDoubles ];
  194. // Test all possible escape-speed generation codepaths, using the
  195. // imageData + sparse array avoidance storage.
  196. doImageData = true;
  197. avoidSparseArray = true;
  198. for (var escapeIdx in escapeTests) {
  199. escape = escapeTests[escapeIdx];
  200. for (var colorMapIdx in colorMaps) {
  201. colorMap = colorMaps[colorMapIdx];
  202. for (var escapeComputationIdx in escapeComputations) {
  203. computeEscapeSpeed = escapeComputations[escapeComputationIdx];
  204. assertEq(createMandelSet(), true);
  205. }
  206. }
  207. }
  208. // Test all possible storage strategies. Note that we already tested
  209. // doImageData == true with avoidSparseArray == true.
  210. escape = escapeAbsDiff;
  211. colorMap = fuzzyColors; // This part doesn't really matter too much here
  212. computeEscapeSpeed = computeEscapeSpeedDoubles;
  213. doImageData = true;
  214. avoidSparseArray = false;
  215. assertEq(createMandelSet(), true);
  216. escape = escapeNorm2;
  217. doImageData = false; // avoidSparseArray doesn't matter here
  218. assertEq(createMandelSet(), true);
  219. //}
  220. //testMandelbrotAll();