binarySearchBounds.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Mikola Lysenko @mikolalysenko
  4. */
  5. "use strict";
  6. /* cspell:disable-next-line */
  7. // Refactor: Peter Somogyvari @petermetz
  8. const compileSearch = (funcName, predicate, reversed, extraArgs, earlyOut) => {
  9. const code = [
  10. "function ",
  11. funcName,
  12. "(a,l,h,",
  13. extraArgs.join(","),
  14. "){",
  15. earlyOut ? "" : "var i=",
  16. reversed ? "l-1" : "h+1",
  17. ";while(l<=h){var m=(l+h)>>>1,x=a[m]"
  18. ];
  19. if (earlyOut) {
  20. if (predicate.indexOf("c") < 0) {
  21. code.push(";if(x===y){return m}else if(x<=y){");
  22. } else {
  23. code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){");
  24. }
  25. } else {
  26. code.push(";if(", predicate, "){i=m;");
  27. }
  28. if (reversed) {
  29. code.push("l=m+1}else{h=m-1}");
  30. } else {
  31. code.push("h=m-1}else{l=m+1}");
  32. }
  33. code.push("}");
  34. if (earlyOut) {
  35. code.push("return -1};");
  36. } else {
  37. code.push("return i};");
  38. }
  39. return code.join("");
  40. };
  41. const compileBoundsSearch = (predicate, reversed, suffix, earlyOut) => {
  42. const arg1 = compileSearch(
  43. "A",
  44. "x" + predicate + "y",
  45. reversed,
  46. ["y"],
  47. earlyOut
  48. );
  49. const arg2 = compileSearch(
  50. "P",
  51. "c(x,y)" + predicate + "0",
  52. reversed,
  53. ["y", "c"],
  54. earlyOut
  55. );
  56. const fnHeader = "function dispatchBinarySearch";
  57. const fnBody =
  58. "(a,y,c,l,h){\
  59. if(typeof(c)==='function'){\
  60. return P(a,(l===void 0)?0:l|0,(h===void 0)?a.length-1:h|0,y,c)\
  61. }else{\
  62. return A(a,(c===void 0)?0:c|0,(l===void 0)?a.length-1:l|0,y)\
  63. }}\
  64. return dispatchBinarySearch";
  65. const fnArgList = [arg1, arg2, fnHeader, suffix, fnBody, suffix];
  66. const fnSource = fnArgList.join("");
  67. const result = new Function(fnSource);
  68. return result();
  69. };
  70. module.exports = {
  71. ge: compileBoundsSearch(">=", false, "GE"),
  72. gt: compileBoundsSearch(">", false, "GT"),
  73. lt: compileBoundsSearch("<", true, "LT"),
  74. le: compileBoundsSearch("<=", true, "LE"),
  75. eq: compileBoundsSearch("-", true, "EQ", true)
  76. };