/// <summary> /// Solves simultaneous linear equations. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="a"> [<c>a.Rank == 2 && a.Shape[0] == a.Shape[1]</c>] </param> /// <param name="b"> [<c>(b.Rank == 1 || b.Rank == 2) && b.Shape[0] == a.Shape[0]</c>] </param> /// <returns></returns> /// <exception cref="ShapeMismatchException"> /// <para> When <c>n := a.Shape[0]</c>, </para> /// <para> - If <c>b.Shape == {n}</c>, then <c>$ReturnValue.Shape == {n}</c>. </para> /// <para> /// - If <c>b.Shape == {n, p}</c>, then <c>$ReturnValue.Shape == {n, p}</c>. /// Each column of return value is the solution against corresponding column of b. /// </para> /// </exception> public static NdArray <T> Solve <T>(this INdArray <T> a, INdArray <T> b) { Guard.AssertShapeMatch(a.Rank == 2 && a.Shape[0] == a.Shape[1], "a.Rank == 2 && a.Shape[0] == a.Shape[1]"); if (b.Rank == 1 && b.Shape[0] == a.Shape[0]) { var(l, u, perms) = a.LUWithPermutationsLegacy(); var x = NdArray.CreateMutable(new T[b.Shape[0]]); SolveCore(l, u, perms, b, x); return(x.MoveToImmutable()); } if (b.Rank == 2 && b.Shape[0] == a.Shape[0]) { var(l, u, perms) = a.LUWithPermutationsLegacy(); var x = NdArray.CreateMutable(new T[b.Shape[0], b.Shape[1]]); var col = b.Shape[1]; for (var j = 0; j < col; ++j) { var bj = b[Range.Whole, new Index(j, false)]; var xj = x[Range.Whole, new Index(j, false)]; SolveCore(l, u, perms, bj, xj); } return(x.MoveToImmutable()); } Guard.ThrowShapeMismatch("(b.Rank == 1 || b.Rank == 2) && b.Shape[0] == a.Shape[0]"); throw new NotSupportedException(); }
/// <summary> /// Gets the identity matrix which has the specified dimension. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="n"></param> /// <returns></returns> public static NdArray <T> Identity <T>(int n) { var array = NdArray.CreateMutable(new T[n, n]); for (var i = 0; i < n; ++i) { array[i, i] = ValueTrait.One <T>(); } return(array.MoveToImmutable()); }
public void Execute() { // Creates with 1-D array and shape definition. var ndarray1 = NdArray.Create(new double[24], new int[] { 2, 3, 4 }); WriteLine(ndarray1); // Creates with multi-dimension array. var ndarray2 = NdArray.Create(new double[2, 3, 4]); WriteLine(ndarray2); // Basic NdArray is immutable. // If you need mutable NdArray, use `CreateMutable` instead of `Create`. var ndarray3 = NdArray.CreateMutable(new double[2, 3, 4]); WriteLine(ndarray3); // You can convert mutable <-> immutable NdArray with `ToImmutable`/`ToMutable`. // These methods create copy. var ndarray4 = ndarray3.ToImmutable(); WriteLine(ndarray4); var ndarray5 = ndarray1.ToMutable(); WriteLine(ndarray5); // You can also convert mutable -> immutable with `MoveTommutable`. // This method moves internal buffer, but does not create copy. // Please note this method destroys the source mutable NdArray. var ndarray6 = ndarray3.MoveToImmutable(); WriteLine(ndarray6); // If generic data type T has `0`/`1` value, you can use `Zeros`/`Ones`. var ndarray7 = NdArray.Zeros <double>(new int[] { 2, 3, 4 }); WriteLine(ndarray7); var ndarray8 = NdArray.Ones <double>(new int[] { 2, 3, 4 }); WriteLine(ndarray8); }
/// <summary> /// Calculates inverse matrix. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="ndArray"></param> /// <returns></returns> public static NdArray <T> Inverse <T>(this INdArray <T> ndArray) { Guard.AssertShapeMatch((bool)(ndArray.Rank == 2 & ndArray.Shape[0] == ndArray.Shape[1]), "ndArray.Rank == 2 & ndArray.Shape[0] == ndArray.Shape[1]"); var b = Identity <T>((int)ndArray.Shape[0]); var(l, u, perms) = NdLinAlg.LUWithPermutationsLegacy <T>(ndArray); var xx = NdArray.CreateMutable(new T[b.Shape[0], b.Shape[1]]); var x = xx.Entity; var row = b.Shape[0]; var col = b.Shape[1]; for (var j = 0; j < col; ++j) { var bj = b[Range.Whole, new Index(j, false)]; var xj = xx[Range.Whole, new Index(j, false)]; SolveCore(l, u, perms, bj, xj); } for (var k = perms.Count - 1; k >= 0; --k) { var(p, q) = perms[k]; for (var i = 0; i < row; ++i) { Span <int> idx1 = stackalloc int[] { i, p }; Span <int> idx2 = stackalloc int[] { i, q }; InternalUtils.Exchange(ref x[idx1], ref x[idx2]); } } for (var k = perms.Count - 1; k >= 0; --k) { var(p, q) = perms[k]; for (var i = 0; i < row; ++i) { Span <int> idx1 = stackalloc int[] { i, p }; Span <int> idx2 = stackalloc int[] { i, q }; InternalUtils.Exchange(ref x[idx1], ref x[idx2]); } } return(xx.MoveToImmutable()); }