public static void SolveLowerLeftTriangular(double[] tStore, double[] x, int xOffset, int dimension)
 {
     for (int r = 0; r < dimension; r++)
     {
         double t = Blas1.dDot(tStore, r, dimension, x, xOffset, 1, r);
         x[xOffset + r] -= t;
     }
 }
 public static void SolveUpperRightTriangular(double[] tStore, double[] x, int xOffset, int dimension)
 {
     for (int r = dimension - 1; r >= 0; r--)
     {
         int    i0 = dimension * r + r;
         double t  = Blas1.dDot(tStore, i0 + dimension, dimension, x, xOffset + r + 1, 1, dimension - r - 1);
         x[xOffset + r] = (x[xOffset + r] - t) / tStore[i0];
     }
 }
Example #3
0
        // Apply a Householder transfrom defined by v to the vector x (which may be
        // a column of a matrix, if H is applied from the left, or a row of a matrix
        // if H is applied from the right). On exit v is unchanged, x is changed.
        // We have H = I - \beta v v^T, so H x = x - (\beta v^T x) v.

        public static void ApplyHouseholderReflection(
            double[] uStore, int uOffset, int uStride,
            double[] yStore, int yOffset, int yStride,
            int count
            )
        {
            double s = Blas1.dDot(uStore, uOffset, uStride, yStore, yOffset, yStride, count);

            Blas1.dAxpy(-s, uStore, uOffset, uStride, yStore, yOffset, yStride, count);
        }
Example #4
0
        // Solve a triangular system
        //   aIsUpper indicates whether A is upper/right or lower/left
        //   aIsUnit indicates whether A's diagonal elements are all 1 or not
        // The relevent elements of xStore are overwritten by the solution vector

        public static void dTrsv(
            bool aIsUpper, bool aIsUnit, double[] aStore, int aOffset, int aRowStride, int aColStride,
            double[] xStore, int xOffset, int xStride,
            int count
            )
        {
            int aDiagonalStride = aColStride + aRowStride;

            // If A is upper triangular, start at the bottom/right and reverse the direction of progression.
            // This does not affect the passed in variables because integers are pass-by-value.
            if (aIsUpper)
            {
                aOffset         = aOffset + (count - 1) * aDiagonalStride;
                aRowStride      = -aRowStride;
                aColStride      = -aColStride;
                aDiagonalStride = -aDiagonalStride;
                xOffset         = xOffset + (count - 1) * xStride;
                xStride         = -xStride;
            }

            // The index of the first row element to be subtracted in the numerator.
            int aRowIndex = aOffset;
            // The index of the x element to be solved for.
            int xIndex = xOffset;

            // We hoist the aIsUnit test outside the loop and pay the cost of a little repeated code in
            // order to avoid an unnecessary per-loop test. It's possible the compiler could do this for us.
            if (aIsUnit)
            {
                for (int n = 0; n < count; n++)
                {
                    xStore[xIndex] -= Blas1.dDot(aStore, aRowIndex, aColStride, xStore, xOffset, xStride, n);
                    aRowIndex      += aRowStride;
                    xIndex         += xStride;
                }
            }
            else
            {
                int aDiagonalIndex = aOffset;
                for (int n = 0; n < count; n++)
                {
                    xStore[xIndex] -= Blas1.dDot(aStore, aRowIndex, aColStride, xStore, xOffset, xStride, n);
                    xStore[xIndex] /= aStore[aDiagonalIndex];
                    aRowIndex      += aRowStride;
                    aDiagonalIndex += aDiagonalStride;
                    xIndex         += xStride;
                }
            }
        }
Example #5
0
        // y <- A x + y

        public static void dGemv(
            double[] aStore, int aOffset, int aRowStride, int aColStride,
            double[] xStore, int xOffset, int xStride,
            double[] yStore, int yOffset, int yStride,
            int rows, int cols
            )
        {
            int aIndex = aOffset;
            int yIndex = yOffset;

            for (int n = 0; n < rows; n++)
            {
                yStore[yIndex] += Blas1.dDot(aStore, aIndex, aColStride, xStore, xOffset, xStride, cols);
                aIndex         += aRowStride;
                yIndex         += yStride;
            }
        }
Example #6
0
        /// <summary>
        /// Computes the inner (scalar or dot) product of a row and a column vector.
        /// </summary>
        /// <param name="v">The row vector.</param>
        /// <param name="u">The column vector.</param>
        /// <returns>The value of the scalar product.</returns>
        public static double operator *(RowVector v, ColumnVector u)
        {
            if (v == null)
            {
                throw new ArgumentNullException(nameof(v));
            }
            if (u == null)
            {
                throw new ArgumentNullException(nameof(u));
            }
            if (v.dimension != u.dimension)
            {
                throw new DimensionMismatchException();
            }
            double p = Blas1.dDot(v.store, v.offset, v.stride, u.store, u.offset, u.stride, v.dimension);

            return(p);
        }
        // on input:
        // store contains the matrix in column-major order (must have the length dimension^2)
        // permutation contains the row permutation (typically 0, 1, 2, ..., dimension - 1; must have the length dimension^2)
        // parity contains the parity of the row permutation (typically 1; must be 1 or -1)
        // dimension contains the dimension of the matrix (must be non-negative)
        // on output:
        // store is replaced by the L and U matrices, L in the lower-left triangle (with 1s along the diagonal), U in the upper-right triangle
        // permutation is replaced by the row permutation, and parity be the parity of that permutation

        // A = PLU

        public static void LUDecompose(double[] store, int[] permutation, ref int parity, int dimension)
        {
            for (int d = 0; d < dimension; d++)
            {
                int    pivotRow   = -1;
                double pivotValue = 0.0;

                for (int r = d; r < dimension; r++)
                {
                    int    a0 = dimension * d + r;
                    double t  = store[a0] - Blas1.dDot(store, r, dimension, store, dimension * d, 1, d);
                    store[a0] = t;
                    if (Math.Abs(t) > Math.Abs(pivotValue))
                    {
                        pivotRow   = r;
                        pivotValue = t;
                    }
                }

                if (pivotValue == 0.0)
                {
                    throw new DivideByZeroException();
                }

                if (pivotRow != d)
                {
                    // switch rows
                    Blas1.dSwap(store, d, dimension, store, pivotRow, dimension, dimension);
                    int t = permutation[pivotRow];
                    permutation[pivotRow] = permutation[d];
                    permutation[d]        = t;
                    parity = -parity;
                }

                Blas1.dScal(1.0 / pivotValue, store, dimension * d + d + 1, 1, dimension - d - 1);

                for (int c = d + 1; c < dimension; c++)
                {
                    double t = Blas1.dDot(store, d, dimension, store, dimension * c, 1, d);
                    store[dimension * c + d] -= t;
                }
            }
        }
Example #8
0
        public static void SolveUpperRightTriangular(double[] tStore, int tRows, int tCols, double[] xStore, int xOffset)
        {
            Debug.Assert(tRows >= tCols);
            // pre-calculate some useful quantities
            int trp1 = tRows + 1;
            int tcm1 = tCols - 1;
            // initialize the x index (to its highest value) the the diagonal t index (to its highest value)
            int xIndex = xOffset + tcm1;
            int tIndex = trp1 * tcm1;

            // do the first, trivial back-substitution
            xStore[xIndex] /= tStore[tIndex];
            // do the remaining back-substitutions, each of which requires subtracting n previously computed x-values
            for (int n = 1; n <= tcm1; n++)
            {
                xIndex -= 1;
                tIndex -= trp1;
                double t = Blas1.dDot(tStore, tIndex + tRows, tRows, xStore, xIndex + 1, 1, n);
                xStore[xIndex] = (xStore[xIndex] - t) / tStore[tIndex];
            }
        }