// reference: // https://github.com/xianyi/OpenBLAS/blob/develop/reference/dlaswpf.f /// <summary> /// [dlaswp] Swaps rows on the matrix A. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="a"></param> /// <param name="colstart"></param> /// <param name="collength"></param> /// <param name="ipiv"></param> /// <remarks> The columns between <c>[colstart, colstart + collength)</c> </remarks> public static void SwapRows <T>(MutableNdArray <T> a, int colstart, int collength, ReadOnlySpan <int> ipiv) { Guard.AssertArgumentRange(0 <= colstart, "0 <= colstart"); Guard.AssertArgumentRange(colstart + collength < a.Shape[1], "colstart + collength < a.Shape[1]"); if (a is RawNdArray <T> xa) { using var alloc = new AllocationSlim <T>(collength); var tmp = alloc.Memory.Slice(0, collength); var c = a.Shape[1]; for (var i = 0; i < ipiv.Length; ++i) { if (i == ipiv[i]) { continue; } var row1 = xa.Entity.Buffer.Slice(c * ipiv[i] + colstart, collength); var row2 = xa.Entity.Buffer.Slice(c * i + colstart, collength); VectorOperation.Identity(row1, tmp); VectorOperation.Identity(row2, row1); VectorOperation.Identity(tmp, row2); } } else { for (var i = 0; i < ipiv.Length; ++i) { if (i == ipiv[i]) { continue; } for (var j = colstart; j < colstart + collength; ++j) { var tmp = a[i, j]; a[i, j] = a[ipiv[i], j]; a[ipiv[i], j] = tmp; } } } }
// reference: // https://github.com/xianyi/OpenBLAS/blob/develop/reference/dtrsmf.f /// <summary> /// [dtrsm] Solves one of the matrix equations: /// <list type="bullet"> /// <item> /// <term><c>(side, transa) = (Left, None)</c></term> /// <description><c>A * X = alpha * B</c></description> /// </item> /// <item> /// <term><c>(side, transa) = (Right, None)</c></term> /// <description><c>X * A = alpha * B</c></description> /// </item> /// </list> /// </summary> /// <typeparam name="T"></typeparam> /// <param name="side"></param> /// <param name="uplo"></param> /// <param name="diag"> <c>true</c> if <paramref name="a"/> is a unit triangular; otherwise, <c>false</c>. </param> /// <param name="alpha"></param> /// <param name="a"></param> /// <param name="b"></param> public static void SolveTriangleMatrix <T>(OperandSide side, TriangleKind uplo, bool diag, T alpha, INdArray <T> a, MutableNdArray <T> b) { if (ValueTrait.Equals(alpha, Zero <T>())) { VectorOperation.Identity(NdArray.Zeros <T>(b.Shape), b); return; } switch ((side, uplo)) { case (OperandSide.Left, TriangleKind.Upper): SolveTriangleMatrixLU(diag, alpha, a, b); break; case (OperandSide.Left, TriangleKind.Lower): SolveTriangleMatrixLL(diag, alpha, a, b); break; case (OperandSide.Right, TriangleKind.Upper): SolveTriangleMatrixRU(diag, alpha, a, b); break; case (OperandSide.Right, TriangleKind.Lower): SolveTriangleMatrixRL(diag, alpha, a, b); break; default: Guard.ThrowArgumentError("Invalid configs."); break; } }