whole_func_string: function getControlPoints(p0, p1, p2, opt_alpha, opt_allowFalseExtrema) {
    var alpha = (opt_alpha !== undefined) ? opt_alpha : 1/3;  // 0=no smoothing, 1=crazy smoothing
    var allowFalseExtrema = opt_allowFalseExtrema || false;
  
    if (!p2) {
      return [p1.x, p1.y, null, null];
    }
  
    // Step 1: Position the control points along each line segment.
    var l1x = (1 - alpha) * p1.x + alpha * p0.x,
        l1y = (1 - alpha) * p1.y + alpha * p0.y,
        r1x = (1 - alpha) * p1.x + alpha * p2.x,
        r1y = (1 - alpha) * p1.y + alpha * p2.y;
  
    // Step 2: shift the points up so that p1 is on the l1–r1 line.
    if (l1x != r1x) {
      // This can be derived w/ some basic algebra.
      var deltaY = p1.y - r1y - (p1.x - r1x) * (l1y - r1y) / (l1x - r1x);
      l1y += deltaY;
      r1y += deltaY;
    }
  
    // Step 3: correct to avoid false extrema.
    if (!allowFalseExtrema) {
      if (l1y > p0.y && l1y > p1.y) {
        l1y = Math.max(p0.y, p1.y);
        r1y = 2 * p1.y - l1y;
      } else if (l1y < p0.y && l1y < p1.y) {
        l1y = Math.min(p0.y, p1.y);
        r1y = 2 * p1.y - l1y;
      }
  
      if (r1y > p1.y && r1y > p2.y) {
        r1y = Math.max(p1.y, p2.y);
        l1y = 2 * p1.y - r1y;
      } else if (r1y < p1.y && r1y < p2.y) {
        r1y = Math.min(p1.y, p2.y);
        l1y = 2 * p1.y - r1y;
      }
    }
  
    return [l1x, l1y, r1x, r1y];
  }
func_code_string: function getControlPoints(p0, p1, p2, opt_alpha, opt_allowFalseExtrema) {
    var alpha = (opt_alpha !== undefined) ? opt_alpha : 1/3;  // 0=no smoothing, 1=crazy smoothing
    var allowFalseExtrema = opt_allowFalseExtrema || false;
  
    if (!p2) {
      return [p1.x, p1.y, null, null];
    }
  
    // Step 1: Position the control points along each line segment.
    var l1x = (1 - alpha) * p1.x + alpha * p0.x,
        l1y = (1 - alpha) * p1.y + alpha * p0.y,
        r1x = (1 - alpha) * p1.x + alpha * p2.x,
        r1y = (1 - alpha) * p1.y + alpha * p2.y;
  
    // Step 2: shift the points up so that p1 is on the l1–r1 line.
    if (l1x != r1x) {
      // This can be derived w/ some basic algebra.
      var deltaY = p1.y - r1y - (p1.x - r1x) * (l1y - r1y) / (l1x - r1x);
      l1y += deltaY;
      r1y += deltaY;
    }
  
    // Step 3: correct to avoid false extrema.
    if (!allowFalseExtrema) {
      if (l1y > p0.y && l1y > p1.y) {
        l1y = Math.max(p0.y, p1.y);
        r1y = 2 * p1.y - l1y;
      } else if (l1y < p0.y && l1y < p1.y) {
        l1y = Math.min(p0.y, p1.y);
        r1y = 2 * p1.y - l1y;
      }
  
      if (r1y > p1.y && r1y > p2.y) {
        r1y = Math.max(p1.y, p2.y);
        l1y = 2 * p1.y - r1y;
      } else if (r1y < p1.y && r1y < p2.y) {
        r1y = Math.min(p1.y, p2.y);
        l1y = 2 * p1.y - r1y;
      }
    }
  
    return [l1x, l1y, r1x, r1y];
  }
func_documentation_string: Given three sequential points, p0, p1 and p2, find the left and right
  control points for p1.
  
  The three points are expected to have x and y properties.
  
  The alpha parameter controls the amount of smoothing.
  If α=0, then both control points will be the same as p1 (i.e. no smoothing).
  
  Returns [l1x, l1y, r1x, r1y]
  
  It's guaranteed that the line from (l1x, l1y)-(r1x, r1y) passes through p1.
  Unless allowFalseExtrema is set, then it's also guaranteed that:
  l1y ∈ [p0.y, p1.y]
  r1y ∈ [p1.y, p2.y]
  
  The basic algorithm is:
  1. Put the control points l1 and r1 α of the way down (p0, p1) and (p1, p2).
  2. Shift l1 and r2 so that the line l1–r1 passes through p1
  3. Adjust to prevent false extrema while keeping p1 on the l1–r1 line.
  
  This is loosely based on the HighCharts algorithm.