private void quadraticBacktrack(
     final DoubleMatrix1D p,
     final Function1D<DoubleMatrix1D, Double> function,
     final DataBundle data) {
   final double lambda0 = data.getLambda0();
   final double g0 = data.getG0();
   final double lambda =
       Math.max(0.01 * lambda0, g0 * lambda0 * lambda0 / (data.getG1() + g0 * (2 * lambda0 - 1)));
   data.swapLambdaAndReplace(lambda);
   updatePosition(p, function, data);
 }
 private void cubicBacktrack(
     final DoubleMatrix1D p,
     final Function1D<DoubleMatrix1D, Double> function,
     final DataBundle data) {
   double temp1, temp2, temp3, temp4, temp5;
   final double lambda0 = data.getLambda0();
   final double lambda1 = data.getLambda1();
   final double g0 = data.getG0();
   temp1 = 1.0 / lambda0 / lambda0;
   temp2 = 1.0 / lambda1 / lambda1;
   temp3 = data.getG1() + g0 * (2 * lambda0 - 1.0);
   temp4 = data.getG2() + g0 * (2 * lambda1 - 1.0);
   temp5 = 1.0 / (lambda0 - lambda1);
   final double a = temp5 * (temp1 * temp3 - temp2 * temp4);
   final double b = temp5 * (-lambda1 * temp1 * temp3 + lambda0 * temp2 * temp4);
   double lambda = (-b + Math.sqrt(b * b + 6 * a * g0)) / 3 / a;
   lambda =
       Math.min(
           Math.max(lambda, 0.01 * lambda0),
           0.75 * lambda1); // make sure new lambda is between 1% & 75% of old value
   data.swapLambdaAndReplace(lambda);
   updatePosition(p, function, data);
 }