public MatrixGF2 Subset(int startR, int startC, int numR, int numC) { if (startR < 0 || mRow <= startR) { throw new ArgumentOutOfRangeException("startR"); } if (startC < 0 || mCol <= startC) { throw new ArgumentOutOfRangeException("startC"); } if (numR < 0 || mRow < startR + numR) { throw new ArgumentOutOfRangeException("numR"); } if (numC < 0 || mCol < startC + numC) { throw new ArgumentOutOfRangeException("numC"); } var rv = new MatrixGF2(numR, numC); for (int r = 0; r < numR; ++r) { for (int c = 0; c < numC; ++c) { rv.Set(r, c, At(startR + r, startC + c)); } } return(rv); }
/// <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); }
/// <summary> /// 転置した行列を戻す。 /// 自分自身を変更しない。 /// </summary> /// <returns>Transposed Matrix</returns> public MatrixGF2 Transpose() { var rv = new MatrixGF2(mCol, mRow); for (int r = 0; r < mRow; ++r) { for (int c = 0; c < mCol; ++c) { rv.Set(c, r, At(r, c)); } } return(rv); }
/// <summary> /// 他の行列aと同じかどうか。 /// </summary> /// <returns>同じなら0。異なるときは0以外。</returns> public int CompareTo(MatrixGF2 a) { if (mRow != a.mRow || mCol != a.mCol) { // 異なる。 return(1); } int acc = 0; for (int r = 0; r < mRow; ++r) { for (int c = 0; c < mCol; ++c) { acc += At(r, c).Add(a.At(r, c)).Val; } } return(acc); }
/// <summary> /// 自分自身を変更しない /// </summary> /// <returns>逆行列</returns> public MatrixGF2 Inverse() { if (mRow != mCol) { throw new NotImplementedException(); } int n = mRow; // org := this var org = new MatrixGF2(n, n, m); // inv := 単位行列 var inv = new MatrixGF2(n, n); inv.SetIdentity(); // ピボットの候補 var pivotList = new List <int>(); for (int i = 0; i < n; ++i) { pivotList.Add(i); } for (int c = 0; c < n; ++c) { // c列の値が1の行を1つだけにする。 // c列が値1の行を探す。 int pivRow = -1; foreach (var r in pivotList) { if (GF2.One == org.At(r, c)) { pivRow = r; break; } } if (pivRow < 0) { // 逆行列が存在しない。 return(null); } pivotList.Remove(pivRow); // pivot以外の行のc列の値を0にする。 for (int r = 0; r < n; ++r) { if (r == pivRow) { continue; } if (org.At(r, c) == GF2.One) { org.AddRow(pivRow, r); inv.AddRow(pivRow, r); } } } // 各々の列は値1が1度だけ現れる。 // sが正方行列になるように行を入れ替える。 for (int c = 0; c < n; ++c) { // c列の値が1の行を探す。 int oneRow = -1; for (int r = 0; r < n; ++r) { if (org.At(r, c) == GF2.One) { oneRow = r; break; } } if (oneRow == c) { // 既にc列c行が1である。 continue; } // c行とoneRow行を入れ替えてc列c行を1にする。 org.SwapRow(oneRow, c); inv.SwapRow(oneRow, c); } return(inv); }
/// <summary> /// rv := this * a /// 自分自身を変更しない。 /// </summary> /// <returns>乗算結果。</returns> public MatrixGF2 Mul(MatrixGF2 a) { return(Mul(this, a)); }