code: private double[] lineSearchBacktrack(Function func, double[] dir, double[] x,
        double[] newX, double[] grad, double lastValue)
        throws MaxEvaluationsExceeded {
  
      double normGradInDir = ArrayMath.innerProduct(dir, grad);
      say("(" + nf.format(normGradInDir) + ")");
      if (normGradInDir > 0) {
        say("{WARNING--- direction of positive gradient chosen!}");
      }
  
      // c1 can be anything between 0 and 1, exclusive (usu. 1/10 - 1/2)
      double step, c1;
  
      // for first few steps, we have less confidence in our initial step-size a
      // so scale back quicker
      if (its <= 2) {
        step = 0.1;
        c1 = 0.1;
      } else {
        step = 1.0;
        c1 = 0.1;
      }
  
      // should be small e.g. 10^-5 ... 10^-1
      double c = 0.01;
  
      // double v = func.valueAt(x);
      // c = c * mult(grad, dir);
      c = c * normGradInDir;
  
      double[] newPoint = new double[3];
  
      while ((newPoint[f] = func.valueAt((plusAndConstMult(x, dir, step, newX)))) > lastValue
          + c * step) {
        fevals += 1;
        if (newPoint[f] < lastValue) {
          // an improvement, but not good enough... suspicious!
          say("!");
        } else {
          say(".");
        }
        step = c1 * step;
      }
  
      newPoint[a] = step;
      fevals += 1;
      if (fevals > maxFevals) {
        throw new MaxEvaluationsExceeded(
            " Exceeded during linesearch() Function ");
      }
  
      return newPoint;
    }
docs: /*
  lineSearchBacktrack is the original linesearch used for the first version
  of QNMinimizer. it only satisfies sufficient descent not the Wolfe
  conditions.