Пример #1
0
        private static void SolveTriangleMatrixRL <T>(bool isUnit, T alpha, INdArray <T> a, MutableNdArray <T> b)
        {
            var(m, n) = (b.Shape[0], b.Shape[1]);

            /* reference Fortran
             * DO 260, J = N, 1, -1
             *  IF( ALPHA.NE.ONE )THEN
             *      DO 220, I = 1, M
             *          B( I, J ) = ALPHA*B( I, J )
             * 220               CONTINUE
             *  END IF
             *  DO 240, K = J + 1, N
             *      IF( A( K, J ).NE.ZERO )THEN
             *          DO 230, I = 1, M
             *              B( I, J ) = B( I, J ) - A( K, J )*B( I, K )
             * 230                   CONTINUE
             *      END IF
             * 240           CONTINUE
             *  IF( NOUNIT )THEN
             *      TEMP = ONE/A( J, J )
             *      DO 250, I = 1, M
             *         B( I, J ) = TEMP*B( I, J )
             * 250               CONTINUE
             *  END IF
             * 260       CONTINUE
             */
            for (var j = n - 1; j >= 0; --j)
            {
                if (ValueTrait.Equals(alpha, One <T>()))
                {
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(alpha, b[i, j]);
                    }
                }
                for (var k = j + 1; k < n; ++k)
                {
                    if (!ValueTrait.Equals(a[k, j], Zero <T>()))
                    {
                        for (var i = 0; i < m; ++i)
                        {
                            b[i, j] = Subtract(b[i, j], Multiply(a[k, j], b[i, k]));
                        }
                    }
                }
                if (!isUnit)
                {
                    var temp = Divide(One <T>(), a[j, j]);
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(temp, b[i, j]);
                    }
                }
            }
        }
Пример #2
0
        private static void SolveTriangleMatrixRU <T>(bool isUnit, T alpha, INdArray <T> a, MutableNdArray <T> b)
        {
            var(m, n) = (b.Shape[0], b.Shape[1]);

            /* reference Fortran
             * DO 210, J = 1, N
             *  IF( ALPHA.NE.ONE )THEN
             *      DO 170, I = 1, M
             *          B( I, J ) = ALPHA*B( I, J )
             * 170               CONTINUE
             *  END IF
             *  DO 190, K = 1, J - 1
             *      IF( A( K, J ).NE.ZERO )THEN
             *          DO 180, I = 1, M
             *              B( I, J ) = B( I, J ) - A( K, J )*B( I, K )
             * 180                   CONTINUE
             *      END IF
             * 190           CONTINUE
             *  IF( NOUNIT )THEN
             *      TEMP = ONE/A( J, J )
             *      DO 200, I = 1, M
             *          B( I, J ) = TEMP*B( I, J )
             * 200               CONTINUE
             *  END IF
             * 210       CONTINUE
             */
            for (var j = 0; j < n; ++j)
            {
                if (ValueTrait.Equals(alpha, One <T>()))
                {
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(alpha, b[i, j]);
                    }
                }
                for (var k = 0; k < j - 1; ++k)
                {
                    if (!ValueTrait.Equals(a[k, j], Zero <T>()))
                    {
                        for (var i = 0; i < m; ++i)
                        {
                            b[i, j] = Subtract(b[i, j], Multiply(a[k, j], b[i, k]));
                        }
                    }
                }
                if (!isUnit)
                {
                    var temp = Divide(One <T>(), a[j, j]);
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(temp, b[i, j]);
                    }
                }
            }
        }
Пример #3
0
        /// <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());
        }
Пример #4
0
        /// <summary>
        ///     Computes sum from all elements of the <paramref name="ndArray"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ndArray"></param>
        /// <returns></returns>
        public static T Sum <T>(this INdArray <T> ndArray)
        {
            var value = ValueTrait.Zero <T>();
            var len   = ndArray.Shape.TotalLength;

            for (var i = 0; i < len; ++i)
            {
                value = ValueTrait.Add(value, ndArray.GetItem(i));
            }
            return(value);
        }
Пример #5
0
        /// <summary>
        ///     Computes unbiased variance from all elements of the <paramref name="ndArray"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ndArray"></param>
        /// <returns></returns>
        public static T UnbiasedVar <T>(this INdArray <T> ndArray)
        {
            var value = ValueTrait.Zero <T>();
            var mean  = ndArray.Mean();
            var len   = ndArray.Shape.TotalLength;

            for (var i = 0; i < len; ++i)
            {
                var temp = ValueTrait.Subtract(ndArray.GetItem(i), mean);
                value = ValueTrait.Multiply(temp, temp);
            }
            return(ValueTrait.Divide(value, ValueTrait.FromLong <T>(len - 1)));
        }
Пример #6
0
        public static Vector <T> GetVector <T>()
            where T : unmanaged
        {
            Span <T> span = stackalloc T[Vector <T> .Count];
            var      x    = ValueTrait.UnaryNegate(ValueTrait.One <T>());

            for (var i = 0; i < Vector <T> .Count; ++i)
            {
                span[i] = x;
                x       = ValueTrait.Increment(x);
            }
            return(new Vector <T>(span));
        }
Пример #7
0
        /// <summary>
        ///     [Pure] Returns the 2-D norm of all elements of <paramref name="ndArray"/>.
        /// </summary>
        /// <param name="ndArray"></param>
        /// <returns></returns>
        public static T Norm2 <T>(this INdArray <T> ndArray)
        {
            var len = ndArray.Shape.TotalLength;

            Guard.AssertOperation(len > 0, "ndArray has no elements.");

            var norm = ValueTrait.Zero <T>();

            for (var i = 0; i < len; ++i)
            {
                var element = ndArray.GetItem(i);
                norm = ValueTrait.Add(norm, ValueTrait.Multiply(element, element));
            }

            return(NdMath.Sqrt(norm));
        }
Пример #8
0
        private static void SolveTriangleMatrixLU <T>(bool isUnit, T alpha, INdArray <T> a, MutableNdArray <T> b)
        {
            var(m, n) = (b.Shape[0], b.Shape[1]);

            /* reference Fortran
             * DO 60, J = 1, N
             *  IF( ALPHA.NE.ONE )THEN
             *      DO 30, I = 1, M
             *          B( I, J ) = ALPHA*B( I, J )
             * 30               CONTINUE
             *  END IF
             *  DO 50, K = M, 1, -1
             *      IF( B( K, J ).NE.ZERO )THEN
             *          IF( NOUNIT )
             * $                      B( K, J ) = B( K, J )/A( K, K )
             *          DO 40, I = 1, K - 1
             *              B( I, J ) = B( I, J ) - B( K, J )*A( I, K )
             * 40                   CONTINUE
             *      END IF
             * 50           CONTINUE
             * 60       CONTINUE
             */
            for (var j = 0; j < n; ++j)
            {
                if (!ValueTrait.Equals(alpha, One <T>()))
                {
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(alpha, b[i, j]);
                    }
                }
                for (var k = m - 1; k >= 0; --k)
                {
                    if (!ValueTrait.Equals(b[k, j], Zero <T>()))
                    {
                        if (!isUnit)
                        {
                            b[k, j] = Divide(b[k, j], a[k, k]);
                        }
                        for (var i = 0; i < k - 1; ++i)
                        {
                            b[i, j] = Subtract(b[i, j], Multiply(b[k, j], a[i, k]));
                        }
                    }
                }
            }
        }
Пример #9
0
        private static void SolveTriangleMatrixLL <T>(bool isUnit, T alpha, INdArray <T> a, MutableNdArray <T> b)
        {
            var(m, n) = (b.Shape[0], b.Shape[1]);

            /* reference Fortran
             * DO 100, J = 1, N
             *  IF( ALPHA.NE.ONE )THEN
             *      DO 70, I = 1, M
             *          B( I, J ) = ALPHA*B( I, J )
             * 70               CONTINUE
             *  END IF
             *  DO 90 K = 1, M
             *      IF( B( K, J ).NE.ZERO )THEN
             *          IF( NOUNIT )
             * $                      B( K, J ) = B( K, J )/A( K, K )
             *          DO 80, I = K + 1, M
             *              B( I, J ) = B( I, J ) - B( K, J )*A( I, K )
             * 80                   CONTINUE
             *      END IF
             * 90           CONTINUE
             * 100       CONTINUE
             */
            for (var j = 0; j < n; ++j)
            {
                if (!ValueTrait.Equals(alpha, One <T>()))
                {
                    for (var i = 0; i < m; ++i)
                    {
                        b[i, j] = Multiply(alpha, b[i, j]);
                    }
                }
                for (var k = 0; k < m; ++k)
                {
                    if (!ValueTrait.Equals(b[k, j], Zero <T>()))
                    {
                        if (!isUnit)
                        {
                            b[k, j] = Divide(b[k, j], b[k, k]);
                        }
                        for (var i = k; i < m; ++i)
                        {
                            b[i, j] = Subtract(b[i, j], Divide(b[k, j], a[i, k]));
                        }
                    }
                }
            }
        }
Пример #10
0
        /// <summary>
        ///     Returns the largest value of the <paramref name="ndArray"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ndArray"></param>
        /// <returns></returns>
        public static T Max <T>(this INdArray <T> ndArray)
        {
            var len = ndArray.Shape.TotalLength;

            Guard.AssertOperation(len > 0, "ndArray has no elements.");

            var max = ndArray.GetItem(0);

            for (var i = 1; i < len; ++i)
            {
                var current = ndArray.GetItem(i);
                if (ValueTrait.GreaterThan(current, max))
                {
                    max = current;
                }
            }
            return(max);
        }
Пример #11
0
        /// <summary>
        ///     Returns the index of the smallest value of the <paramref name="ndArray"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ndArray"></param>
        /// <returns></returns>
        public static IndexArray ArgMin <T>(this INdArray <T> ndArray)
        {
            var len = ndArray.Shape.TotalLength;

            Guard.AssertOperation(len > 0, "ndArray has no elements.");

            var argmin = 0;
            var min    = ndArray.GetItem(0);

            for (var i = 1; i < len; ++i)
            {
                var current = ndArray.GetItem(i);
                if (ValueTrait.LessThan(current, min))
                {
                    argmin = i;
                    min    = current;
                }
            }
            return(ndArray.ToShapedIndices(argmin));
        }
Пример #12
0
        // 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;
            }
        }
Пример #13
0
        /// <summary>
        /// Calculates dot product of the two specified sequences.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        public static T Dot <T>(ReadOnlyMemory <T> lhs, ReadOnlyMemory <T> rhs)
        {
            Guard.AssertArgument(lhs.Length == rhs.Length, "lhs.Length == rhs.Length");

            if (typeof(T) == typeof(byte))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <byte> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <byte> >(ref rhs)
                    );
                return(Unsafe.As <byte, T>(ref result));
            }
            if (typeof(T) == typeof(ushort))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <ushort> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <ushort> >(ref rhs)
                    );
                return(Unsafe.As <ushort, T>(ref result));
            }
            if (typeof(T) == typeof(uint))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <uint> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <uint> >(ref rhs)
                    );
                return(Unsafe.As <uint, T>(ref result));
            }
            if (typeof(T) == typeof(ulong))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <ulong> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <ulong> >(ref rhs)
                    );
                return(Unsafe.As <ulong, T>(ref result));
            }
            if (typeof(T) == typeof(sbyte))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <sbyte> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <sbyte> >(ref rhs)
                    );
                return(Unsafe.As <sbyte, T>(ref result));
            }
            if (typeof(T) == typeof(short))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <short> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <short> >(ref rhs)
                    );
                return(Unsafe.As <short, T>(ref result));
            }
            if (typeof(T) == typeof(int))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <int> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <int> >(ref rhs)
                    );
                return(Unsafe.As <int, T>(ref result));
            }
            if (typeof(T) == typeof(long))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <long> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <long> >(ref rhs)
                    );
                return(Unsafe.As <long, T>(ref result));
            }
            if (typeof(T) == typeof(float))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <float> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <float> >(ref rhs)
                    );
                return(Unsafe.As <float, T>(ref result));
            }
            if (typeof(T) == typeof(double))
            {
                var result = DotOptimized(
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <double> >(ref lhs),
                    Unsafe.As <ReadOnlyMemory <T>, ReadOnlyMemory <double> >(ref rhs)
                    );
                return(Unsafe.As <double, T>(ref result));
            }

            {
                var result = ValueTrait.Zero <T>();
                for (var i = 0; i < lhs.Length; ++i)
                {
                    result = ValueTrait.Add(result, ValueTrait.Multiply(lhs.Span[i], rhs.Span[i]));
                }
                return(result);
            }
        }
Пример #14
0
        /// <summary>
        /// Calculates dot product of the two specified sequences.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lhs"></param>
        /// <param name="rhs"></param>
        /// <returns></returns>
        private static T DotOptimized <T>(ReadOnlyMemory <T> lhs, ReadOnlyMemory <T> rhs)
            where T : unmanaged
        {
            var lhsVSpan = MemoryMarshal.Cast <T, Vector <T> >(lhs.Span);
            var rhsVSpan = MemoryMarshal.Cast <T, Vector <T> >(rhs.Span);
            var retval   = ValueTrait.Zero <T>();
            var i        = 0;

            for (var len = lhsVSpan.Length & ~0b1111; i < len; i += 16)
            {
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i], rhsVSpan[i]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x1], rhsVSpan[i + 0x1]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x2], rhsVSpan[i + 0x2]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x3], rhsVSpan[i + 0x3]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x4], rhsVSpan[i + 0x4]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x5], rhsVSpan[i + 0x5]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x6], rhsVSpan[i + 0x6]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x7], rhsVSpan[i + 0x7]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x8], rhsVSpan[i + 0x8]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x9], rhsVSpan[i + 0x9]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xA], rhsVSpan[i + 0xA]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xB], rhsVSpan[i + 0xB]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xC], rhsVSpan[i + 0xC]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xD], rhsVSpan[i + 0xD]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xE], rhsVSpan[i + 0xE]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0xF], rhsVSpan[i + 0xF]));
            }
            if (i < (lhsVSpan.Length & ~0b111))
            {
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i], rhsVSpan[i]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x1], rhsVSpan[i + 0x1]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x2], rhsVSpan[i + 0x2]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x3], rhsVSpan[i + 0x3]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x4], rhsVSpan[i + 0x4]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x5], rhsVSpan[i + 0x5]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x6], rhsVSpan[i + 0x6]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x7], rhsVSpan[i + 0x7]));
                i     += 8;
            }
            if (i < (lhsVSpan.Length & ~0b11))
            {
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i], rhsVSpan[i]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x1], rhsVSpan[i + 0x1]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x2], rhsVSpan[i + 0x2]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x3], rhsVSpan[i + 0x3]));
                i     += 4;
            }
            if (i < (lhsVSpan.Length & ~0b1))
            {
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i], rhsVSpan[i]));
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i + 0x1], rhsVSpan[i + 0x1]));
                i     += 2;
            }
            if (i < lhsVSpan.Length)
            {
                retval = ValueTrait.Add(retval, Vector.Dot(lhsVSpan[i], rhsVSpan[i]));
                ++i;
            }

            var lhsRemainSpan    = lhs.Span.Slice(Vector <T> .Count * i);
            var rhsRemainSpan    = rhs.Span.Slice(Vector <T> .Count * i);
            var resultRemainSpan = lhs.Span.Slice(Vector <T> .Count * i);

            for (var j = 0; j < resultRemainSpan.Length; ++j)
            {
                retval = ValueTrait.Add(retval, ValueTrait.Multiply(lhsRemainSpan[j], rhsRemainSpan[j]));
            }
            return(retval);
        }
Пример #15
0
 /// <summary>
 ///     Computes mean from all elements of the <paramref name="ndArray"/>.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="ndArray"></param>
 /// <returns></returns>
 public static T Mean <T>(this INdArray <T> ndArray)
 => ValueTrait.Divide(ndArray.Sum(), ValueTrait.FromLong <T>(ndArray.Shape.TotalLength));