class TimeSquareInterpolator1D extends Interpolator1D {

  @Override
  public double firstDerivative(final Interpolator1DDataBundle data, final Double value) {
    ArgumentChecker.notNull(value, "Value to be interpolated must not be null");
    ArgumentChecker.isTrue(value > 0, "Value should be stricly positive");
    ArgumentChecker.notNull(data, "Data bundle must not be null");
    int lowerIndex = data.getLowerBoundIndex(value);
    int index;
    if (lowerIndex == data.size() - 1) {
      index = data.size() - 2;
    } else {
      index = lowerIndex;
    }
    double x1 = data.getKeys()[index];
    double y1 = data.getValues()[index];
    double x2 = data.getKeys()[index + 1];
    double y2 = data.getValues()[index + 1];
    if ((y1 < EPS) || (y2 < EPS)) {
      throw new NotImplementedException("node sensitivity not implemented when one node is 0 value");
    }
    final double w = (x2 - value) / (x2 - x1);
    final double xy21 = x1 * y1 * y1;
    final double xy22 = x2 * y2 * y2;
    final double xy2 = w * xy21 + (1 - w) * xy22;
    return 0.5 * (-Math.sqrt(xy2 / value) + (-xy21 + xy22) / (x2 - x1) / Math.sqrt(xy2 / value)) / value;
  }

}