Beispiel #1
0
        /// <summary>
        /// 2つの行列を上側、下側として連結した1個の行列を戻す。
        /// </summary>
        /// <param name="top">上側の行列</param>
        /// <param name="bottom">下側の行列</param>
        /// <returns>[top;bottom]</returns>
        public static WWMatrix JoinV(WWMatrix top, WWMatrix bottom)
        {
            if (top.Column != bottom.Column)
            {
                throw new ArgumentException("top.column != bottom.column");
            }

            var r = new WWMatrix(top.Row + bottom.Row, top.Column);

            for (int y = 0; y < top.Row; ++y)
            {
                for (int x = 0; x < top.Column; ++x)
                {
                    r.Set(y, x, top.At(y, x));
                }
            }
            for (int y = 0; y < bottom.Row; ++y)
            {
                for (int x = 0; x < bottom.Column; ++x)
                {
                    r.Set(top.Row + y, x, bottom.At(y, x));
                }
            }

            return(r);
        }
Beispiel #2
0
        /// <summary>
        /// 2つの行列を左側右側として連結した1個の行列を戻す。
        /// </summary>
        /// <param name="left">左側の行列</param>
        /// <param name="right">右側の行列</param>
        /// <returns>[left right]</returns>
        public static WWMatrix JoinH(WWMatrix left, WWMatrix right)
        {
            if (left.Row != right.Row)
            {
                throw new ArgumentException("left.Row != right.Row");
            }

            var r = new WWMatrix(left.Row, left.Column + right.Column);

            for (int y = 0; y < left.Row; ++y)
            {
                for (int x = 0; x < left.Column; ++x)
                {
                    r.Set(y, x, left.At(y, x));
                }
            }
            for (int y = 0; y < right.Row; ++y)
            {
                for (int x = 0; x < right.Column; ++x)
                {
                    r.Set(y, left.Column + x, right.At(y, x));
                }
            }

            return(r);
        }
Beispiel #3
0
        public static WWMatrix Mul(WWMatrix lhs, WWMatrix rhs)
        {
            if (lhs.Column != rhs.Row)
            {
                throw new ArgumentException("lhs.Column != rhs.Row");
            }

            int loopCount = lhs.Column;

            var rv = new WWMatrix(lhs.Row, rhs.Column);

            for (int r = 0; r < rv.Row; ++r)
            {
                for (int c = 0; c < rv.Column; ++c)
                {
                    double v = 0;
                    for (int i = 0; i < loopCount; ++i)
                    {
                        v += lhs.At(r, i) * rhs.At(i, c);
                    }
                    rv.Set(r, c, v);
                }
            }

            return(rv);
        }
Beispiel #4
0
        public static double[] Transform(double[] from)
        {
            if (!IsPowerOf2(from.Length))
            {
                throw new ArgumentException("from length is not power of 2");
            }

            int L = from.Length;

            // Lは2のN乗。
            int N = 0;

            for (int i = L; 1 < i; i /= 2)
            {
                ++N;
            }

            var m = new WWMatrix(L, N + 1);

            for (int r = 0; r < L; ++r)
            {
                m.Set(r, 0, from[r]);
            }

            for (int c = 0; c < N; ++c)
            {
                for (int r = 0; r < L / 2; ++r)
                {
                    m.Set(r, c + 1, m.At(r * 2, c) + m.At(r * 2 + 1, c));
                }
                for (int r = 0; r < L / 2; ++r)
                {
                    m.Set(r + L / 2, c + 1, m.At(r * 2, c) - m.At(r * 2 + 1, c));
                }
            }

            var rv = new double[L];

            for (int r = 0; r < L; ++r)
            {
                rv[r] = m.At(r, N);
            }

            return(rv);
        }
        public WWMatrix ToMatrix()
        {
            WWMatrix rv = new WWMatrix(mRow, mCol);

            for (int r = 0; r < mRow; ++r)
            {
                for (int c = 0; c < mCol; ++c)
                {
                    rv.Set(r, c, At(r, c).Val);
                }
            }

            return(rv);
        }
Beispiel #6
0
        /// <summary>
        /// 転置した行列を作って戻す。
        /// 自分自身を変更しない。
        /// </summary>
        /// <returns>転置した行列。</returns>
        public WWMatrix Transpose()
        {
            var t = new WWMatrix(mCol, mRow);

            for (int y = 0; y < mRow; ++y)
            {
                for (int x = 0; x < mCol; ++x)
                {
                    t.Set(x, y, At(y, x));
                }
            }

            return(t);
        }
Beispiel #7
0
        /// <summary>
        /// https://en.wikipedia.org/wiki/Crout_matrix_decomposition
        /// </summary>
        public static ResultEnum LUdecompose(WWMatrix inA, out WWMatrix outL, out WWMatrix outU, double epsilon = 1.0e-7)
        {
            if (inA.Row < 2 || inA.Row != inA.Column)
            {
                outL = new WWMatrix(0, 0);
                outU = new WWMatrix(0, 0);
                return(ResultEnum.UnsupportedMatrixShape);
            }

            int N = inA.Row;

            outL = new WWMatrix(N, N);
            outU = new WWMatrix(N, N);

            outU.SetIdentity();

            for (int x = 0; x < N; ++x)
            {
                for (int y = x; y < N; ++y)
                {
                    double sum = 0;
                    for (int k = 0; k < x; ++k)
                    {
                        sum += outL.At(y, k) * outU.At(k, x);
                    }
                    outL.Set(y, x, inA.At(y, x) - sum);
                }

                for (int y = x; y < N; ++y)
                {
                    double sum = 0;
                    for (int k = 0; k < x; ++k)
                    {
                        sum += outL.At(x, k) * outU.At(k, y);
                    }
                    if (WWMathUtil.IsAlmostZero(outL.At(x, x), epsilon))
                    {
                        return(ResultEnum.FailedToChoosePivot);
                    }

                    outU.Set(x, y, (inA.At(x, y) - sum) / outL.At(x, x));
                }
            }

            return(ResultEnum.Success);
        }
Beispiel #8
0
        /// <summary>
        /// https://www.student.cs.uwaterloo.ca/~cs370/notes/LUExample2.pdf
        /// </summary>
        public static ResultEnum LUdecompose2(WWMatrix inA, out WWMatrix outL, out WWMatrix outP, out WWMatrix outU, double epsilon = 1.0e-7)
        {
            if (inA.Row < 2 || inA.Row != inA.Column)
            {
                outP = new WWMatrix(0, 0);
                outL = new WWMatrix(0, 0);
                outU = new WWMatrix(0, 0);
                return(ResultEnum.UnsupportedMatrixShape);
            }

            int N = inA.Row;

            outP = new WWMatrix(N, N).SetIdentity();
            outL = new WWMatrix(N, N).SetIdentity();
            outU = new WWMatrix(N, N);

            outU = inA.DeepCopy();

            var PA = new WWMatrix(N, N);

            // Lの0行目は [1 0 0 ... 0]

            for (int c = 0; c < N - 1; ++c)
            {
                // c個目のピボットを選択する。
                // Uのc列を比較し、絶対値が最大のものを選ぶ。
                // Pのc行目が決定する。
                int maxRow = c;
                {
                    double maxAbs = 0;
                    for (int y = c; y < N; ++y)
                    {
                        if (maxAbs < Math.Abs(outU.At(y, c)))
                        {
                            maxAbs = Math.Abs(outU.At(y, c));
                            maxRow = y;
                        }
                    }
                }
                // ピボットは、maxRow行c列。

                outU.ExchangeRows(c, maxRow);
                outP.ExchangeRows(c, maxRow);

                outL.ExchangeRows(c, maxRow);
                outL.ExchangeCols(c, maxRow);

                // 並び替えによりuccがピボットになった。
                double ucc = outU.At(c, c);
                if (WWMathUtil.IsAlmostZero(ucc, epsilon))
                {
                    return(ResultEnum.FailedToChoosePivot);
                }

                for (int k = c + 1; k < N; ++k)
                {
                    // Uのk列目の計算。
                    // Uのk列目を0にするために、1列目を何倍して足すか。
                    double ukc = outU.At(k, c);

                    double ratio = ukc / ucc;
                    for (int x = 0; x < N; ++x)
                    {
                        double ucx = outU.At(c, x);
                        double ukx = outU.At(k, x);
                        outU.Set(k, x, ukx - ratio * ucx);
                    }

                    // Lのk行c列 = ratio。
                    outL.Set(k, c, ratio);
                }
            }

            return(ResultEnum.Success);
        }