/// <summary>
        /// rv = lhs * rhs
        /// 自分自身(lhs,rhs)を変更しない。
        /// </summary>
        /// <returns>乗算結果。</returns>
        public static MatrixGF2 Mul(MatrixGF2 lhs, MatrixGF2 rhs)
        {
            if (lhs.Column != rhs.Row)
            {
                throw new ArgumentException("lhs.Column != rhs.Row");
            }

            int loopCount = lhs.Column;

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

            Parallel.For(0, rv.Row, r => {
                for (int c = 0; c < rv.Column; ++c)
                {
                    GF2 v = GF2.Zero;
                    for (int i = 0; i < loopCount; ++i)
                    {
                        v = GF2.Add(v, GF2.Mul(lhs.At(r, i), rhs.At(i, c)));
                    }
                    rv.Set(r, c, v);
                }
            });

            return(rv);
        }
 /// ■■行列の要素はrow majorで並んでいる。■■
 /// すなわち、1次元配列にシリアライズするとき、
 /// 0row目の全要素を詰め、1row目の全要素を詰め…という要領で詰める。
 /// <para/>numRow=3, numColumn=3の例。
 /// <para/>
 /// <para/>       column番号
 /// <para/>       0  1  2
 /// <para/>row番号0→ ┌a00 a01 a02┐
 /// <para/>row番号1→ │a10 a11 a12│
 /// <para/>row番号2→ └a20 a21 a22┘
 /// <para/>
 /// <para/> ↓
 /// <para/> m[] = { a00, a01, a02, a10, a11, a12, a20, a21, a22 }
 public MatrixGF2(int row, int column)
 {
     mRow = row;
     mCol = column;
     m    = new GF2[mRow * mCol];
     for (int i = 0; i < m.Length; ++i)
     {
         m[i] = GF2.Zero;
     }
 }
        /// ■■行列の要素はrow majorで並んでいる。■■
        /// すなわち、1次元配列にシリアライズするとき、
        /// 0row目の全要素を詰め、1row目の全要素を詰め…という要領で詰める。
        /// <para/>numRow=3, numColumn=3の例。
        /// <para/>
        /// <para/>       column番号
        /// <para/>       0  1  2
        /// <para/>row番号0→ ┌a00 a01 a02┐
        /// <para/>row番号1→ │a10 a11 a12│
        /// <para/>row番号2→ └a20 a21 a22┘
        /// <para/>
        /// <para/> ↓
        /// <para/> m[] = { a00, a01, a02, a10, a11, a12, a20, a21, a22 }
        public MatrixGF2(int numRow, int numColumn, GF2[] v)
        {
            mRow = numRow;
            mCol = numColumn;

            if (mRow * mCol != v.Length)
            {
                throw new ArgumentException("v.length and row * column mismatch");
            }

            m = new GF2[mRow * mCol];
            Array.Copy(v, m, m.Length);
        }
        /// <summary>
        /// toRow := toRow + fromRow
        /// 自分自身を変更する。
        /// </summary>
        private void AddRow(int fromRow, int toRow)
        {
            if (fromRow < 0 || mRow <= fromRow)
            {
                throw new ArgumentOutOfRangeException("fromRow");
            }
            if (toRow < 0 || mRow <= toRow)
            {
                throw new ArgumentOutOfRangeException("toRow");
            }

            for (int c = 0; c < mCol; ++c)
            {
                var v = GF2.Add(At(fromRow, c), At(toRow, c));
                Set(toRow, c, v);
            }
        }
 public void Set(int row, int column, GF2 v)
 {
     m[column + mCol * row] = v;
 }