Example #1
0
        public bool Solve()
        {
            Iterations = 0;
            int size = B.Length;

            // Based on the algorithm in "Matrix Computations" by Golum and Van Loan.
            R = new double[size];
            P = new double[size];
            W = new double[size];

            if (X == null || UseXAsInitialGuess == false)
            {
                if (X == null)
                {
                    X = new double[size];
                }
                Array.Clear(X, 0, X.Length);
                Array.Copy(B, R, B.Length);
            }
            else
            {
                // hopefully is X is a decent initialization...
                InitializeR(R);
            }

            // [RMS] these were inside loop but they are constant!
            double norm  = BufferUtil.Dot(B, B);
            double root1 = Math.Sqrt(norm);

            // The first iteration.
            double rho0 = BufferUtil.Dot(R, R);

            // [RMS] If we were initialized w/ constraints already satisfied,
            //   then we are done! (happens for example in mesh deformations)
            if (rho0 < math.MathUtil.ZeroTolerance * root1)
            {
                return(true);
            }

            Array.Copy(R, P, R.Length);

            MultiplyF(P, W);

            double alpha = rho0 / BufferUtil.Dot(P, W);

            BufferUtil.MultiplyAdd(X, alpha, P);
            BufferUtil.MultiplyAdd(R, -alpha, W);
            double rho1 = BufferUtil.Dot(R, R);

            // The remaining iterations.
            int iter;

            for (iter = 1; iter < MaxIterations; ++iter)
            {
                double root0 = Math.Sqrt(rho1);
                if (root0 <= math.MathUtil.ZeroTolerance * root1)
                {
                    break;
                }

                double beta = rho1 / rho0;
                UpdateP(P, beta, R);

                MultiplyF(P, W);

                alpha = rho1 / BufferUtil.Dot(P, W);
                BufferUtil.MultiplyAdd(X, alpha, P);
                BufferUtil.MultiplyAdd(R, -alpha, W);
                rho0 = rho1;
                rho1 = BufferUtil.Dot(R, R);
            }


            //System.Console.WriteLine("{0} iterations", iter);
            Iterations = iter;
            return(iter < MaxIterations);
        }