jpp/lab2/zad1/include/GF.hpp

132 lines
2.9 KiB
C++

#pragma once
#include <cinttypes>
#include <compare>
#include <sstream>
template<uint N>
class GF {
uint _value;
public:
std::strong_ordering operator<=>(const GF<N> &rhs) const = default;
GF<N> &operator=(const GF<N> &value) = default;
GF()
: _value(0u) {}
GF(const uint &value)
: _value(value % N) {}
GF<N> &operator=(const uint &value) {
this->_value = value % N;
return *this;
}
GF<N> operator+(const GF<N> &rhs) const {
return (this->_value + rhs._value) % N;
}
GF<N> operator+(const uint &rhs) const {
return this->operator+(GF<N>(rhs));
}
GF<N> operator-(const GF<N> &rhs) const {
if (this->_value < rhs._value) {
return N - (rhs._value - this->_value);
}
return (this->_value - rhs._value);
}
GF<N> operator-(const uint &rhs) const {
return this->operator-(GF<N>(rhs));
}
GF<N> operator*(const GF<N> &rhs) const {
return (this->_value * rhs._value) % N;
}
GF<N> operator*(const uint &rhs) const {
return this->operator*(GF<N>(rhs));
}
/*
* throws std::invalid_argument when dividing by 0
*/
GF<N> operator/(const GF<N> &rhs) const {
if (rhs._value == 0) {
throw std::invalid_argument("division by 0 is illegal");
}
GF<N> inverse = 1;
for (size_t i = 1; i < N; i++) {
if (rhs * i == GF<N>(1)) {
inverse = i;
break;
}
}
return GF<N>(*this * inverse);
}
GF<N> operator/(const uint &rhs) const {
return this->operator/(GF<N>(rhs));
}
GF<N> operator+=(const GF<N> &rhs) {
*this = *this + rhs;
return *this;
}
GF<N> operator+=(const uint &rhs) {
return this->operator+=(GF<N>(rhs));
}
GF<N> operator-=(const GF<N> &rhs) {
*this = *this - rhs;
return *this;
}
GF<N> operator-=(const uint &rhs) {
return this->operator-=(GF<N>(rhs));
}
GF<N> operator*=(const GF<N> &rhs) {
*this = *this * rhs;
return *this;
}
GF<N> operator*=(const uint &rhs) {
return this->operator*=(GF<N>(rhs));
}
GF<N> operator/=(const GF<N> &rhs) {
*this = *this / rhs;
return *this;
}
GF<N> operator/=(const uint &rhs) {
return this->operator/=(GF<N>(rhs));
}
friend std::ostream &operator<<(std::ostream &stream, const GF<N> &val) {
stream << "GF<" << N << ">(" << val._value << ")";
return stream;
}
friend std::istream &operator>>(std::istream &stream, GF<N> &val) {
stream >> val._value;
val._value %= N;
return stream;
}
/*
* returns the characteristic of this GF
*/
uint characteristic() const { return N; }
/*
* returns the value of this GF
*/
uint value() const { return _value; }
};