본문 바로가기
Computer Science

[C++] class Modulo: 나머지환에서의 사칙연산을 구현해 보자

by invrtd.h 2022. 8. 4.

설명은 나중에 써야겠다.

template<unsigned int P, unsigned int PHI = P - 1>
class Modulo {
private:
    long long n;
    
public:
    Modulo() = default;
    constexpr Modulo(long long _n) : n(_n >= 0 ? _n % P : (P - (-_n % P)) % P) {}
    constexpr Modulo operator+(const Modulo& rhs) const {return Modulo((n + rhs.n) % P);}
    constexpr Modulo& operator+=(const Modulo& rhs) {*this = *this + rhs; return *this;}
    constexpr Modulo operator-() const {return n == 0 ? Modulo(0) : Modulo(P - n);}
    constexpr Modulo operator-(const Modulo& rhs) const {return *this + (-rhs);}
    constexpr Modulo& operator-=(const Modulo& rhs) {(*this) = (*this) - rhs; return *this;}
    constexpr Modulo operator*(const Modulo& rhs) const {return Modulo((n * rhs.n) % P);}
    constexpr Modulo& operator*=(const Modulo& rhs) {(*this) = (*this) * rhs; return *this;}
    
    constexpr Modulo pow(unsigned long long powered) const {
        if (powered <= 1) {
            return powered == 0 ? 1 : *this;
        }
        Modulo hold = pow(powered / 2);
        if (powered % 2 == 0) {
            return hold * hold;
        } else {
            return hold * hold * (*this);
        }
    }
    [[nodiscard]] constexpr Modulo inverse() const {return this->pow(PHI - 1);}
    constexpr Modulo operator/(const Modulo& rhs) const {
        if (rhs == 0) {throw std::logic_error("DIV BY ZERO");}
        return *this * rhs.inverse();
    }
    constexpr Modulo& operator/=(const Modulo& rhs) {*this = *this / rhs; return *this;}
    constexpr bool operator==(const Modulo& rhs) const {return n == rhs.n;}
    explicit operator int() const {return static_cast<int>(n);}
};

댓글