// copy = 행렬을 copy후 계산할것인가? // allowMulNeg = Switching이 홀수번 이루어지면 자동으로 첫 행에 * -1 public static Matrix GaussBot(Matrix m, bool copy, bool allowMulNeg) { bool found = false, neg = false; int r = 0, c = 0; Matrix ret = copy ? new Matrix(m) : m; while (r < m.rows && c < m.columns) { for (int i = r; i < m.rows; i++) { if (((Fraction)m.data[i, c]).GetValue() != 0) { if (i != r) { Switching(ret, i, r); Console.WriteLine("Switch " + i + ", " + r); neg = !neg; } found = true; break; } } if (!found) { c++; continue; } else { Fraction src = ret.data[r, c] as Fraction; for (int j = r + 1; j < m.rows; j++) { Fraction val = ret.data[j, c] as Fraction; if (val.GetValue() != 0) { Fraction frac = FractionOperators.Negative(FractionOperators.Divide(val, src)); ScalaAdd(ret, r, j, frac); Console.WriteLine("Add " + r + "*" + frac + " -> " + j); } } } r++; c++; } if (neg && allowMulNeg) { ScalaRow(ret, 0, -1); } return(ret); }
public static Vector Normalize(List <TokenType> parameters) { Vector v = parameters[0] as Vector; Vector.CheckNumberic(v); Fraction len = Length(parameters); if (v is Vec2 vec2) { return(new Vec2(FractionOperators.Divide(vec2.X, len), FractionOperators.Divide(vec2.Y, len))); } if (v is Vec3 vec3) { return(new Vec3(FractionOperators.Divide(vec3.X, len), FractionOperators.Divide(vec3.Y, len), FractionOperators.Divide(vec3.Z, len))); } return(null); }
public static Matrix GaussTop(Matrix m, bool copy) { int r = m.rows - 1, c = m.columns - 1; Matrix ret = copy ? new Matrix(m) : m; while (r >= 0 && c >= 0) { int swcnt = 0; for (int i = r; i >= 0; i--) { if (((Fraction)ret.data[i, c]).GetValue() != 0) { if (i != r) { Switching(ret, i, r); } swcnt++; break; } } if (swcnt == 0) { c--; continue; } else { Fraction src = ret.data[r, c] as Fraction; for (int j = r - 1; j >= 0; j--) { Fraction val = ret.data[j, c] as Fraction; if (val.GetValue() != 0) { ScalaAdd(ret, r, j, FractionOperators.Negative(FractionOperators.Divide(val, src))); } } } r--; c--; } return(ret); }
public static Matrix Inverse(List <TokenType> parameters) { Matrix m = parameters[0] as Matrix; Matrix.CheckNumbericMatrix(m); Matrix.CheckSquareMatrix(m); Matrix mat = Matrix.CreateUnsafeMatrix(m.rows, m.columns * 2); for (int r = 0; r < m.rows; r++) { for (int c = 0; c < m.columns; c++) { mat.data[r, c] = m.data[r, c]; } for (int c = m.columns; c < m.columns * 2; c++) { if (c == r + m.columns) { mat.data[r, c] = new Fraction(1); } else { mat.data[r, c] = new Fraction(0); } } } GaussBot(mat, false, false); Fraction det = 1; for (int i = 0; i < mat.rows; i++) { det = FractionOperators.Multiply(det, mat.data[i, i]); } if (det.GetValue() == 0) { throw new ExprCoreException("행렬식이 0인 행렬은 inverse를 구할 수 없습니다."); } for (int i = mat.rows - 1; i >= 0; i--) { for (int j = i - 1; j >= 0; j--) { ScalaAdd(mat, i, j, FractionOperators.Negative(FractionOperators.Divide(mat.data[j, i], mat.data[i, i]))); } ScalaRow(mat, i, FractionOperators.Divide(new Fraction(1), mat.data[i, i])); } Matrix ret = Matrix.CreateUnsafeMatrix(m.rows, m.columns); for (int r = 0; r < m.rows; r++) { for (int c = 0; c < m.columns; c++) { ret.data[r, c] = mat.data[r, m.rows + c]; } } return(ret); }