/// <summary>Computes the sum of two specific <see cref="DenseMatrix"/> objects, i.e. A + \alpha * B. /// </summary> /// <param name="a">The first matrix, i.e. 'A'.</param> /// <param name="b">The second matrix, i.e. 'B'.</param> /// <param name="scalar">The scalar \alpha.</param> /// <returns>The sum A + \alpha * B in its <see cref="DenseMatrix"/> representation.</returns> private static DenseMatrix Add(DenseMatrix a, DenseMatrix b, double scalar) { MatrixSpecialFunction.TestAdditionInput(a, b); int n = a.RowCount * a.ColumnCount; var y = new double[n]; int rowCount = a.RowCount; int columnCount = a.ColumnCount; if (a.m_TransposeState == BLAS.MatrixTransposeState.NoTranspose) { switch (b.m_TransposeState) { case BLAS.MatrixTransposeState.NoTranspose: BLAS.Level1.dcopy(n, a.Data, y); BLAS.Level1.daxpy(n, scalar, b.Data, y); break; case BLAS.MatrixTransposeState.Transpose: BLAS.Level1.dcopy(n, a.Data, y); for (int i = 0; i < rowCount; i++) { BLAS.Level1.daxpy(columnCount, scalar, b.Data, y, 1, rowCount, i * b.m_RowCount, i); } break; default: throw new InvalidOperationException(); } return(new DenseMatrix(rowCount, columnCount, y)); } else // A^t { switch (b.m_TransposeState) { case BLAS.MatrixTransposeState.NoTranspose: BLAS.Level1.dcopy(n, a.Data, y); for (int i = 0; i < rowCount; i++) { BLAS.Level1.daxpy(columnCount, scalar, b.Data, y, 1, rowCount, i * b.m_RowCount, i); } break; case BLAS.MatrixTransposeState.Transpose: BLAS.Level1.dcopy(n, a.Data, y); BLAS.Level1.daxpy(n, scalar, b.Data, y); break; default: throw new InvalidOperationException(); } return(new DenseMatrix(rowCount, columnCount, y, BLAS.MatrixTransposeState.Transpose)); } }
/// <summary>Gets 'C = C + \alpha * A, where 'C' represents the matrix specified by the current instance. The current instance will be changed. /// </summary> /// <param name="a">The dense matrix 'A' to add.</param> /// <param name="alpha">The scalar factor \alpha.</param> /// <returns>The result of the operation, i.e. '\alpha * A + this', which is a reference to the current instance.</returns> /// <exception cref="ArgumentNullException">Thrown, if <paramref name="a"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">Thrown, if the number of rows/columns of <paramref name="a"/> does not coincide with the number of rows/columns of the matrix given by the current instance.</exception> /// <remarks>The current object will be changed and a reference to the current object will be returned. /// <para> /// Use this method for some '+=' or '-=' operator which may performs better than some separate addition. /// </para></remarks> public DenseMatrix AddAssignment(DenseMatrix a, double alpha = 1.0) { MatrixSpecialFunction.TestAdditionInput(this, a); if (m_TransposeState == BLAS.MatrixTransposeState.NoTranspose) { switch (a.m_TransposeState) { case BLAS.MatrixTransposeState.NoTranspose: BLAS.Level1.daxpy(m_RowCount * m_ColumnCount, alpha, a.m_Data, m_Data); break; case BLAS.MatrixTransposeState.Transpose: // c[i+j*m_RowCount] += \alpha * a[j+i*a.m_RowCount] for i=0,..,m_RowCount-1, j=0,..,m_ColumnCount-1 double[] aData = a.Data; for (int i = 0; i < m_RowCount; i++) { BLAS.Level1.daxpy(m_ColumnCount, alpha, aData, m_Data, 1, m_RowCount, i * a.m_RowCount, i); } break; default: throw new InvalidOperationException(); } } else if (m_TransposeState == BLAS.MatrixTransposeState.Transpose) { switch (a.m_TransposeState) { case BLAS.MatrixTransposeState.Transpose: BLAS.Level1.daxpy(m_RowCount * m_ColumnCount, alpha, a.m_Data, m_Data); break; case BLAS.MatrixTransposeState.NoTranspose: for (int i = 0; i < m_RowCount; i++) { BLAS.Level1.daxpy(m_ColumnCount, alpha, a.m_Data, m_Data, a.m_RowCount, 1, i, i * m_RowCount); // m_Data[j + i * m_RowCount] += alpha * a.m_Data[i + j * a.m_RowCount] for j \in [0, m_ColumnCount), } break; default: throw new InvalidOperationException(); } } else { throw new InvalidOperationException(); } return(this); }
/// <summary>Gets C = C + \alpha * A, where C represents the matrix specified by the current instance. The current instance will be changed. /// </summary> /// <param name="a">The general band matrix A to add.</param> /// <param name="alpha">The scalar factor \alpha.</param> /// <returns>The result of the operation, i.e. \alpha * A + this, which is just a reference of the current instance.</returns> /// <exception cref="ArgumentNullException">Thrown, if <paramref name="a"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">Thrown, if the number of rows/columns of A does not coincide with the number of rows/columns of the matrix given by the current instance.</exception> /// <remarks>The current object will be changed and a reference to the current object will be returned. /// <para> /// Use this method for some '+=' or '-=' operator which may performs better than some separate addition. /// </para></remarks> public DenseMatrix AddAssignment(GeneralBandMatrix a, double alpha = 1.0) { MatrixSpecialFunction.TestAdditionInput(this, a); int superPlusSubPlusMainDiagonalCount = a.SuperDiagonalCount + a.SubDiagonalCount + 1; if (m_TransposeState == BLAS.MatrixTransposeState.NoTranspose) { switch (a.DataTransposeState) { case BLAS.MatrixTransposeState.NoTranspose: for (int j = 0; j < m_ColumnCount; j++) { int iMin = System.Math.Max(0, j - a.SuperDiagonalCount); int iMax = System.Math.Min(m_RowCount - 1, j + a.SubDiagonalCount); for (int i = iMin; i <= iMax; i++) { m_Data[i + m_RowCount * j] += alpha * a.Data[j * superPlusSubPlusMainDiagonalCount + (i - j + a.SuperDiagonalCount)]; } } break; case BLAS.MatrixTransposeState.Transpose: for (int j = 0; j < m_ColumnCount; j++) { int iMin = System.Math.Max(0, j - a.SuperDiagonalCount); int iMax = System.Math.Min(m_RowCount - 1, j + a.SubDiagonalCount); for (int i = iMin; i <= iMax; i++) { m_Data[i + m_RowCount * j] += alpha * a.Data[i * superPlusSubPlusMainDiagonalCount + (j - i + a.SuperDiagonalCount)]; } } break; default: throw new InvalidOperationException(); } } else if (m_TransposeState == BLAS.MatrixTransposeState.Transpose) { switch (a.DataTransposeState) { case BLAS.MatrixTransposeState.NoTranspose: for (int j = 0; j < ColumnCount; j++) // Property 'ColumnCount' returns the value of m_RowCount { int iMin = System.Math.Max(0, j - a.SuperDiagonalCount); int iMax = System.Math.Min(RowCount - 1, j + a.SubDiagonalCount); for (int i = iMin; i <= iMax; i++) { m_Data[j + m_RowCount * i] += alpha * a.Data[j * superPlusSubPlusMainDiagonalCount + (i - j + a.SuperDiagonalCount)]; } } break; case BLAS.MatrixTransposeState.Transpose: for (int j = 0; j < ColumnCount; j++) // Property 'ColumnCount' returns the value of m_RowCount { int iMin = System.Math.Max(0, j - a.SuperDiagonalCount); int iMax = System.Math.Min(RowCount - 1, j + a.SubDiagonalCount); for (int i = iMin; i <= iMax; i++) { m_Data[j + m_RowCount * i] += alpha * a.Data[i * superPlusSubPlusMainDiagonalCount + (j - i + a.SuperDiagonalCount)]; } } break; default: throw new InvalidOperationException(); } } else { throw new InvalidOperationException(); } return(this); }
/// <summary>The addition of two <see cref="GeneralBandMatrix"/> objects, i.e. A + \alpha * B. /// </summary> /// <param name="a">The first general band matrix A.</param> /// <param name="b">The second general band matrix B.</param> /// <param name="scalar">The scalar \alpha.</param> /// <returns>The result of the operator, i.e. A + \alpha * 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> private static GeneralBandMatrix Add(GeneralBandMatrix a, GeneralBandMatrix b, double scalar) { MatrixSpecialFunction.TestAdditionInput(a, b); int subDiagonalCount = Math.Max(a.SubDiagonalCount, b.SubDiagonalCount); int superDiagonalCount = Math.Max(a.SuperDiagonalCount, b.SuperDiagonalCount); int rowCount = a.RowCount; int columnCount = a.ColumnCount; int length = rowCount * (subDiagonalCount + superDiagonalCount + 1); var c = new double[length]; switch (a.m_TransposeState) { case BLAS.MatrixTransposeState.NoTranspose: if (b.m_TransposeState == BLAS.MatrixTransposeState.NoTranspose) { for (int j = 0; j < columnCount; j++) { int offSetMatrixA = j * (a.m_SubDiagonalCount + a.m_SuperDiagonalCount + 1); int offSetMatrixB = j * (b.m_SubDiagonalCount + b.m_SuperDiagonalCount + 1); int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1); for (int i = Math.Max(0, j - superDiagonalCount); i <= Math.Min(rowCount - 1, j + subDiagonalCount); i++) { double value = 0.0; if ((i - j <= a.m_SubDiagonalCount) && (j - i <= a.m_SuperDiagonalCount)) { value += a.m_Data[i - j + a.m_SuperDiagonalCount + offSetMatrixA]; } if ((i - j <= b.m_SubDiagonalCount) && (j - i <= b.m_SuperDiagonalCount)) { value += scalar * b.m_Data[i - j + b.m_SuperDiagonalCount + offSetMatrixB]; } c[i - j + superDiagonalCount + offsetMatrixC] = value; } } } else { int k = b.m_SubDiagonalCount + b.m_SuperDiagonalCount + 1; for (int j = 0; j < columnCount; j++) { int offSetMatrixA = j * (a.m_SubDiagonalCount + a.m_SuperDiagonalCount + 1); int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1); for (int i = Math.Max(0, j - superDiagonalCount); i <= Math.Min(rowCount - 1, j + subDiagonalCount); i++) { double value = 0.0; if ((i - j <= a.m_SubDiagonalCount) && (j - i <= a.m_SuperDiagonalCount)) { value += a.m_Data[i - j + a.m_SuperDiagonalCount + offSetMatrixA]; } if ((i - j <= b.m_SubDiagonalCount) && (j - i <= b.m_SuperDiagonalCount)) { value += scalar * b.m_Data[j - i + b.m_SuperDiagonalCount + i * k]; } c[i - j + superDiagonalCount + offsetMatrixC] = value; } } } break; case BLAS.MatrixTransposeState.Transpose: if (b.m_TransposeState == BLAS.MatrixTransposeState.NoTranspose) { int k = a.m_SubDiagonalCount + a.m_SuperDiagonalCount + 1; for (int j = 0; j < columnCount; j++) { int offSetMatrixB = j * (b.m_SubDiagonalCount + b.m_SuperDiagonalCount + 1); int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1); for (int i = Math.Max(0, j - superDiagonalCount); i <= Math.Min(rowCount - 1, j + subDiagonalCount); i++) { double value = 0.0; if ((i - j <= a.m_SubDiagonalCount) && (j - i <= a.m_SuperDiagonalCount)) { value += a.m_Data[j - i + a.m_SuperDiagonalCount + i * k]; } if ((i - j <= b.m_SubDiagonalCount) && (j - i <= b.m_SuperDiagonalCount)) { value += scalar * b.m_Data[i - j + b.m_SuperDiagonalCount + offSetMatrixB]; } c[i - j + superDiagonalCount + offsetMatrixC] = value; } } } else { int ka = a.m_SubDiagonalCount + a.m_SuperDiagonalCount + 1; int kb = b.m_SubDiagonalCount + b.m_SuperDiagonalCount + 1; for (int j = 0; j < columnCount; j++) { int offsetMatrixC = j * (subDiagonalCount + superDiagonalCount + 1); for (int i = Math.Max(0, j - superDiagonalCount); i <= Math.Min(rowCount - 1, j + subDiagonalCount); i++) { double value = 0.0; if ((i - j <= a.m_SubDiagonalCount) && (j - i <= a.m_SuperDiagonalCount)) { value += a.m_Data[j - i + a.m_SuperDiagonalCount + i * ka]; } if ((i - j <= b.m_SubDiagonalCount) && (j - i <= b.m_SuperDiagonalCount)) { value += scalar * b.m_Data[j - i + b.m_SuperDiagonalCount + i * kb]; } c[i - j + superDiagonalCount + offsetMatrixC] = value; } } } break; default: throw new InvalidOperationException(); } return new GeneralBandMatrix(rowCount, columnCount, subDiagonalCount, superDiagonalCount, c); }