docs: function generateBezier (mX1, mY1, mX2, mY2) {
          var NEWTON_ITERATIONS = 4,
              NEWTON_MIN_SLOPE = 0.001,
              SUBDIVISION_PRECISION = 0.0000001,
              SUBDIVISION_MAX_ITERATIONS = 10,
              kSplineTableSize = 11,
              kSampleStepSize = 1.0 / (kSplineTableSize - 1.0),
              float32ArraySupported = "Float32Array" in window;
  
          /* Must contain four arguments. */
          if (arguments.length !== 4) {
              return false;
          }
  
          /* Arguments must be numbers. */
          for (var i = 0; i < 4; ++i) {
              if (typeof arguments[i] !== "number" || isNaN(arguments[i]) || !isFinite(arguments[i])) {
                  return false;
              }
          }
  
          /* X values must be in the [0, 1] range. */
          mX1 = Math.min(mX1, 1);
          mX2 = Math.min(mX2, 1);
          mX1 = Math.max(mX1, 0);
          mX2 = Math.max(mX2, 0);
  
          var mSampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);
  
          function A (aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }
          function B (aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }
          function C (aA1)      { return 3.0 * aA1; }
  
          function calcBezier (aT, aA1, aA2) {
              return ((A(aA1, aA2)*aT + B(aA1, aA2))*aT + C(aA1))*aT;
          }
  
          function getSlope (aT, aA1, aA2) {
              return 3.0 * A(aA1, aA2)*aT*aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
          }
  
          function newtonRaphsonIterate (aX, aGuessT) {
              for (var i = 0; i < NEWTON_ITERATIONS; ++i) {
                  var currentSlope = getSlope(aGuessT, mX1, mX2);
  
                  if (currentSlope === 0.0) return aGuessT;
  
                  var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
                  aGuessT -= currentX / currentSlope;
              }
  
              return aGuessT;
          }
  
          function calcSampleValues () {
              for (var i = 0; i < kSplineTableSize; ++i) {
                  mSampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
              }
          }
  
          function binarySubdivide (aX, aA, aB) {
              var currentX, currentT, i = 0;
  
              do {
                  currentT = aA + (aB - aA) / 2.0;
                  currentX = calcBezier(currentT, mX1, mX2) - aX;
                  if (currentX > 0.0) {
                    aB = currentT;
                  } else {
                    aA = currentT;
                  }
              } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
  
              return currentT;
          }
  
          function getTForX (aX) {
              var intervalStart = 0.0,
                  currentSample = 1,
                  lastSample = kSplineTableSize - 1;
  
              for (; currentSample != lastSample && mSampleValues[currentSample] <= aX; ++currentSample) {
                  intervalStart += kSampleStepSize;
              }
  
              --currentSample;
  
              var dist = (aX - mSampleValues[currentSample]) / (mSampleValues[currentSample+1] - mSampleValues[currentSample]),
                  guessForT = intervalStart + dist * kSampleStepSize,
                  initialSlope = getSlope(guessForT, mX1, mX2);
  
              if (initialSlope >= NEWTON_MIN_SLOPE) {
                  return newtonRaphsonIterate(aX, guessForT);
              } else if (initialSlope == 0.0) {
                  return guessForT;
              } else {
                  return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize);
              }
          }
  
          var _precomputed = false;
  
          function precompute() {
              _precomputed = true;
              if (mX1 != mY1 || mX2 != mY2) calcSampleValues();
          }
  
          var f = function (aX) {
              if (!_precomputed) precompute();
              if (mX1 === mY1 && mX2 === mY2) return aX;
              if (aX === 0) return 0;
              if (aX === 1) return 1;
  
              return calcBezier(getTForX(aX), mY1, mY2);
          };
  
          f.getControlPoints = function() { return [{ x: mX1, y: mY1 }, { x: mX2, y: mY2 }]; };
  
          var str = "generateBezier(" + [mX1, mY1, mX2, mY2] + ")";
          f.toString = function () { return str; };
  
          return f;
      }