Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstdlib>
- //================ class Rational ===============//
- class Rational {
- private:
- int64_t p = 1;
- int64_t q = 1;
- void reduce();
- public:
- Rational() = default;
- Rational(int);
- Rational(int64_t num, int64_t dom = 1);
- Rational& operator=(const Rational& other) = default;
- ~Rational() = default;
- int64_t getNumerator() const;
- int64_t getDenominator() const;
- void SetNumerator(int64_t value);
- void SetDenominator(int64_t value);
- Rational operator-() const;
- Rational operator+() const ;
- Rational& operator++();
- Rational& operator--();
- Rational operator++(int);
- Rational operator--(int);
- Rational& operator+=(const Rational& rhs);
- Rational& operator-=(const Rational& rhs);
- Rational& operator*=(const Rational& rhs);
- Rational& operator/=(const Rational& rhs);
- };
- class MatrixWrongSizeError: std::exception {
- };
- class MatrixIndexError: std::exception {
- };
- class MatrixIsDegenerateError: std::exception {
- };
- class RationalDivisionByZero: std::exception {
- };
- template <typename T>
- T getZero() {
- return T(0);
- }
- //================ Rational ===============//
- int64_t GCD(int64_t x, int64_t y) {
- x = (x >= 0) ? x : -x;
- y = (y >= 0) ? y : -y;
- if (x == 0 || y == 1) {
- return y;
- }
- if (y == 0 || x == 1) {
- return x;
- }
- int64_t tmp;
- while (y) {
- tmp = x % y;
- x = y;
- y = tmp;
- }
- return x;
- }
- void Rational::reduce() {
- int64_t gcd = GCD(p, q);
- p /= gcd;
- q /= gcd;
- if (q < 0) {
- q *= -1;
- p *= -1;
- }
- }
- Rational::Rational(int64_t num, int64_t den){
- p = num;
- q = den;
- if (q < 0) {
- p *= -1;
- q *= -1;
- }
- reduce();
- }
- Rational::Rational(int num):Rational(static_cast<int64_t>(num)) {
- }
- int64_t Rational::getNumerator() const {
- return p;
- }
- int64_t Rational::getDenominator() const {
- return q;
- }
- void Rational::SetNumerator(int64_t value) {
- p = value;
- reduce();
- }
- void Rational::SetDenominator(int64_t value) {
- if (value == 0) {
- throw RationalDivisionByZero();
- }
- q = value;
- reduce();
- }
- Rational Rational::operator+() const {
- return *this;
- }
- Rational Rational::operator-() const {
- Rational res;
- res.p = -getNumerator();
- res.q = getDenominator();
- return res;
- }
- Rational& Rational::operator+=(const Rational& rhs) {
- p = p * rhs.q + q * rhs.p;
- q *= rhs.q;
- reduce();
- return *this;
- }
- Rational& Rational::operator-=(const Rational& rhs) {
- *this += (-rhs);
- return *this;
- }
- Rational& Rational::operator*=(const Rational& rhs) {
- p *= rhs.p;
- q *= rhs.q;
- reduce();
- return *this;
- }
- bool operator==(const Rational& lhs, const Rational& rhs) {
- return (lhs.getNumerator() == rhs.getNumerator() &&
- lhs.getDenominator() == rhs.getDenominator());
- }
- Rational& Rational::operator/=(const Rational& rhs) {
- if (rhs == 0) {
- throw RationalDivisionByZero();
- }
- p *= rhs.q;
- q *= rhs.p;
- reduce();
- return *this;
- }
- Rational operator+(const Rational& lhs, const Rational& rhs) {
- Rational result = lhs;
- result += rhs;
- return result;
- }
- Rational operator-(const Rational& lhs, const Rational& rhs) {
- Rational result = lhs;
- result -= rhs;
- return result;
- }
- Rational operator*(const Rational& lhs, const Rational& rhs) {
- Rational result = lhs;
- result *= rhs;
- return result;
- }
- Rational operator/(const Rational& lhs, const Rational& rhs) {
- Rational result = lhs;
- result /= rhs;
- return result;
- }
- //pre increment
- Rational& Rational::operator++() {
- *this += 1;
- return *this;
- }
- //pre decrement
- Rational& Rational::operator--() {
- *this -= 1;
- return *this;
- }
- //post increment
- Rational Rational::operator++(int) {
- Rational old_value = *this;
- *this += 1;
- return old_value;
- }
- //post decrement
- Rational Rational::operator--(int) {
- Rational old_value = *this;
- *this -= 1;
- return old_value;
- }
- bool operator<(const Rational& lhs, const Rational& rhs) {
- return (lhs.getNumerator() * rhs.getDenominator() <
- lhs.getDenominator() * rhs.getNumerator());
- }
- bool operator>(const Rational& lhs, const Rational& rhs) {
- return (rhs < lhs);
- }
- bool operator!=(const Rational& lhs, const Rational& rhs) {
- return !(lhs == rhs);
- }
- bool operator<=(const Rational& lhs, const Rational& rhs) {
- return !(lhs > rhs);
- }
- bool operator>=(const Rational& lhs, const Rational& rhs) {
- return !(lhs < rhs);
- }
- std::ostream& operator<<(std::ostream& os, const Rational& rational) {
- os << rational.getNumerator();
- if (rational.getDenominator() != 1) {
- os << '/' << rational.getDenominator();
- }
- return os;
- }
- std::istream& operator>>(std::istream& is, Rational& rational) {
- const int kMaxFractionSize = 6;
- char str[kMaxFractionSize];
- is >> str;
- char* end;
- rational.SetNumerator(strtoll(str, &end, 10));
- if (*end != 0) {
- ++end;
- rational.SetDenominator(strtoll(end, &end, 10));
- } else {
- rational.SetDenominator(1);
- }
- return is;
- }
- //=============== Matrix class ===============//
- template <class T>
- class Matrix {
- protected:
- T** array_;
- int rowsCnt_;
- int colsCnt_;
- void ArrayReallocation(int new_rows, int new_cols);
- public:
- Matrix();
- Matrix(int rows_cnt, int cols_cnt);
- Matrix(const Matrix& other);
- virtual Matrix& operator=(const Matrix& other);
- virtual ~Matrix();
- int getRowsNumber() const;
- int getColumnsNumber() const;
- Matrix& transpose();
- Matrix getTransposed() const;
- virtual Matrix operator-() const;
- virtual Matrix& operator+=(const Matrix& other);
- virtual Matrix& operator-=(const Matrix& other);
- virtual Matrix& operator*=(const Matrix& other);
- T& operator()(int i, int j);
- const T& operator()(int i, int j) const;
- template <class U>
- friend std::istream& operator>>(std::istream& is, Matrix<U>& other);
- friend Matrix<T> operator*(const Matrix<T>& mtr, T nmb) {
- Matrix<T> res = mtr;
- return res *= nmb;
- }
- friend Matrix<T> operator*(T nmb, const Matrix<T>& mtr) {
- return mtr * nmb;
- }
- };
- //================ Matrix ===============//
- template <class T>
- void FillZeroes(Matrix<T>& mtr) {
- T zero = getZero<T>();
- for (int i = 0; i < mtr.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr.getColumnsNumber(); ++j) {
- mtr(i, j) = zero;
- }
- }
- }
- template <class T>
- Matrix<T>::Matrix()
- : rowsCnt_(0)
- , colsCnt_(0)
- , array_(nullptr){
- }
- template <class T>
- Matrix<T>::Matrix(int rows_cnt, int cols_cnt)
- : rowsCnt_(rows_cnt)
- , colsCnt_(cols_cnt) {
- array_ = new T*[rows_cnt];
- for (int i = 0; i < rows_cnt; ++i) {
- array_[i] = new T[cols_cnt];
- }
- FillZeroes(*this);
- }
- template <class T>
- int Matrix<T>::getRowsNumber() const {
- return rowsCnt_;
- }
- template <class T>
- int Matrix<T>::getColumnsNumber() const {
- return colsCnt_;
- }
- template <class T>
- void Copy(const Matrix<T>& mtr_from, Matrix<T>& mtr_to) {
- for (int i = 0; i < mtr_from.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr_from.getColumnsNumber(); ++j) {
- mtr_to(i, j) = mtr_from(i, j);
- }
- }
- }
- template <class T>
- Matrix<T>::Matrix(const Matrix& other): Matrix(other.getRowsNumber(), other.getColumnsNumber()) {
- Copy(other, *this);
- }
- template <class T>
- Matrix<T>& Matrix<T>::operator=(const Matrix<T>& other) {
- if (&other == this) {
- return *this;
- }
- for (int i = 0; i < getRowsNumber(); ++i) {
- delete array_[i];
- }
- delete[] array_;
- array_ = new T*[other.getRowsNumber()];
- for (int i = 0; i < other.getRowsNumber(); ++i) {
- array_[i] = new T[other.getColumnsNumber()];
- }
- rowsCnt_ = other.getRowsNumber();
- colsCnt_ = other.getColumnsNumber();
- Copy(other, *this);
- return *this;
- }
- template <class T>
- Matrix<T>::~Matrix() {
- for (int i = 0; i < getRowsNumber(); ++i) {
- delete array_[i];
- }
- delete[] array_;
- }
- template <class T>
- bool InvalidIndex(int i, int j, const Matrix<T>& mtr) {
- return (i < 0 || j < 0 || i >= mtr.getRowsNumber() || j >= mtr.getColumnsNumber());
- }
- template <class T>
- T& Matrix<T>::operator()(int i, int j) {
- if (InvalidIndex(i, j, *this)) {
- throw MatrixIndexError();
- }
- return array_[i][j];
- }
- template <class T>
- const T& Matrix<T>::operator()(int i, int j) const {
- if (InvalidIndex(i, j, *this)) {
- throw MatrixIndexError();
- }
- return array_[i][j];
- }
- template <class T>
- void Swap(T& a, T& b) {
- T tmp = a;
- a = b;
- b = tmp;
- }
- template <class T>
- Matrix<T>& Matrix<T>::transpose() {
- if (getRowsNumber() == getColumnsNumber()) {
- for (int i = 0; i < getRowsNumber(); ++i) {
- for (int j = 0; j < getColumnsNumber(); ++j) {
- if (j > i) {
- Swap(array_[i][j], array_[j][i]);
- }
- }
- }
- } else {
- Matrix<T> old_mtr = *this;
- *this = Matrix(getColumnsNumber(), getRowsNumber());
- for (int i = 0; i < getRowsNumber(); ++i) {
- for (int j = 0; j < getColumnsNumber(); ++j) {
- array_[i][j] = old_mtr(j, i);
- }
- }
- }
- return *this;
- }
- template <class T>
- Matrix<T> Matrix<T>::getTransposed() const {
- Matrix<T> res = *this;
- res.transpose();
- return res;
- }
- template <class T>
- Matrix<T>& operator*=(Matrix<T>& mtr, T nmb) {
- for (int i = 0; i < mtr.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr.getColumnsNumber(); ++j) {
- mtr(i, j) *= nmb;
- }
- }
- return mtr;
- }
- template <class T, class U>
- Matrix<T>& operator/=(Matrix<T>& mtr, U nmb) {
- for (int i = 0; i < mtr.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr.getColumnsNumber(); ++j) {
- mtr(i, j) /= nmb;
- }
- }
- return mtr;
- }
- template <class T>
- bool InvalidSizeForAddition(const Matrix<T>& lhs, const Matrix<T>& rhs) {
- return (lhs.getRowsNumber() != rhs.getRowsNumber()) ||
- (lhs.getColumnsNumber() != rhs.getColumnsNumber());
- }
- template <class T>
- Matrix<T> Matrix<T>::operator-() const {
- Matrix<T> res = *this;
- for (int i = 0; i < getRowsNumber(); ++i) {
- for (int j = 0; j < getColumnsNumber(); ++j) {
- res(i, j) *= -1;
- }
- }
- return res;
- }
- template <class T>
- Matrix<T>& Matrix<T>::operator+=(const Matrix<T>& other) {
- if (InvalidSizeForAddition(*this, other)) {
- throw MatrixWrongSizeError();
- }
- for (int i = 0; i < getRowsNumber(); ++i) {
- for (int j = 0; j < getColumnsNumber(); ++j) {
- array_[i][j] += other(i, j);
- }
- }
- return *this;
- }
- template <class T>
- Matrix<T>& Matrix<T>::operator-=(const Matrix<T>& other) {
- *this += -other;
- return *this;
- }
- template <class T>
- bool InvalidSizeForMultiplication(const Matrix<T>& lhs, const Matrix<T>& rhs) {
- return (lhs.getColumnsNumber() != rhs.getRowsNumber());
- }
- template <class T>
- void Matrix<T>::ArrayReallocation(int new_rows, int new_cols) {
- for (int i = 0; i < getRowsNumber(); ++i) {
- delete array_[i];
- }
- delete[] array_;
- array_ = new T*[new_rows];
- for (int i = 0; i < new_rows; ++i) {
- array_[i] = new T[new_cols];
- }
- rowsCnt_ = new_rows;
- colsCnt_ = new_cols;
- FillZeroes(*this);
- }
- template <class T>
- Matrix<T>& Matrix<T>::operator*=(const Matrix<T>& other){
- if (InvalidSizeForMultiplication(*this, other)) {
- throw MatrixWrongSizeError();
- }
- bool isSameMatrix = false;
- if (this == &other) {
- isSameMatrix = true;
- }
- Matrix copy = *this;
- ArrayReallocation(getRowsNumber(), other.getColumnsNumber());
- for (int i = 0; i < copy.getRowsNumber(); ++i) {
- for (int j = 0; j < other.getColumnsNumber(); ++j) {
- for (int k = 0; k < copy.getColumnsNumber(); ++k) {
- array_[i][j] += copy(i, k) * (isSameMatrix ? copy(k, j) : other(k, j));
- }
- }
- }
- return *this;
- }
- template <class T>
- Matrix<T> operator*(const Matrix<T>& lhs, const Matrix<T>& rhs) {
- Matrix<T> res = lhs;
- return res *= rhs;
- }
- template <class T>
- Matrix<T> operator+(const Matrix<T>& lhs, const Matrix<T>& rhs) {
- Matrix<T> res = lhs;
- return res += rhs;
- }
- template <class T>
- Matrix<T> operator-(const Matrix<T>& lhs, const Matrix<T>& rhs) {
- Matrix<T> res = lhs;
- return res -= rhs;
- }
- template <class T>
- std::istream& operator>>(std::istream& is, Matrix<T>& mtr) {
- for (int i = 0; i < mtr.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr.getColumnsNumber(); ++j) {
- is >> mtr(i, j);
- }
- }
- return is;
- }
- template <class T>
- std::ostream& operator<<(std::ostream& os, const Matrix<T>& mtr) {
- for (int i = 0; i < mtr.getRowsNumber(); ++i) {
- for (int j = 0; j < mtr.getColumnsNumber(); ++j) {
- os << mtr(i, j) << ' ';
- }
- os << '\n';
- }
- return os;
- }
- //=============== SquareMatrix class ===============//
- template <class T>
- class SquareMatrix : public Matrix<T> {
- private:
- void MinorMatrix(const SquareMatrix<T>&, SquareMatrix<T>&, int, int) const ;
- T Determinant(const SquareMatrix& matrix) const ;
- void ArrayReallocation(int size);
- void Free();
- public:
- SquareMatrix();
- explicit SquareMatrix(int size);
- SquareMatrix(const SquareMatrix<T>& other);
- SquareMatrix<T> getInverse() const;
- SquareMatrix<T>& invert();
- int getSize() const;
- T getTrace() const;
- T getDeterminant() const;
- SquareMatrix<T> getTransposed() const;
- SquareMatrix<T>& transpose();
- T Cofactor(const SquareMatrix &matrix, int row_to_delete, int col_to_delete) const;
- friend SquareMatrix<T> operator*(const SquareMatrix<T>& matrix, T number) {
- SquareMatrix<T> res = matrix;
- res *= number;
- return res;
- }
- friend SquareMatrix<T> operator*(T number, const SquareMatrix<T>& matrix) {
- return matrix * number;
- }
- };
- //================ SquareMatrix ===============//
- template<typename T>
- SquareMatrix<T>::SquareMatrix(): Matrix<T>() {
- }
- template<typename T>
- SquareMatrix<T>::SquareMatrix(int size) : Matrix<T>(size, size) {
- }
- template<typename T>
- SquareMatrix<T>::SquareMatrix(const SquareMatrix<T>& other) : Matrix<T>(other) {
- }
- template <class T>
- int SquareMatrix<T>::getSize() const {
- return this->getRowsNumber();
- }
- template <class T>
- void SquareMatrix<T>::MinorMatrix(const SquareMatrix<T>& matrix, SquareMatrix<T>& new_matrix, int row_to_delete, int col_to_delete) const {
- int row_shift = 0;
- int col_shift = 0;
- for (int i = 0; i < new_matrix.getSize(); ++i) {
- if (i == row_to_delete) {
- row_shift = 1;
- }
- col_shift = 0;
- for (int j = 0; j < new_matrix.getSize(); ++j) {
- if (j == col_to_delete) {
- col_shift = 1;
- }
- new_matrix(i, j) = matrix(i + row_shift, j + col_shift);
- }
- }
- }
- template <class T>
- void SquareMatrix<T>::Free() {
- for(int i = 0; i < getSize(); i++) {
- delete[] this->array_[i];
- }
- delete[] this->array_;
- }
- template <class T>
- T SquareMatrix<T>::Determinant(const SquareMatrix& matrix) const {
- T det = getZero<T>();
- int sign = 1;
- if (matrix.getSize() == 1) {
- return matrix(0, 0);
- }
- if (matrix.getSize() == 2) {
- return matrix(0, 0) * matrix(1, 1) - matrix(1, 0) * matrix(0, 1);
- }
- SquareMatrix minor = SquareMatrix(matrix.getSize() - 1);
- T detMinor = Determinant(minor);
- for(int j = 0; j < matrix.getSize(); ++j) {
- MinorMatrix(matrix, minor, 0, j);
- det += sign * matrix(0, j) * detMinor;
- sign *= -1;
- }
- //minor.Free();
- return det;
- }
- template <class T>
- T SquareMatrix<T>::getDeterminant() const {
- return Determinant(*this);
- }
- template <class T>
- T SquareMatrix<T>::Cofactor(const SquareMatrix<T>& matrix, int row_to_delete, int col_to_delete) const {
- if (getSize() == 1) {
- return T(1);
- }
- SquareMatrix minor = SquareMatrix(matrix.getSize() - 1);
- MinorMatrix(matrix, minor, row_to_delete, col_to_delete);
- if ((row_to_delete + col_to_delete) % 2 == 1) {
- return -minor.getDeterminant();
- }
- return minor.getDeterminant();
- }
- template <class T>
- SquareMatrix<T> SquareMatrix<T>::getInverse() const {
- T det = getDeterminant();
- if (det == 0) {
- throw MatrixIsDegenerateError();
- }
- SquareMatrix transposed_mtr = this->getTransposed();
- SquareMatrix cofactor_mtr(getSize());
- for (int i = 0; i < getSize(); ++i) {
- for (int j = 0; j < getSize(); ++j) {
- cofactor_mtr(i, j) = Cofactor(transposed_mtr, i, j);
- }
- }
- return (cofactor_mtr /= det);
- }
- template <typename T>
- SquareMatrix<T>& SquareMatrix<T>::invert() {
- *this = getInverse();
- return *this;
- }
- template <class T>
- T SquareMatrix<T>::getTrace() const {
- T trace = getZero<T>();
- for (int i = 0; i < getSize(); ++i) {
- trace += this->array_[i][i];
- }
- return trace;
- }
- template <typename T>
- SquareMatrix<T> SquareMatrix<T>::getTransposed() const {
- SquareMatrix<T> res = *this;
- res.Matrix<T>::transpose();
- return res;
- }
- template <typename T>
- SquareMatrix<T>& SquareMatrix<T>::transpose() {
- *this = this->getTransposed();
- return *this;
- }
- template <class T, class U>
- SquareMatrix<T>& operator/=(SquareMatrix<T>& mtr, U nmb) {
- for (int i = 0; i < mtr.getSize(); ++i) {
- for (int j = 0; j < mtr.getSize(); ++j) {
- mtr(i, j) /= nmb;
- }
- }
- return mtr;
- }
- template <class T>
- void SquareMatrix<T>::ArrayReallocation(int size) {
- for (int i = 0; i < getSize(); ++i) {
- delete this->array_[i];
- }
- delete[] this->array_;
- this->array_ = new T*[size];
- for (int i = 0; i < size; ++i) {
- this->array_[i] = new T[size];
- }
- this->rowsCnt_ = this->colsCnt_ = size;
- FillZeroes(*this);
- }
- template <class T>
- SquareMatrix<T> operator*(const SquareMatrix<T>& lhs, const SquareMatrix<T>& rhs) {
- SquareMatrix<T> res = lhs;
- res *= rhs;
- return res;
- }
- template <class T>
- SquareMatrix<T> operator/(const SquareMatrix<T>& matrix, const T& number) {
- SquareMatrix<T> res = matrix;
- res /= number;
- return res;
- }
- template <class T>
- SquareMatrix<T> operator/(const T& number, const SquareMatrix<T>& matrix) {
- return matrix / number;
- }
- template <class T>
- Matrix<T> operator*(const Matrix<T>& mtr, const SquareMatrix<T>& square_mtr) {
- return mtr * dynamic_cast<const Matrix<T>&>(square_mtr);
- }
- template <class T>
- SquareMatrix<T> operator+(const SquareMatrix<T>& lhs, const SquareMatrix<T>& rhs) {
- SquareMatrix<T> res = lhs;
- res += rhs;
- return res;
- }
- template <class T>
- SquareMatrix<T> operator-(const SquareMatrix<T>& lhs, const SquareMatrix<T>& rhs) {
- SquareMatrix<T> res = lhs;
- res -= rhs;
- return res;
- }
- //=================== main() ===============//
- using namespace std;
- int main() {
- int m, n, p;
- Rational r;
- cin >> m >> n >> p >> r;
- Matrix<Rational> A(m, n);
- SquareMatrix<Rational> S(p);
- cin >> A >> S;
- try {
- cout << (A * S) * A.getTransposed() << endl;
- } catch (const MatrixWrongSizeError&) {
- cout << "A and S have not appropriate sizes for multiplication." << endl;
- }
- cout << (r * (S = S) * S).getSize() << endl;
- SquareMatrix<Rational> P(S);
- cout << (P * (S + S - 3 * P)).getDeterminant() << endl;
- const SquareMatrix<Rational>& rS = S;
- cout << rS.getSize() << ' ' << rS.getDeterminant() << ' ' << rS.getTrace() << endl;
- cout << (S = S) * (S + rS) << endl;
- cout << (S *= S) << endl;
- try {
- cout << rS.getInverse() << endl;
- cout << P.invert().getTransposed().getDeterminant() << endl;
- cout << P << endl;
- } catch (const MatrixIsDegenerateError&) {
- cout << "Cannot inverse matrix." << endl;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement