/// <summary>The multiplication of two <see cref="DenseMatrix"/> objects, i.e. A * B.
        /// </summary>
        /// <param name="a">The first dense matrix A.</param>
        /// <param name="b">The second dense matrix B.</param>
        /// <returns>The result of the operator, i.e. A * B.</returns>
        /// <exception cref="ArgumentNullException">Thrown, if <paramref name="a"/> or <paramref name="b"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown, if the matrix operation A * B can not be place because of unsuited arguments.</exception>
        public static DenseMatrix operator *(DenseMatrix a, DenseMatrix b)
        {
            MatrixSpecialFunction.TestMultiplicationInput(a, b);

            int m = a.RowCount;    // number of rows of op(A) and C
            int n = b.ColumnCount; // number of columns of op(B) and C
            int k = a.ColumnCount; // number of columns of op(A) = number of rows of op(B)

            var c = new double[n * m];

            BLAS.Level3.dgemm(m, n, k, 1.0, a.m_Data, b.m_Data, 0.0, c, a.m_TransposeState, b.m_TransposeState);

            return(new DenseMatrix(m, n, c));
        }
        /// <summary>Gets C = \alpha * (A * B) + \beta * C, where C represents the matrix specified by the current instance. The current instance will be changed.
        /// </summary>
        /// <param name="a">The dense matrix A.</param>
        /// <param name="b">The dense matrix B.</param>
        /// <param name="alpha">The scalar factor \alpha.</param>
        /// <param name="beta">The scalar factor \beta.</param>
        /// <returns>The result of the operation, i.e. \alpha * (A * B) + \beta * this, which is a reference to the current instance.</returns>
        /// <exception cref="ArgumentNullException">Thrown, if <paramref name="a"/> or <paramref name="b"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown, if the number of row/columns of <paramref name="a"/> and <paramref name="b"/> is not allowed for the operation.</exception>
        /// <remarks>The current object will be changed.</remarks>
        public DenseMatrix AddAssignment(DenseMatrix a, DenseMatrix b, double alpha = 1.0, double beta = 1.0)
        {
            MatrixSpecialFunction.TestMultiplicationInput(a, b);

            if (m_TransposeState == BLAS.MatrixTransposeState.Transpose)
            {
                T_InPlace();  // re-sort the matrix represented by the current instance and swap #rows vs. #columns. This allows the application of BLAS level 3 routine in the next step
            }
            int m = a.RowCount;
            int n = b.ColumnCount;
            int k = a.ColumnCount;

            if (m != m_RowCount)
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExceptionMessages.ArgumentCombinationInvalid, "RowCount, A.RowCount"));
            }
            if (n != m_ColumnCount)
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExceptionMessages.ArgumentCombinationInvalid, "ColumnCount, B.ColumnCount"));
            }
            BLAS.Level3.dgemm(m, n, k, alpha, a.m_Data, b.m_Data, beta, m_Data, a.m_TransposeState, b.m_TransposeState);
            return(this);
        }
Beispiel #3
0
        /// <summary>Multiplies a diagonal matrix with a dense matrix.
        /// </summary>
        /// <param name="denseMatrix">The dense matrix (left side).</param>
        /// <param name="diagonalMatrix">The diagonal matrix (right side).</param>
        /// <returns>The <see cref="DenseMatrix"/> object that represents the product of both specified matrices.</returns>
        public static DenseMatrix operator *(DenseMatrix denseMatrix, DiagonalMatrix diagonalMatrix)
        {
            MatrixSpecialFunction.TestMultiplicationInput(denseMatrix, diagonalMatrix);

            int rowCount    = denseMatrix.RowCount;
            int columnCount = denseMatrix.ColumnCount;

            var data = new double[rowCount * columnCount];

            switch (denseMatrix.DataTransposeState)
            {
            case BLAS.MatrixTransposeState.NoTranspose:      // here, we use BLAS functions to speed up operation
                BLAS.Level1.dcopy(rowCount * columnCount, denseMatrix.Data, data);

                for (int j = 0; j < columnCount; j++)
                {
                    BLAS.Level1.dscal(rowCount, diagonalMatrix[j, j], data, 1, rowCount * j);      // c[i + RowCount * j] *= diagonal[j,j]
                }
                break;

            case BLAS.MatrixTransposeState.Transpose:
                for (int j = 0; j < columnCount; j++)
                {
                    double diagonalFactor = diagonalMatrix[j, j];
                    for (int i = 0; i < rowCount; i++)
                    {
                        data[i + rowCount * j] = denseMatrix[i, j] * diagonalFactor;
                    }
                }
                break;

            default:
                throw new NotImplementedException();
            }
            return(new DenseMatrix(rowCount, columnCount, data));
        }
        /// <summary>The multiplication of two <see cref="GeneralBandMatrix"/> objects, i.e. A * B.
        /// </summary>
        /// <param name="a">The first general band matrix A.</param>
        /// <param name="b">The second general band matrix B.</param>
        /// <returns>The result of the operator, i.e. 'A * B'.</returns>
        /// <exception cref="ArgumentNullException">Thrown, if <paramref name="a"/> or <paramref name="b"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown, if the number of columns of <paramref name="a"/> does not coincide with the number of rows of <paramref name="b"/>.</exception>
        public static GeneralBandMatrix operator *(GeneralBandMatrix a, GeneralBandMatrix b)
        {
            MatrixSpecialFunction.TestMultiplicationInput(a, b);

            int n = b.ColumnCount;  // number of columns of op(B) and C
            int m = a.RowCount; // number of rows of op(A) and C
            int k = a.ColumnCount; // number of columns of op(A) = number of rows of op(B)

            int subDiagonalCountOpA = a.SubDiagonalCount;
            int superDiagonalCountOpA = a.SuperDiagonalCount;
            int subDiagonalCountOpB = b.SubDiagonalCount;
            int superDiagonalCountOpB = b.SuperDiagonalCount;

            if (b.RowCount != k)
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExceptionMessages.ArgumentCombinationInvalid, "A.ColumnCount, B.RowCount"));
            }

            // determind the parameters for the result object and allocate memory
            int subDiagonalCount = Math.Max(0, subDiagonalCountOpA - superDiagonalCountOpB);
            int superDiagonalCount = Math.Max(0, superDiagonalCountOpA - subDiagonalCountOpB);

            int length = m * (subDiagonalCount + superDiagonalCount + 1);
            double[] c = new double[length];

            double[] aData = a.m_Data;
            double[] bData = b.m_Data;

            // do a second switch and calculate the result for each case:
            if ((a.m_TransposeState == BLAS.MatrixTransposeState.Transpose) && (b.m_TransposeState == BLAS.MatrixTransposeState.Transpose))
            {
                for (int j = 0; j < n; j++)
                {
                    int offsetMatrixA = j * (subDiagonalCountOpA + superDiagonalCountOpA + 1);
                    int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1);

                    for (int i = j - superDiagonalCount; i <= j + subDiagonalCount; i++)
                    {
                        double value = 0.0;
                        for (int s = Math.Max(i - subDiagonalCountOpA, j - superDiagonalCountOpB); s <= Math.Min(k, Math.Min(i + superDiagonalCountOpA, j + subDiagonalCountOpB)); s++)
                        {
                            value += aData[s - i + superDiagonalCountOpA + offsetMatrixA] * bData[j - s + superDiagonalCountOpB + s * (subDiagonalCountOpB + superDiagonalCountOpB + 1)];
                        }
                        c[i - j + superDiagonalCount + offsetMatrixC] = value;
                    }
                }
            }
            else if (a.m_TransposeState == BLAS.MatrixTransposeState.Transpose)
            {
                for (int j = 0; j < n; j++)
                {
                    int offsetMatrixA = j * (subDiagonalCountOpA + superDiagonalCountOpA + 1);
                    int offsetMatrixB = j * (subDiagonalCountOpB + superDiagonalCountOpB + 1);
                    int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1);

                    for (int i = j - superDiagonalCount; i <= j + subDiagonalCount; i++)
                    {
                        double value = 0.0;
                        for (int s = Math.Max(i - subDiagonalCountOpA, j - superDiagonalCountOpB); s <= Math.Min(k, Math.Min(i + superDiagonalCountOpA, j + subDiagonalCountOpB)); s++)
                        {
                            value += aData[s - i + superDiagonalCountOpA + offsetMatrixA] * bData[s - j + superDiagonalCountOpB + offsetMatrixB];
                        }
                        c[i - j + superDiagonalCount + offsetMatrixC] = value;
                    }
                }
            }
            else if (b.m_TransposeState == BLAS.MatrixTransposeState.Transpose)
            {
                for (int j = 0; j < n; j++)
                {
                    int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1);

                    for (int i = j - superDiagonalCount; i <= j + subDiagonalCount; i++)
                    {
                        double value = 0.0;
                        for (int s = Math.Max(i - subDiagonalCountOpA, j - superDiagonalCountOpB); s <= Math.Min(k, Math.Min(i + superDiagonalCountOpA, j + subDiagonalCountOpB)); s++)
                        {
                            value += aData[i - s + superDiagonalCountOpA + s * (subDiagonalCountOpA + superDiagonalCountOpA + 1)] * bData[j - s + superDiagonalCountOpB + s * (subDiagonalCountOpB + superDiagonalCountOpB + 1)];
                        }
                        c[i - j + superDiagonalCount + offsetMatrixC] = value;
                    }
                }
            }
            else  // op(A) = A, op(B) = B
            {
                for (int j = 0; j < n; j++)
                {
                    int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1);
                    int offsetMatrixB = j * (subDiagonalCountOpB + superDiagonalCountOpB + 1);

                    for (int i = j - superDiagonalCount; i <= j + subDiagonalCount; i++)
                    {
                        double value = 0.0;
                        for (int s = Math.Max(i - subDiagonalCountOpA, j - superDiagonalCountOpB); s <= Math.Min(k, Math.Min(i + superDiagonalCountOpA, j + subDiagonalCountOpB)); s++)
                        {
                            value += aData[i - s + superDiagonalCountOpA + s * (subDiagonalCountOpA + superDiagonalCountOpA + 1)] * bData[s - j + superDiagonalCountOpB + offsetMatrixB];
                        }
                        c[i - j + superDiagonalCount + offsetMatrixC] = value;
                    }
                }
            }
            return new GeneralBandMatrix(m, n, subDiagonalCount, superDiagonalCount, c);
        }