/// <summary> /// C = A * B (where '*' denotes matrix multiplication) /// </summary> public static void MatrixMultiply(ManagedStorage <double> a, ManagedStorage <double> b, ManagedStorage <double> c, bool aShouldTranspose = false, bool bShouldTranspose = false) { int aRows = aShouldTranspose ? a.ColumnCount : a.RowCount; int aCols = aShouldTranspose ? a.RowCount : a.ColumnCount; int bRows = bShouldTranspose ? b.ColumnCount : b.RowCount; int bCols = bShouldTranspose ? b.RowCount : b.ColumnCount; int cRows = c.RowCount; int cCols = c.ColumnCount; if (aCols != bRows) { throw new Exception("A and B are not compatible sizes."); } if ((cRows != aRows) || (cCols != bCols)) { throw new Exception("C is incorrectly sized for output."); } int transposeA = aShouldTranspose ? (int)CBLAS_TRANSPOSE.CblasTrans : (int)CBLAS_TRANSPOSE.CblasNoTrans; int transposeB = bShouldTranspose ? (int)CBLAS_TRANSPOSE.CblasTrans : (int)CBLAS_TRANSPOSE.CblasNoTrans; fixed(double *p_a = &a.Array[a.ArrayStart]) { fixed(double *p_b = &b.Array[b.ArrayStart]) { fixed(double *p_c = &c.Array[c.ArrayStart]) { int status = cblas_dgemm((int)CBLAS_ORDER.CblasColMajor, transposeA, transposeB, aRows, bCols, aCols, 1.0, p_a, a.RowCount, p_b, b.RowCount, 0.0, p_c, c.RowCount); } } } }
public static void SortInPlace(ManagedStorage <double> a) { char order = 'I'; // 'D' fixed(double *p_a = &a.Array[a.ArrayStart]) { LAPACKE_dlasrt(order, a.Length, p_a); } }
public static double Dot(ManagedStorage <double> a, ManagedStorage <double> b) { fixed(double *p_a = &a.Array[a.ArrayStart]) { fixed(double *p_b = &b.Array[b.ArrayStart]) { return(cblas_ddot(a.Length, p_a, 1, p_b, 1)); } } }
/// <summary> /// Performs Eigenvalue decomposition. /// </summary> /// <param name="a"></param> /// <param name="eigenvectors"></param> /// <param name="eigenvalues"></param> public static void EigenvalueDecomposition(ManagedStorage <double> a, ManagedStorage <double> eigenvectors, ManagedStorage <double> eigenvalues) { int m = 0, info = 0; int n = a.RowCount; var aClone = a.Clone(); int[] isuppz = new int[2 * n]; char jobz = 'V'; char range = 'A'; char uplo = 'U'; double[] work = new double[1]; int lwork = -1, liwork = -1; int[] iwork = new int[1]; int lda = n; int ldz = n; int il, iu; double vl, vu, abstol; vl = vu = abstol = 0; il = iu = 0; fixed(double *p_a = &aClone.Array[aClone.ArrayStart]) { fixed(double *p_eigenvectors = &eigenvectors.Array[eigenvectors.ArrayStart]) { fixed(double *p_eigenvalues = &eigenvalues.Array[eigenvalues.ArrayStart]) { DSYEVR(ref jobz, ref range, ref uplo, ref n, p_a, ref lda, ref vl, ref vu, ref il, ref iu, ref abstol, ref m, p_eigenvalues, p_eigenvectors, ref ldz, isuppz, work, ref lwork, iwork, ref liwork, ref info); if (info != 0) { throw new Exception("Eigenvalue decomposition error."); } lwork = (int)work[0]; work = new double[lwork]; liwork = (int)iwork[0]; iwork = new int[liwork]; DSYEVR(ref jobz, ref range, ref uplo, ref n, p_a, ref lda, ref vl, ref vu, ref il, ref iu, ref abstol, ref m, p_eigenvalues, p_eigenvectors, ref ldz, isuppz, work, ref lwork, iwork, ref liwork, ref info); } } } }
/// <summary> /// Performs Cholesky decomposition of a matrix in place. /// </summary> /// <param name="matrix">The upper triangular part contains symmetric matrix on entry. /// Lower triangular part contains decomposition on exit.</param> /// <param name="positiveSemiDefinite">Whether matrix was positive semi-definite.</param> public static void CholeskyDecomposition(ManagedStorage <double> a, out bool positiveSemiDefinite) { if (a.RowCount != a.ColumnCount) { throw new ArgumentException("matrix must be square."); } int lda = a.ColumnCount; int info = -1; int n = a.ColumnCount; //subMatrixDimension; // to only transform sub-matrix char uplo = 'L'; fixed(double *p_a = &a.Array[a.ArrayStart]) { DPOTRF(ref uplo, ref n, p_a, ref lda, ref info); } positiveSemiDefinite = true; if (info != 0) { positiveSemiDefinite = false; } }
public static void SortInPlace(ManagedStorage<double> a) { char order = 'I'; // 'D' fixed (double* p_a = &a.Array[a.ArrayStart]) { LAPACKE_dlasrt(order, a.Length, p_a); } }
/// <summary> /// C = A * B (where '*' denotes matrix multiplication) /// </summary> public static void MatrixMultiply(ManagedStorage<double> a, ManagedStorage<double> b, ManagedStorage<double> c, bool aShouldTranspose = false, bool bShouldTranspose = false) { int aRows = aShouldTranspose ? a.ColumnCount : a.RowCount; int aCols = aShouldTranspose ? a.RowCount : a.ColumnCount; int bRows = bShouldTranspose ? b.ColumnCount : b.RowCount; int bCols = bShouldTranspose ? b.RowCount : b.ColumnCount; int cRows = c.RowCount; int cCols = c.ColumnCount; if (aCols != bRows) throw new Exception("A and B are not compatible sizes."); if ((cRows != aRows) || (cCols != bCols)) throw new Exception("C is incorrectly sized for output."); int transposeA = aShouldTranspose ? (int)CBLAS_TRANSPOSE.CblasTrans : (int)CBLAS_TRANSPOSE.CblasNoTrans; int transposeB = bShouldTranspose ? (int)CBLAS_TRANSPOSE.CblasTrans : (int)CBLAS_TRANSPOSE.CblasNoTrans; fixed (double* p_a = &a.Array[a.ArrayStart]) { fixed (double* p_b = &b.Array[b.ArrayStart]) { fixed (double* p_c = &c.Array[c.ArrayStart]) { int status = cblas_dgemm((int)CBLAS_ORDER.CblasColMajor, transposeA, transposeB, aRows, bCols, aCols, 1.0, p_a, a.RowCount, p_b, b.RowCount, 0.0, p_c, c.RowCount); } } } }
/// <summary> /// Performs Eigenvalue decomposition. /// </summary> /// <param name="a"></param> /// <param name="eigenvectors"></param> /// <param name="eigenvalues"></param> public static void EigenvalueDecomposition(ManagedStorage<double> a, ManagedStorage<double> eigenvectors, ManagedStorage<double> eigenvalues) { int m = 0, info = 0; int n = a.RowCount; var aClone = a.Clone(); int[] isuppz = new int[2 * n]; char jobz = 'V'; char range = 'A'; char uplo = 'U'; double[] work = new double[1]; int lwork = -1, liwork = -1; int[] iwork = new int[1]; int lda = n; int ldz = n; int il, iu; double vl, vu, abstol; vl = vu = abstol = 0; il = iu = 0; fixed (double* p_a = &aClone.Array[aClone.ArrayStart]) { fixed (double* p_eigenvectors = &eigenvectors.Array[eigenvectors.ArrayStart]) { fixed (double* p_eigenvalues = &eigenvalues.Array[eigenvalues.ArrayStart]) { DSYEVR(ref jobz, ref range, ref uplo, ref n, p_a, ref lda, ref vl, ref vu, ref il, ref iu, ref abstol, ref m, p_eigenvalues, p_eigenvectors, ref ldz, isuppz, work, ref lwork, iwork, ref liwork, ref info); if (info != 0) { throw new Exception("Eigenvalue decomposition error."); } lwork = (int)work[0]; work = new double[lwork]; liwork = (int)iwork[0]; iwork = new int[liwork]; DSYEVR(ref jobz, ref range, ref uplo, ref n, p_a, ref lda, ref vl, ref vu, ref il, ref iu, ref abstol, ref m, p_eigenvalues, p_eigenvectors, ref ldz, isuppz, work, ref lwork, iwork, ref liwork, ref info); } } } }
public static double Dot(ManagedStorage<double> a, ManagedStorage<double> b) { fixed (double* p_a = &a.Array[a.ArrayStart]) { fixed (double* p_b = &b.Array[b.ArrayStart]) { return cblas_ddot(a.Length, p_a, 1, p_b, 1); } } }
/// <summary> /// Performs Cholesky decomposition of a matrix in place. /// </summary> /// <param name="matrix">The upper triangular part contains symmetric matrix on entry. /// Lower triangular part contains decomposition on exit.</param> /// <param name="positiveSemiDefinite">Whether matrix was positive semi-definite.</param> public static void CholeskyDecomposition(ManagedStorage<double> a, out bool positiveSemiDefinite) { if (a.RowCount != a.ColumnCount) throw new ArgumentException("matrix must be square."); int lda = a.ColumnCount; int info = -1; int n = a.ColumnCount; //subMatrixDimension; // to only transform sub-matrix char uplo = 'L'; fixed (double* p_a = &a.Array[a.ArrayStart]) { DPOTRF(ref uplo, ref n, p_a, ref lda, ref info); } positiveSemiDefinite = true; if (info != 0) positiveSemiDefinite = false; }