/**
  * Return gradient term of quadratic. This instance will be in the vector space of the
  * perturbModel, if provided. Otherwise, uses an instance of the referenceModel.
  *
  * @return Value of <code> b = -F' N [data - f(m)] + Mm  </code> if dampOnlyPerturbation is false,
  *     and <code> b = -F' N [data - f(m)] </code> if dampOnlyPerturbation is true.
  */
 public Vect getB() {
   Vect data = VectUtil.cloneZero(_data); // data is data with zeros
   _transform.forwardNonlinear(data, _referenceModel); // data is f(m)
   data.add(1., -1., _data); // data is -e = -(d - f(m))
   _transform.adjustRobustErrors(data); // (remove outliers from e)
   data.multiplyInverseCovariance(); // data is -Ne
   Vect b = null;
   if (_dampOnlyPerturbation) {
     if (_perturbModel != null) {
       b = VectUtil.cloneZero(_perturbModel); // b is 0
     } else {
       b = VectUtil.cloneZero(_referenceModel); // b is 0
     }
   } else {
     if (_perturbModel != null) {
       b = _perturbModel.clone();
       b.project(0., 1., _referenceModel); // b is m
     } else {
       b = _referenceModel.clone(); // b is m
     }
     b.multiplyInverseCovariance(); // b is M m
   }
   _transform.addTranspose(data, b, _referenceModel); // b is -F'Ne [+ Mm]
   data.dispose();
   return b;
 }
  /**
   * Evaluate the full objective function without approximation. Provide a model in the vector space
   * of the referenceModel. perturbModel is unused. Useful for line-search of best scale factor. If
   * dampedPerturbation, evaluates
   *
   * <pre>
   * [f(m)-data]'N[f(m)-data] + (m-m0)'M(m-m0)
   * </pre>
   *
   * where m0 is the reference model. Otherwise evaluates
   *
   * <pre>
   * [f(m)-data]'N[f(m)-data] + m'M m
   * </pre>
   *
   * @param m Model to be evaluated.
   * @return Value of objective function.
   */
  public double evalFullObjectiveFunction(VectConst m) {

    Vect data = VectUtil.cloneZero(_data); // data is zeros

    Vect model = m.clone(); // model is m
    model.constrain(); // may have been done already

    _transform.forwardNonlinear(data, model); // data is f(m)
    data.add(1., -1., _data); // data is e = f(m) - data
    _transform.adjustRobustErrors(data);
    double eNe = data.magnitude(); // eNe is e'Ne
    checkNaN(eNe);
    data.dispose();

    // damp perturbation if requested
    if (_dampOnlyPerturbation) {
      model.add(1., -1., _referenceModel); // model is (m-m0)
    }

    double mMm = model.magnitude(); // mMm is (m-m0)'M(m-m0)
    checkNaN(mMm);
    model.dispose();
    return (eNe + mMm);
  }