132 lines
2.9 KiB
C++
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; }
|
|
};
|