SymmLQ.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.linear;

  22. import org.hipparchus.exception.LocalizedCoreFormats;
  23. import org.hipparchus.exception.MathIllegalArgumentException;
  24. import org.hipparchus.exception.MathIllegalStateException;
  25. import org.hipparchus.exception.NullArgumentException;
  26. import org.hipparchus.util.FastMath;
  27. import org.hipparchus.util.IterationManager;
  28. import org.hipparchus.util.MathUtils;

  29. /**
  30.  * <p>
  31.  * Implementation of the SYMMLQ iterative linear solver proposed by <a
  32.  * href="#PAIG1975">Paige and Saunders (1975)</a>. This implementation is
  33.  * largely based on the FORTRAN code by Pr. Michael A. Saunders, available <a
  34.  * href="http://www.stanford.edu/group/SOL/software/symmlq/f77/">here</a>.
  35.  * </p>
  36.  * <p>
  37.  * SYMMLQ is designed to solve the system of linear equations A &middot; x = b
  38.  * where A is an n &times; n self-adjoint linear operator (defined as a
  39.  * {@link RealLinearOperator}), and b is a given vector. The operator A is not
  40.  * required to be positive definite. If A is known to be definite, the method of
  41.  * conjugate gradients might be preferred, since it will require about the same
  42.  * number of iterations as SYMMLQ but slightly less work per iteration.
  43.  * </p>
  44.  * <p>
  45.  * SYMMLQ is designed to solve the system (A - shift &middot; I) &middot; x = b,
  46.  * where shift is a specified scalar value. If shift and b are suitably chosen,
  47.  * the computed vector x may approximate an (unnormalized) eigenvector of A, as
  48.  * in the methods of inverse iteration and/or Rayleigh-quotient iteration.
  49.  * Again, the linear operator (A - shift &middot; I) need not be positive
  50.  * definite (but <em>must</em> be self-adjoint). The work per iteration is very
  51.  * slightly less if shift = 0.
  52.  * </p>
  53.  * <p><strong>Preconditioning</strong></p>
  54.  * <p>
  55.  * Preconditioning may reduce the number of iterations required. The solver may
  56.  * be provided with a positive definite preconditioner
  57.  * M = P<sup>T</sup> &middot; P
  58.  * that is known to approximate
  59.  * (A - shift &middot; I)<sup>-1</sup> in some sense, where matrix-vector
  60.  * products of the form M &middot; y = x can be computed efficiently. Then
  61.  * SYMMLQ will implicitly solve the system of equations
  62.  * P &middot; (A - shift &middot; I) &middot; P<sup>T</sup> &middot;
  63.  * x<sub>hat</sub> = P &middot; b, i.e.
  64.  * A<sub>hat</sub> &middot; x<sub>hat</sub> = b<sub>hat</sub>,
  65.  * where
  66.  * A<sub>hat</sub> = P &middot; (A - shift &middot; I) &middot; P<sup>T</sup>,
  67.  * b<sub>hat</sub> = P &middot; b,
  68.  * and return the solution
  69.  * x = P<sup>T</sup> &middot; x<sub>hat</sub>.
  70.  * The associated residual is
  71.  * r<sub>hat</sub> = b<sub>hat</sub> - A<sub>hat</sub> &middot; x<sub>hat</sub>
  72.  *                 = P &middot; [b - (A - shift &middot; I) &middot; x]
  73.  *                 = P &middot; r.
  74.  * </p>
  75.  * <p>
  76.  * In the case of preconditioning, the {@link IterativeLinearSolverEvent}s that
  77.  * this solver fires are such that
  78.  * {@link IterativeLinearSolverEvent#getNormOfResidual()} returns the norm of
  79.  * the <em>preconditioned</em>, updated residual, ||P &middot; r||, not the norm
  80.  * of the <em>true</em> residual ||r||.
  81.  * </p>
  82.  * <p><strong>Default stopping criterion</strong></p>
  83.  * <p>
  84.  * A default stopping criterion is implemented. The iterations stop when || rhat
  85.  * || &le; &delta; || Ahat || || xhat ||, where xhat is the current estimate of
  86.  * the solution of the transformed system, rhat the current estimate of the
  87.  * corresponding residual, and &delta; a user-specified tolerance.
  88.  * </p>
  89.  * <strong>Iteration count</strong>
  90.  * <p>
  91.  * In the present context, an iteration should be understood as one evaluation
  92.  * of the matrix-vector product A &middot; x. The initialization phase therefore
  93.  * counts as one iteration. If the user requires checks on the symmetry of A,
  94.  * this entails one further matrix-vector product in the initial phase. This
  95.  * further product is <em>not</em> accounted for in the iteration count. In
  96.  * other words, the number of iterations required to reach convergence will be
  97.  * identical, whether checks have been required or not.
  98.  * </p>
  99.  * <p>
  100.  * The present definition of the iteration count differs from that adopted in
  101.  * the original FOTRAN code, where the initialization phase was <em>not</em>
  102.  * taken into account.
  103.  * </p>
  104.  * <strong>Initial guess of the solution</strong>
  105.  * <p>
  106.  * The {@code x} parameter in
  107.  * </p>
  108.  * <ul>
  109.  * <li>{@link #solve(RealLinearOperator, RealVector, RealVector)},</li>
  110.  * <li>{@link #solve(RealLinearOperator, RealLinearOperator, RealVector, RealVector)}},</li>
  111.  * <li>{@link #solveInPlace(RealLinearOperator, RealVector, RealVector)},</li>
  112.  * <li>{@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector)},</li>
  113.  * <li>{@link #solveInPlace(RealLinearOperator, RealLinearOperator, RealVector, RealVector, boolean, double)},</li>
  114.  * </ul>
  115.  * <p>
  116.  * should not be considered as an initial guess, as it is set to zero in the
  117.  * initial phase. If x<sub>0</sub> is known to be a good approximation to x, one
  118.  * should compute r<sub>0</sub> = b - A &middot; x, solve A &middot; dx = r0,
  119.  * and set x = x<sub>0</sub> + dx.
  120.  * </p>
  121.  * <p><strong>Exception context</strong></p>
  122.  * <p>
  123.  * Besides standard {@link MathIllegalArgumentException}, this class might throw
  124.  * {@link MathIllegalArgumentException} if the linear operator or the
  125.  * preconditioner are not symmetric.
  126.  * </p>
  127.  * <ul>
  128.  * <li>key {@code "operator"} points to the offending linear operator, say L,</li>
  129.  * <li>key {@code "vector1"} points to the first offending vector, say x,
  130.  * <li>key {@code "vector2"} points to the second offending vector, say y, such
  131.  * that x<sup>T</sup> &middot; L &middot; y &ne; y<sup>T</sup> &middot; L
  132.  * &middot; x (within a certain accuracy).</li>
  133.  * </ul>
  134.  * <p>
  135.  * {@link MathIllegalArgumentException} might also be thrown in case the
  136.  * preconditioner is not positive definite.
  137.  * </p>
  138.  * <p><strong>References</strong></p>
  139.  * <dl>
  140.  * <dt><a id="PAIG1975">Paige and Saunders (1975)</a></dt>
  141.  * <dd>C. C. Paige and M. A. Saunders, <a
  142.  * href="http://www.stanford.edu/group/SOL/software/symmlq/PS75.pdf"><em>
  143.  * Solution of Sparse Indefinite Systems of Linear Equations</em></a>, SIAM
  144.  * Journal on Numerical Analysis 12(4): 617-629, 1975</dd>
  145.  * </dl>
  146.  *
  147.  */
  148. public class SymmLQ
  149.     extends PreconditionedIterativeLinearSolver {

  150.     /** {@code true} if symmetry of matrix and conditioner must be checked. */
  151.     private final boolean check;

  152.     /**
  153.      * The value of the custom tolerance &delta; for the default stopping
  154.      * criterion.
  155.      */
  156.     private final double delta;

  157.     /*
  158.      * IMPLEMENTATION NOTES
  159.      * --------------------
  160.      * The implementation follows as closely as possible the notations of Paige
  161.      * and Saunders (1975). Attention must be paid to the fact that some
  162.      * quantities which are relevant to iteration k can only be computed in
  163.      * iteration (k+1). Therefore, minute attention must be paid to the index of
  164.      * each state variable of this algorithm.
  165.      *
  166.      * 1. Preconditioning
  167.      *    ---------------
  168.      * The Lanczos iterations associated with Ahat and bhat read
  169.      *   beta[1] = ||P * b||
  170.      *   v[1] = P * b / beta[1]
  171.      *   beta[k+1] * v[k+1] = Ahat * v[k] - alpha[k] * v[k] - beta[k] * v[k-1]
  172.      *                      = P * (A - shift * I) * P' * v[k] - alpha[k] * v[k]
  173.      *                        - beta[k] * v[k-1]
  174.      * Multiplying both sides by P', we get
  175.      *   beta[k+1] * (P' * v)[k+1] = M * (A - shift * I) * (P' * v)[k]
  176.      *                               - alpha[k] * (P' * v)[k]
  177.      *                               - beta[k] * (P' * v[k-1]),
  178.      * and
  179.      *   alpha[k+1] = v[k+1]' * Ahat * v[k+1]
  180.      *              = v[k+1]' * P * (A - shift * I) * P' * v[k+1]
  181.      *              = (P' * v)[k+1]' * (A - shift * I) * (P' * v)[k+1].
  182.      *
  183.      * In other words, the Lanczos iterations are unchanged, except for the fact
  184.      * that we really compute (P' * v) instead of v. It can easily be checked
  185.      * that all other formulas are unchanged. It must be noted that P is never
  186.      * explicitly used, only matrix-vector products involving are invoked.
  187.      *
  188.      * 2. Accounting for the shift parameter
  189.      *    ----------------------------------
  190.      * Is trivial: each time A.operate(x) is invoked, one must subtract shift * x
  191.      * to the result.
  192.      *
  193.      * 3. Accounting for the goodb flag
  194.      *    -----------------------------
  195.      * When goodb is set to true, the component of xL along b is computed
  196.      * separately. From Paige and Saunders (1975), equation (5.9), we have
  197.      *   wbar[k+1] = s[k] * wbar[k] - c[k] * v[k+1],
  198.      *   wbar[1] = v[1].
  199.      * Introducing wbar2[k] = wbar[k] - s[1] * ... * s[k-1] * v[1], it can
  200.      * easily be verified by induction that wbar2 follows the same recursive
  201.      * relation
  202.      *   wbar2[k+1] = s[k] * wbar2[k] - c[k] * v[k+1],
  203.      *   wbar2[1] = 0,
  204.      * and we then have
  205.      *   w[k] = c[k] * wbar2[k] + s[k] * v[k+1]
  206.      *          + s[1] * ... * s[k-1] * c[k] * v[1].
  207.      * Introducing w2[k] = w[k] - s[1] * ... * s[k-1] * c[k] * v[1], we find,
  208.      * from (5.10)
  209.      *   xL[k] = zeta[1] * w[1] + ... + zeta[k] * w[k]
  210.      *         = zeta[1] * w2[1] + ... + zeta[k] * w2[k]
  211.      *           + (s[1] * c[2] * zeta[2] + ...
  212.      *           + s[1] * ... * s[k-1] * c[k] * zeta[k]) * v[1]
  213.      *         = xL2[k] + bstep[k] * v[1],
  214.      * where xL2[k] is defined by
  215.      *   xL2[0] = 0,
  216.      *   xL2[k+1] = xL2[k] + zeta[k+1] * w2[k+1],
  217.      * and bstep is defined by
  218.      *   bstep[1] = 0,
  219.      *   bstep[k] = bstep[k-1] + s[1] * ... * s[k-1] * c[k] * zeta[k].
  220.      * We also have, from (5.11)
  221.      *   xC[k] = xL[k-1] + zbar[k] * wbar[k]
  222.      *         = xL2[k-1] + zbar[k] * wbar2[k]
  223.      *           + (bstep[k-1] + s[1] * ... * s[k-1] * zbar[k]) * v[1].
  224.      */

  225.     /**
  226.      * <p>
  227.      * A simple container holding the non-final variables used in the
  228.      * iterations. Making the current state of the solver visible from the
  229.      * outside is necessary, because during the iterations, {@code x} does not
  230.      * <em>exactly</em> hold the current estimate of the solution. Indeed,
  231.      * {@code x} needs in general to be moved from the LQ point to the CG point.
  232.      * Besides, additional upudates must be carried out in case {@code goodb} is
  233.      * set to {@code true}.
  234.      * </p>
  235.      * <p>
  236.      * In all subsequent comments, the description of the state variables refer
  237.      * to their value after a call to {@link #update()}. In these comments, k is
  238.      * the current number of evaluations of matrix-vector products.
  239.      * </p>
  240.      */
  241.     private static class State {
  242.         /** The cubic root of {@link #MACH_PREC}. */
  243.         static final double CBRT_MACH_PREC;

  244.         /** The machine precision. */
  245.         static final double MACH_PREC;

  246.         /** Reference to the linear operator. */
  247.         private final RealLinearOperator a;

  248.         /** Reference to the right-hand side vector. */
  249.         private final RealVector b;

  250.         /** {@code true} if symmetry of matrix and conditioner must be checked. */
  251.         private final boolean check;

  252.         /**
  253.          * The value of the custom tolerance &delta; for the default stopping
  254.          * criterion.
  255.          */
  256.         private final double delta;

  257.         /** The value of beta[k+1]. */
  258.         private double beta;

  259.         /** The value of beta[1]. */
  260.         private double beta1;

  261.         /** The value of bstep[k-1]. */
  262.         private double bstep;

  263.         /** The estimate of the norm of P * rC[k]. */
  264.         private double cgnorm;

  265.         /** The value of dbar[k+1] = -beta[k+1] * c[k-1]. */
  266.         private double dbar;

  267.         /**
  268.          * The value of gamma[k] * zeta[k]. Was called {@code rhs1} in the
  269.          * initial code.
  270.          */
  271.         private double gammaZeta;

  272.         /** The value of gbar[k]. */
  273.         private double gbar;

  274.         /** The value of max(|alpha[1]|, gamma[1], ..., gamma[k-1]). */
  275.         private double gmax;

  276.         /** The value of min(|alpha[1]|, gamma[1], ..., gamma[k-1]). */
  277.         private double gmin;

  278.         /** Copy of the {@code goodb} parameter. */
  279.         private final boolean goodb;

  280.         /** {@code true} if the default convergence criterion is verified. */
  281.         private boolean hasConverged;

  282.         /** The estimate of the norm of P * rL[k-1]. */
  283.         private double lqnorm;

  284.         /** Reference to the preconditioner, M. */
  285.         private final RealLinearOperator m;

  286.         /**
  287.          * The value of (-eps[k+1] * zeta[k-1]). Was called {@code rhs2} in the
  288.          * initial code.
  289.          */
  290.         private double minusEpsZeta;

  291.         /** The value of M * b. */
  292.         private final RealVector mb;

  293.         /** The value of beta[k]. */
  294.         private double oldb;

  295.         /** The value of beta[k] * M^(-1) * P' * v[k]. */
  296.         private RealVector r1;

  297.         /** The value of beta[k+1] * M^(-1) * P' * v[k+1]. */
  298.         private RealVector r2;

  299.         /**
  300.          * The value of the updated, preconditioned residual P * r. This value is
  301.          * given by {@code min(}{@link #cgnorm}{@code , }{@link #lqnorm}{@code )}.
  302.          */
  303.         private double rnorm;

  304.         /** Copy of the {@code shift} parameter. */
  305.         private final double shift;

  306.         /** The value of s[1] * ... * s[k-1]. */
  307.         private double snprod;

  308.         /**
  309.          * An estimate of the square of the norm of A * V[k], based on Paige and
  310.          * Saunders (1975), equation (3.3).
  311.          */
  312.         private double tnorm;

  313.         /**
  314.          * The value of P' * wbar[k] or P' * (wbar[k] - s[1] * ... * s[k-1] *
  315.          * v[1]) if {@code goodb} is {@code true}. Was called {@code w} in the
  316.          * initial code.
  317.          */
  318.         private RealVector wbar;

  319.         /**
  320.          * A reference to the vector to be updated with the solution. Contains
  321.          * the value of xL[k-1] if {@code goodb} is {@code false}, (xL[k-1] -
  322.          * bstep[k-1] * v[1]) otherwise.
  323.          */
  324.         private final RealVector xL;

  325.         /** The value of beta[k+1] * P' * v[k+1]. */
  326.         private RealVector y;

  327.         /** The value of zeta[1]^2 + ... + zeta[k-1]^2. */
  328.         private double ynorm2;

  329.         /** The value of {@code b == 0} (exact floating-point equality). */
  330.         private boolean bIsNull;

  331.         static {
  332.             MACH_PREC = FastMath.ulp(1.);
  333.             CBRT_MACH_PREC = FastMath.cbrt(MACH_PREC);
  334.         }

  335.         /**
  336.          * Creates and inits to k = 1 a new instance of this class.
  337.          *
  338.          * @param a the linear operator A of the system
  339.          * @param m the preconditioner, M (can be {@code null})
  340.          * @param b the right-hand side vector
  341.          * @param goodb usually {@code false}, except if {@code x} is expected
  342.          * to contain a large multiple of {@code b}
  343.          * @param shift the amount to be subtracted to all diagonal elements of
  344.          * A
  345.          * @param delta the &delta; parameter for the default stopping criterion
  346.          * @param check {@code true} if self-adjointedness of both matrix and
  347.          * preconditioner should be checked
  348.          */
  349.         State(final RealLinearOperator a,
  350.             final RealLinearOperator m,
  351.             final RealVector b,
  352.             final boolean goodb,
  353.             final double shift,
  354.             final double delta,
  355.             final boolean check) {
  356.             this.a = a;
  357.             this.m = m;
  358.             this.b = b;
  359.             this.xL = new ArrayRealVector(b.getDimension());
  360.             this.goodb = goodb;
  361.             this.shift = shift;
  362.             this.mb = m == null ? b : m.operate(b);
  363.             this.hasConverged = false;
  364.             this.check = check;
  365.             this.delta = delta;
  366.         }

  367.         /**
  368.          * Performs a symmetry check on the specified linear operator, and throws an
  369.          * exception in case this check fails. Given a linear operator L, and a
  370.          * vector x, this method checks that
  371.          * x' &middot; L &middot; y = y' &middot; L &middot; x
  372.          * (within a given accuracy), where y = L &middot; x.
  373.          * @param x the candidate vector x
  374.          * @param y the candidate vector y = L &middot; x
  375.          * @param z the vector z = L &middot; y
  376.          *
  377.          * @throws MathIllegalArgumentException when the test fails
  378.          */
  379.         private static void checkSymmetry(final RealVector x, final RealVector y, final RealVector z)
  380.             throws MathIllegalArgumentException {
  381.             final double s = y.dotProduct(y);
  382.             final double t = x.dotProduct(z);
  383.             final double epsa = (s + MACH_PREC) * CBRT_MACH_PREC;
  384.             if (FastMath.abs(s - t) > epsa) {
  385.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_SELF_ADJOINT_OPERATOR);
  386.             }
  387.         }

  388.         /**
  389.          * Throws a new {@link MathIllegalArgumentException} with
  390.          * appropriate context.
  391.          * @throws MathIllegalArgumentException in any circumstances
  392.          */
  393.         private static void throwNPDLOException() throws MathIllegalArgumentException {
  394.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NON_POSITIVE_DEFINITE_OPERATOR);
  395.         }

  396.         /**
  397.          * A clone of the BLAS {@code DAXPY} function, which carries out the
  398.          * operation y &larr; a &middot; x + y. This is for internal use only: no
  399.          * dimension checks are provided.
  400.          *
  401.          * @param a the scalar by which {@code x} is to be multiplied
  402.          * @param x the vector to be added to {@code y}
  403.          * @param y the vector to be incremented
  404.          */
  405.         private static void daxpy(final double a, final RealVector x,
  406.             final RealVector y) {
  407.             final int n = x.getDimension();
  408.             for (int i = 0; i < n; i++) {
  409.                 y.setEntry(i, a * x.getEntry(i) + y.getEntry(i));
  410.             }
  411.         }

  412.         /**
  413.          * A BLAS-like function, for the operation z &larr; a &middot; x + b
  414.          * &middot; y + z. This is for internal use only: no dimension checks are
  415.          * provided.
  416.          *
  417.          * @param a the scalar by which {@code x} is to be multiplied
  418.          * @param x the first vector to be added to {@code z}
  419.          * @param b the scalar by which {@code y} is to be multiplied
  420.          * @param y the second vector to be added to {@code z}
  421.          * @param z the vector to be incremented
  422.          */
  423.         private static void daxpbypz(final double a, final RealVector x,
  424.             final double b, final RealVector y, final RealVector z) {
  425.             final int n = z.getDimension();
  426.             for (int i = 0; i < n; i++) {
  427.                 final double zi;
  428.                 zi = a * x.getEntry(i) + b * y.getEntry(i) + z.getEntry(i);
  429.                 z.setEntry(i, zi);
  430.             }
  431.         }

  432.         /**
  433.          * <p>
  434.          * Move to the CG point if it seems better. In this version of SYMMLQ,
  435.          * the convergence tests involve only cgnorm, so we're unlikely to stop
  436.          * at an LQ point, except if the iteration limit interferes.
  437.          * </p>
  438.          * <p>
  439.          * Additional upudates are also carried out in case {@code goodb} is set
  440.          * to {@code true}.
  441.          * </p>
  442.          *
  443.          * @param x the vector to be updated with the refined value of xL
  444.          */
  445.          void refineSolution(final RealVector x) {
  446.             final int n = this.xL.getDimension();
  447.             if (lqnorm < cgnorm) {
  448.                 if (!goodb) {
  449.                     x.setSubVector(0, this.xL);
  450.                 } else {
  451.                     final double step = bstep / beta1;
  452.                     for (int i = 0; i < n; i++) {
  453.                         final double bi = mb.getEntry(i);
  454.                         final double xi = this.xL.getEntry(i);
  455.                         x.setEntry(i, xi + step * bi);
  456.                     }
  457.                 }
  458.             } else {
  459.                 final double anorm = FastMath.sqrt(tnorm);
  460.                 final double diag = gbar == 0. ? anorm * MACH_PREC : gbar;
  461.                 final double zbar = gammaZeta / diag;
  462.                 final double step = (bstep + snprod * zbar) / beta1;
  463.                 // ynorm = FastMath.sqrt(ynorm2 + zbar * zbar);
  464.                 if (!goodb) {
  465.                     for (int i = 0; i < n; i++) {
  466.                         final double xi = this.xL.getEntry(i);
  467.                         final double wi = wbar.getEntry(i);
  468.                         x.setEntry(i, xi + zbar * wi);
  469.                     }
  470.                 } else {
  471.                     for (int i = 0; i < n; i++) {
  472.                         final double xi = this.xL.getEntry(i);
  473.                         final double wi = wbar.getEntry(i);
  474.                         final double bi = mb.getEntry(i);
  475.                         x.setEntry(i, xi + zbar * wi + step * bi);
  476.                     }
  477.                 }
  478.             }
  479.         }

  480.         /**
  481.          * Performs the initial phase of the SYMMLQ algorithm. On return, the
  482.          * value of the state variables of {@code this} object correspond to k =
  483.          * 1.
  484.          */
  485.          void init() {
  486.             this.xL.set(0.);
  487.             /*
  488.              * Set up y for the first Lanczos vector. y and beta1 will be zero
  489.              * if b = 0.
  490.              */
  491.             this.r1 = this.b.copy();
  492.             this.y = this.m == null ? this.b.copy() : this.m.operate(this.r1);
  493.             if ((this.m != null) && this.check) {
  494.                 checkSymmetry(this.r1, this.y, this.m.operate(this.y));
  495.             }

  496.             this.beta1 = this.r1.dotProduct(this.y);
  497.             if (this.beta1 < 0.) {
  498.                 throwNPDLOException();
  499.             }
  500.             if (this.beta1 == 0.) {
  501.                 /* If b = 0 exactly, stop with x = 0. */
  502.                 this.bIsNull = true;
  503.                 return;
  504.             }
  505.             this.bIsNull = false;
  506.             this.beta1 = FastMath.sqrt(this.beta1);
  507.             /* At this point
  508.              *   r1 = b,
  509.              *   y = M * b,
  510.              *   beta1 = beta[1].
  511.              */
  512.             final RealVector v = this.y.mapMultiply(1. / this.beta1);
  513.             this.y = this.a.operate(v);
  514.             if (this.check) {
  515.                 checkSymmetry(v, this.y, this.a.operate(this.y));
  516.             }
  517.             /*
  518.              * Set up y for the second Lanczos vector. y and beta will be zero
  519.              * or very small if b is an eigenvector.
  520.              */
  521.             daxpy(-this.shift, v, this.y);
  522.             final double alpha = v.dotProduct(this.y);
  523.             daxpy(-alpha / this.beta1, this.r1, this.y);
  524.             /*
  525.              * At this point
  526.              *   alpha = alpha[1]
  527.              *   y     = beta[2] * M^(-1) * P' * v[2]
  528.              */
  529.             /* Make sure r2 will be orthogonal to the first v. */
  530.             final double vty = v.dotProduct(this.y);
  531.             final double vtv = v.dotProduct(v);
  532.             daxpy(-vty / vtv, v, this.y);
  533.             this.r2 = this.y.copy();
  534.             if (this.m != null) {
  535.                 this.y = this.m.operate(this.r2);
  536.             }
  537.             this.oldb = this.beta1;
  538.             this.beta = this.r2.dotProduct(this.y);
  539.             if (this.beta < 0.) {
  540.                 throwNPDLOException();
  541.             }
  542.             this.beta = FastMath.sqrt(this.beta);
  543.             /*
  544.              * At this point
  545.              *   oldb = beta[1]
  546.              *   beta = beta[2]
  547.              *   y  = beta[2] * P' * v[2]
  548.              *   r2 = beta[2] * M^(-1) * P' * v[2]
  549.              */
  550.             this.cgnorm = this.beta1;
  551.             this.gbar = alpha;
  552.             this.dbar = this.beta;
  553.             this.gammaZeta = this.beta1;
  554.             this.minusEpsZeta = 0.;
  555.             this.bstep = 0.;
  556.             this.snprod = 1.;
  557.             this.tnorm = alpha * alpha + this.beta * this.beta;
  558.             this.ynorm2 = 0.;
  559.             this.gmax = FastMath.abs(alpha) + MACH_PREC;
  560.             this.gmin = this.gmax;

  561.             if (this.goodb) {
  562.                 this.wbar = new ArrayRealVector(this.a.getRowDimension());
  563.                 this.wbar.set(0.);
  564.             } else {
  565.                 this.wbar = v;
  566.             }
  567.             updateNorms();
  568.         }

  569.         /**
  570.          * Performs the next iteration of the algorithm. The iteration count
  571.          * should be incremented prior to calling this method. On return, the
  572.          * value of the state variables of {@code this} object correspond to the
  573.          * current iteration count {@code k}.
  574.          */
  575.         void update() {
  576.             final RealVector v = y.mapMultiply(1. / beta);
  577.             y = a.operate(v);
  578.             daxpbypz(-shift, v, -beta / oldb, r1, y);
  579.             final double alpha = v.dotProduct(y);
  580.             /*
  581.              * At this point
  582.              *   v     = P' * v[k],
  583.              *   y     = (A - shift * I) * P' * v[k] - beta[k] * M^(-1) * P' * v[k-1],
  584.              *   alpha = v'[k] * P * (A - shift * I) * P' * v[k]
  585.              *           - beta[k] * v[k]' * P * M^(-1) * P' * v[k-1]
  586.              *         = v'[k] * P * (A - shift * I) * P' * v[k]
  587.              *           - beta[k] * v[k]' * v[k-1]
  588.              *         = alpha[k].
  589.              */
  590.             daxpy(-alpha / beta, r2, y);
  591.             /*
  592.              * At this point
  593.              *   y = (A - shift * I) * P' * v[k] - alpha[k] * M^(-1) * P' * v[k]
  594.              *       - beta[k] * M^(-1) * P' * v[k-1]
  595.              *     = M^(-1) * P' * (P * (A - shift * I) * P' * v[k] -alpha[k] * v[k]
  596.              *       - beta[k] * v[k-1])
  597.              *     = beta[k+1] * M^(-1) * P' * v[k+1],
  598.              * from Paige and Saunders (1975), equation (3.2).
  599.              *
  600.              * WATCH-IT: the two following lines work only because y is no longer
  601.              * updated up to the end of the present iteration, and is
  602.              * reinitialized at the beginning of the next iteration.
  603.              */
  604.             r1 = r2;
  605.             r2 = y;
  606.             if (m != null) {
  607.                 y = m.operate(r2);
  608.             }
  609.             oldb = beta;
  610.             beta = r2.dotProduct(y);
  611.             if (beta < 0.) {
  612.                 throwNPDLOException();
  613.             }
  614.             beta = FastMath.sqrt(beta);
  615.             /*
  616.              * At this point
  617.              *   r1 = beta[k] * M^(-1) * P' * v[k],
  618.              *   r2 = beta[k+1] * M^(-1) * P' * v[k+1],
  619.              *   y  = beta[k+1] * P' * v[k+1],
  620.              *   oldb = beta[k],
  621.              *   beta = beta[k+1].
  622.              */
  623.             tnorm += alpha * alpha + oldb * oldb + beta * beta;
  624.             /*
  625.              * Compute the next plane rotation for Q. See Paige and Saunders
  626.              * (1975), equation (5.6), with
  627.              *   gamma = gamma[k-1],
  628.              *   c     = c[k-1],
  629.              *   s     = s[k-1].
  630.              */
  631.             final double gamma = FastMath.sqrt(gbar * gbar + oldb * oldb);
  632.             final double c = gbar / gamma;
  633.             final double s = oldb / gamma;
  634.             /*
  635.              * The relations
  636.              *   gbar[k] = s[k-1] * (-c[k-2] * beta[k]) - c[k-1] * alpha[k]
  637.              *           = s[k-1] * dbar[k] - c[k-1] * alpha[k],
  638.              *   delta[k] = c[k-1] * dbar[k] + s[k-1] * alpha[k],
  639.              * are not stated in Paige and Saunders (1975), but can be retrieved
  640.              * by expanding the (k, k-1) and (k, k) coefficients of the matrix in
  641.              * equation (5.5).
  642.              */
  643.             final double deltak = c * dbar + s * alpha;
  644.             gbar = s * dbar - c * alpha;
  645.             final double eps = s * beta;
  646.             dbar = -c * beta;
  647.             final double zeta = gammaZeta / gamma;
  648.             /*
  649.              * At this point
  650.              *   gbar   = gbar[k]
  651.              *   deltak = delta[k]
  652.              *   eps    = eps[k+1]
  653.              *   dbar   = dbar[k+1]
  654.              *   zeta   = zeta[k-1]
  655.              */
  656.             final double zetaC = zeta * c;
  657.             final double zetaS = zeta * s;
  658.             final int n = xL.getDimension();
  659.             for (int i = 0; i < n; i++) {
  660.                 final double xi = xL.getEntry(i);
  661.                 final double vi = v.getEntry(i);
  662.                 final double wi = wbar.getEntry(i);
  663.                 xL.setEntry(i, xi + wi * zetaC + vi * zetaS);
  664.                 wbar.setEntry(i, wi * s - vi * c);
  665.             }
  666.             /*
  667.              * At this point
  668.              *   x = xL[k-1],
  669.              *   ptwbar = P' wbar[k],
  670.              * see Paige and Saunders (1975), equations (5.9) and (5.10).
  671.              */
  672.             bstep += snprod * c * zeta;
  673.             snprod *= s;
  674.             gmax = FastMath.max(gmax, gamma);
  675.             gmin = FastMath.min(gmin, gamma);
  676.             ynorm2 += zeta * zeta;
  677.             gammaZeta = minusEpsZeta - deltak * zeta;
  678.             minusEpsZeta = -eps * zeta;
  679.             /*
  680.              * At this point
  681.              *   snprod       = s[1] * ... * s[k-1],
  682.              *   gmax         = max(|alpha[1]|, gamma[1], ..., gamma[k-1]),
  683.              *   gmin         = min(|alpha[1]|, gamma[1], ..., gamma[k-1]),
  684.              *   ynorm2       = zeta[1]^2 + ... + zeta[k-1]^2,
  685.              *   gammaZeta    = gamma[k] * zeta[k],
  686.              *   minusEpsZeta = -eps[k+1] * zeta[k-1].
  687.              * The relation for gammaZeta can be retrieved from Paige and
  688.              * Saunders (1975), equation (5.4a), last line of the vector
  689.              * gbar[k] * zbar[k] = -eps[k] * zeta[k-2] - delta[k] * zeta[k-1].
  690.              */
  691.             updateNorms();
  692.         }

  693.         /**
  694.          * Computes the norms of the residuals, and checks for convergence.
  695.          * Updates {@link #lqnorm} and {@link #cgnorm}.
  696.          */
  697.         private void updateNorms() {
  698.             final double anorm = FastMath.sqrt(tnorm);
  699.             final double ynorm = FastMath.sqrt(ynorm2);
  700.             final double epsa = anorm * MACH_PREC;
  701.             final double epsx = anorm * ynorm * MACH_PREC;
  702.             final double epsr = anorm * ynorm * delta;
  703.             final double diag = gbar == 0. ? epsa : gbar;
  704.             lqnorm = FastMath.sqrt(gammaZeta * gammaZeta +
  705.                                    minusEpsZeta * minusEpsZeta);
  706.             final double qrnorm = snprod * beta1;
  707.             cgnorm = qrnorm * beta / FastMath.abs(diag);

  708.             /*
  709.              * Estimate cond(A). In this version we look at the diagonals of L
  710.              * in the factorization of the tridiagonal matrix, T = L * Q.
  711.              * Sometimes, T[k] can be misleadingly ill-conditioned when T[k+1]
  712.              * is not, so we must be careful not to overestimate acond.
  713.              */
  714.             final double acond;
  715.             if (lqnorm <= cgnorm) {
  716.                 acond = gmax / gmin;
  717.             } else {
  718.                 acond = gmax / FastMath.min(gmin, FastMath.abs(diag));
  719.             }
  720.             if (acond * MACH_PREC >= 0.1) {
  721.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.ILL_CONDITIONED_OPERATOR, acond);
  722.             }
  723.             if (beta1 <= epsx) {
  724.                 /*
  725.                  * x has converged to an eigenvector of A corresponding to the
  726.                  * eigenvalue shift.
  727.                  */
  728.                 throw new MathIllegalArgumentException(LocalizedCoreFormats.SINGULAR_OPERATOR);
  729.             }
  730.             rnorm = FastMath.min(cgnorm, lqnorm);
  731.             hasConverged = (cgnorm <= epsx) || (cgnorm <= epsr);
  732.         }

  733.         /**
  734.          * Returns {@code true} if the default stopping criterion is fulfilled.
  735.          *
  736.          * @return {@code true} if convergence of the iterations has occurred
  737.          */
  738.         boolean hasConverged() {
  739.             return hasConverged;
  740.         }

  741.         /**
  742.          * Returns {@code true} if the right-hand side vector is zero exactly.
  743.          *
  744.          * @return the boolean value of {@code b == 0}
  745.          */
  746.         boolean bEqualsNullVector() {
  747.             return bIsNull;
  748.         }

  749.         /**
  750.          * Returns {@code true} if {@code beta} is essentially zero. This method
  751.          * is used to check for early stop of the iterations.
  752.          *
  753.          * @return {@code true} if {@code beta < }{@link #MACH_PREC}
  754.          */
  755.         boolean betaEqualsZero() {
  756.             return beta < MACH_PREC;
  757.         }

  758.         /**
  759.          * Returns the norm of the updated, preconditioned residual.
  760.          *
  761.          * @return the norm of the residual, ||P * r||
  762.          */
  763.         double getNormOfResidual() {
  764.             return rnorm;
  765.         }
  766.     }

  767.     /**
  768.      * Creates a new instance of this class, with <a href="#stopcrit">default
  769.      * stopping criterion</a>. Note that setting {@code check} to {@code true}
  770.      * entails an extra matrix-vector product in the initial phase.
  771.      *
  772.      * @param maxIterations the maximum number of iterations
  773.      * @param delta the &delta; parameter for the default stopping criterion
  774.      * @param check {@code true} if self-adjointedness of both matrix and
  775.      * preconditioner should be checked
  776.      */
  777.     public SymmLQ(final int maxIterations, final double delta,
  778.                   final boolean check) {
  779.         super(maxIterations);
  780.         this.delta = delta;
  781.         this.check = check;
  782.     }

  783.     /**
  784.      * Creates a new instance of this class, with <a href="#stopcrit">default
  785.      * stopping criterion</a> and custom iteration manager. Note that setting
  786.      * {@code check} to {@code true} entails an extra matrix-vector product in
  787.      * the initial phase.
  788.      *
  789.      * @param manager the custom iteration manager
  790.      * @param delta the &delta; parameter for the default stopping criterion
  791.      * @param check {@code true} if self-adjointedness of both matrix and
  792.      * preconditioner should be checked
  793.      */
  794.     public SymmLQ(final IterationManager manager, final double delta,
  795.                   final boolean check) {
  796.         super(manager);
  797.         this.delta = delta;
  798.         this.check = check;
  799.     }

  800.     /**
  801.      * Returns {@code true} if symmetry of the matrix, and symmetry as well as
  802.      * positive definiteness of the preconditioner should be checked.
  803.      *
  804.      * @return {@code true} if the tests are to be performed
  805.      * @since 1.4
  806.      */
  807.     public final boolean shouldCheck() {
  808.         return check;
  809.     }

  810.     /**
  811.      * {@inheritDoc}
  812.      *
  813.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  814.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  815.      * @throws MathIllegalArgumentException if {@code m} is not
  816.      * positive definite
  817.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  818.      */
  819.     @Override
  820.     public RealVector solve(final RealLinearOperator a,
  821.         final RealLinearOperator m, final RealVector b) throws
  822.             NullArgumentException, MathIllegalStateException, MathIllegalArgumentException {
  823.         MathUtils.checkNotNull(a);
  824.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  825.         return solveInPlace(a, m, b, x, false, 0.);
  826.     }

  827.     /**
  828.      * Returns an estimate of the solution to the linear system (A - shift
  829.      * &middot; I) &middot; x = b.
  830.      * <p>
  831.      * If the solution x is expected to contain a large multiple of {@code b}
  832.      * (as in Rayleigh-quotient iteration), then better precision may be
  833.      * achieved with {@code goodb} set to {@code true}; this however requires an
  834.      * extra call to the preconditioner.
  835.      * </p>
  836.      * <p>
  837.      * {@code shift} should be zero if the system A &middot; x = b is to be
  838.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  839.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  840.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  841.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  842.      * shift, then the computed x may have very large components. When
  843.      * normalized, x may be closer to an eigenvector than b.
  844.      * </p>
  845.      *
  846.      * @param a the linear operator A of the system
  847.      * @param m the preconditioner, M (can be {@code null})
  848.      * @param b the right-hand side vector
  849.      * @param goodb usually {@code false}, except if {@code x} is expected to
  850.      * contain a large multiple of {@code b}
  851.      * @param shift the amount to be subtracted to all diagonal elements of A
  852.      * @return a reference to {@code x} (shallow copy)
  853.      * @throws NullArgumentException if one of the parameters is {@code null}
  854.      * @throws MathIllegalArgumentException if {@code a} or {@code m} is not square
  855.      * @throws MathIllegalArgumentException if {@code m} or {@code b} have dimensions
  856.      * inconsistent with {@code a}
  857.      * @throws MathIllegalStateException at exhaustion of the iteration count,
  858.      * unless a custom
  859.      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
  860.      * has been set at construction of the {@link IterationManager}
  861.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  862.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  863.      * @throws MathIllegalArgumentException if {@code m} is not
  864.      * positive definite
  865.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  866.      */
  867.     public RealVector solve(final RealLinearOperator a, final RealLinearOperator m,
  868.                             final RealVector b, final boolean goodb, final double shift)
  869.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  870.         MathUtils.checkNotNull(a);
  871.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  872.         return solveInPlace(a, m, b, x, goodb, shift);
  873.     }

  874.     /**
  875.      * {@inheritDoc}
  876.      *
  877.      * @param x not meaningful in this implementation; should not be considered
  878.      * as an initial guess (<a href="#initguess">more</a>)
  879.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  880.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  881.      * @throws MathIllegalArgumentException if {@code m} is not positive
  882.      * definite
  883.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  884.      */
  885.     @Override
  886.     public RealVector solve(final RealLinearOperator a,
  887.         final RealLinearOperator m, final RealVector b, final RealVector x)
  888.         throws NullArgumentException,
  889.         MathIllegalArgumentException,
  890.         MathIllegalStateException {
  891.         MathUtils.checkNotNull(x);
  892.         return solveInPlace(a, m, b, x.copy(), false, 0.);
  893.     }

  894.     /**
  895.      * {@inheritDoc}
  896.      *
  897.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  898.      * {@code true}, and {@code a} is not self-adjoint
  899.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  900.      */
  901.     @Override
  902.     public RealVector solve(final RealLinearOperator a, final RealVector b)
  903.         throws NullArgumentException,
  904.         MathIllegalArgumentException, MathIllegalStateException {
  905.         MathUtils.checkNotNull(a);
  906.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  907.         x.set(0.);
  908.         return solveInPlace(a, null, b, x, false, 0.);
  909.     }

  910.     /**
  911.      * Returns the solution to the system (A - shift &middot; I) &middot; x = b.
  912.      * <p>
  913.      * If the solution x is expected to contain a large multiple of {@code b}
  914.      * (as in Rayleigh-quotient iteration), then better precision may be
  915.      * achieved with {@code goodb} set to {@code true}.
  916.      * </p>
  917.      * <p>
  918.      * {@code shift} should be zero if the system A &middot; x = b is to be
  919.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  920.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  921.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  922.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  923.      * shift, then the computed x may have very large components. When
  924.      * normalized, x may be closer to an eigenvector than b.
  925.      * </p>
  926.      *
  927.      * @param a the linear operator A of the system
  928.      * @param b the right-hand side vector
  929.      * @param goodb usually {@code false}, except if {@code x} is expected to
  930.      * contain a large multiple of {@code b}
  931.      * @param shift the amount to be subtracted to all diagonal elements of A
  932.      * @return a reference to {@code x}
  933.      * @throws NullArgumentException if one of the parameters is {@code null}
  934.      * @throws MathIllegalArgumentException if {@code a} is not square
  935.      * @throws MathIllegalArgumentException if {@code b} has dimensions
  936.      * inconsistent with {@code a}
  937.      * @throws MathIllegalStateException at exhaustion of the iteration count,
  938.      * unless a custom
  939.      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
  940.      * has been set at construction of the {@link IterationManager}
  941.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  942.      * {@code true}, and {@code a} is not self-adjoint
  943.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  944.      */
  945.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  946.                             final boolean goodb, final double shift)
  947.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  948.         MathUtils.checkNotNull(a);
  949.         final RealVector x = new ArrayRealVector(a.getColumnDimension());
  950.         return solveInPlace(a, null, b, x, goodb, shift);
  951.     }

  952.     /**
  953.      * {@inheritDoc}
  954.      *
  955.      * @param x not meaningful in this implementation; should not be considered
  956.      * as an initial guess (<a href="#initguess">more</a>)
  957.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  958.      * {@code true}, and {@code a} is not self-adjoint
  959.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  960.      */
  961.     @Override
  962.     public RealVector solve(final RealLinearOperator a, final RealVector b,
  963.         final RealVector x) throws NullArgumentException, MathIllegalArgumentException,
  964.         MathIllegalStateException {
  965.         MathUtils.checkNotNull(x);
  966.         return solveInPlace(a, null, b, x.copy(), false, 0.);
  967.     }

  968.     /**
  969.      * {@inheritDoc}
  970.      *
  971.      * @param x the vector to be updated with the solution; {@code x} should
  972.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  973.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  974.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  975.      * @throws MathIllegalArgumentException if {@code m} is not
  976.      * positive definite
  977.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  978.      */
  979.     @Override
  980.     public RealVector solveInPlace(final RealLinearOperator a,
  981.         final RealLinearOperator m, final RealVector b, final RealVector x)
  982.         throws NullArgumentException,
  983.         MathIllegalArgumentException,
  984.         MathIllegalStateException {
  985.         return solveInPlace(a, m, b, x, false, 0.);
  986.     }

  987.     /**
  988.      * Returns an estimate of the solution to the linear system (A - shift
  989.      * &middot; I) &middot; x = b. The solution is computed in-place.
  990.      * <p>
  991.      * If the solution x is expected to contain a large multiple of {@code b}
  992.      * (as in Rayleigh-quotient iteration), then better precision may be
  993.      * achieved with {@code goodb} set to {@code true}; this however requires an
  994.      * extra call to the preconditioner.
  995.      * </p>
  996.      * <p>
  997.      * {@code shift} should be zero if the system A &middot; x = b is to be
  998.      * solved. Otherwise, it could be an approximation to an eigenvalue of A,
  999.      * such as the Rayleigh quotient b<sup>T</sup> &middot; A &middot; b /
  1000.      * (b<sup>T</sup> &middot; b) corresponding to the vector b. If b is
  1001.      * sufficiently like an eigenvector corresponding to an eigenvalue near
  1002.      * shift, then the computed x may have very large components. When
  1003.      * normalized, x may be closer to an eigenvector than b.
  1004.      * </p>
  1005.      *
  1006.      * @param a the linear operator A of the system
  1007.      * @param m the preconditioner, M (can be {@code null})
  1008.      * @param b the right-hand side vector
  1009.      * @param x the vector to be updated with the solution; {@code x} should
  1010.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  1011.      * @param goodb usually {@code false}, except if {@code x} is expected to
  1012.      * contain a large multiple of {@code b}
  1013.      * @param shift the amount to be subtracted to all diagonal elements of A
  1014.      * @return a reference to {@code x} (shallow copy).
  1015.      * @throws NullArgumentException if one of the parameters is {@code null}
  1016.      * @throws MathIllegalArgumentException if {@code a} or {@code m} is not square
  1017.      * @throws MathIllegalArgumentException if {@code m}, {@code b} or {@code x}
  1018.      * have dimensions inconsistent with {@code a}.
  1019.      * @throws MathIllegalStateException at exhaustion of the iteration count,
  1020.      * unless a custom
  1021.      * {@link org.hipparchus.util.Incrementor.MaxCountExceededCallback callback}
  1022.      * has been set at construction of the {@link IterationManager}
  1023.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  1024.      * {@code true}, and {@code a} or {@code m} is not self-adjoint
  1025.      * @throws MathIllegalArgumentException if {@code m} is not positive definite
  1026.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  1027.      */
  1028.     public RealVector solveInPlace(final RealLinearOperator a,
  1029.                                    final RealLinearOperator m, final RealVector b,
  1030.                                    final RealVector x, final boolean goodb, final double shift)
  1031.         throws MathIllegalArgumentException, NullArgumentException, MathIllegalStateException {
  1032.         checkParameters(a, m, b, x);

  1033.         final IterationManager manager = getIterationManager();
  1034.         /* Initialization counts as an iteration. */
  1035.         manager.resetIterationCount();
  1036.         manager.incrementIterationCount();

  1037.         final State state;
  1038.         state = new State(a, m, b, goodb, shift, delta, check);
  1039.         state.init();
  1040.         state.refineSolution(x);
  1041.         IterativeLinearSolverEvent event;
  1042.         event = new DefaultIterativeLinearSolverEvent(this,
  1043.                                                       manager.getIterations(),
  1044.                                                       x,
  1045.                                                       b,
  1046.                                                       state.getNormOfResidual());
  1047.         if (state.bEqualsNullVector()) {
  1048.             /* If b = 0 exactly, stop with x = 0. */
  1049.             manager.fireTerminationEvent(event);
  1050.             return x;
  1051.         }
  1052.         /* Cause termination if beta is essentially zero. */
  1053.         final boolean earlyStop;
  1054.         earlyStop = state.betaEqualsZero() || state.hasConverged();
  1055.         manager.fireInitializationEvent(event);
  1056.         if (!earlyStop) {
  1057.             do {
  1058.                 manager.incrementIterationCount();
  1059.                 event = new DefaultIterativeLinearSolverEvent(this,
  1060.                                                               manager.getIterations(),
  1061.                                                               x,
  1062.                                                               b,
  1063.                                                               state.getNormOfResidual());
  1064.                 manager.fireIterationStartedEvent(event);
  1065.                 state.update();
  1066.                 state.refineSolution(x);
  1067.                 event = new DefaultIterativeLinearSolverEvent(this,
  1068.                                                               manager.getIterations(),
  1069.                                                               x,
  1070.                                                               b,
  1071.                                                               state.getNormOfResidual());
  1072.                 manager.fireIterationPerformedEvent(event);
  1073.             } while (!state.hasConverged());
  1074.         }
  1075.         event = new DefaultIterativeLinearSolverEvent(this,
  1076.                                                       manager.getIterations(),
  1077.                                                       x,
  1078.                                                       b,
  1079.                                                       state.getNormOfResidual());
  1080.         manager.fireTerminationEvent(event);
  1081.         return x;
  1082.     }

  1083.     /**
  1084.      * {@inheritDoc}
  1085.      *
  1086.      * @param x the vector to be updated with the solution; {@code x} should
  1087.      * not be considered as an initial guess (<a href="#initguess">more</a>)
  1088.      * @throws MathIllegalArgumentException if {@link #shouldCheck()} is
  1089.      * {@code true}, and {@code a} is not self-adjoint
  1090.      * @throws MathIllegalArgumentException if {@code a} is ill-conditioned
  1091.      */
  1092.     @Override
  1093.     public RealVector solveInPlace(final RealLinearOperator a,
  1094.         final RealVector b, final RealVector x) throws NullArgumentException, MathIllegalArgumentException,
  1095.         MathIllegalStateException {
  1096.         return solveInPlace(a, null, b, x, false, 0.);
  1097.     }
  1098. }