This repository has been archived on 2025-04-04. You can view files and clone it, but cannot push or open issues or pull requests.
mathematical-algorithms-cpp/src/types.hpp
2025-03-31 17:03:07 +09:00

119 lines
No EOL
2.7 KiB
C++

#include <cmath>
#include <iostream>
using namespace std;
/**
* A generic function for computing the GCD
* @tparam R : this template variable should be a type for which all the necessary
* operations for Euclidean domains have been implemented
* @param a
* @param b
* @return
*/
template <typename R>
R gcd(R a, R b) {
if (b == 0)
return a;
R r = a % b;
while (r != 0) {
a = b;
b = r;
r = a % b;
}
return b;
}
/**
* Rational on R which is always normalized.
* @tparam R : a type for Euclidean domain
*/
template<typename R>
struct ratio {
R num;
R denom;
};
template<typename R>
ratio<R> &rational_of(R n) {
return ratio<R>(n, 1);
}
template<typename R>
ratio<R> &normalize(ratio<R> &n) {
const R gcd = gcd(n.num, n.denom);
n.num = n.num / gcd;
n.denom = n.denom / gcd;
return n;
}
template<typename R>
ratio<R> &operator+(const ratio<R> &l, const ratio<R> &r) {
return normalize(rational(l.num * r.denom + r.num * l.denom, l.denom * r.denom));
}
template<typename R>
ratio<R> &operator-(const ratio<R> &l, const ratio<R> &r) {
return normalize(rational(l.num * r.denom - r.num * l.denom, l.denom * r.denom));
}
template<typename R>
ratio<R> &operator*(const ratio<R> &l, const ratio<R> &r) {
return normalize(rational(l.num * r.num, l.denom * r.denom));
}
template<typename R>
ratio<R> &operator/(const ratio<R> &l, const ratio<R> &r) {
return normalize(rational(l.num * r.denom, r.denom * l.num));
}
template<typename R>
bool operator==(const ratio<R> &l, const ratio<R> &r) {
return l.num == r.num && l.denom == r.denom;
}
template<typename R>
bool operator!=(const ratio<R> &l, const ratio<R> &r) {
return l.num != r.num || l.denom != r.denom;
}
template <typename R>
std::ostream& operator<<(std::ostream& os, const ratio<R>& r) {
os << r.a << "/" << r.b;
return os;
}
/**
* Prime field where number is kept to be in range [0, p).
*/
template<unsigned int>
struct prime_field {
size_t number;
};
template<unsigned int p>
prime_field<p> &operator+(const prime_field<p> &l, const prime_field<p> &r) {
return prime_field((l.number + r.number) % p);
}
template<unsigned int p>
prime_field<p> &operator-(const prime_field<p> &l, const prime_field<p> &r) {
return prime_field((l.number - r.number) % p);
}
template<unsigned int p>
prime_field<p> &operator*(const prime_field<p> &l, const prime_field<p> &r) {
return prime_field((l.number * r.number) % p);
}
// TODO prime_field /
template<unsigned int p>
bool operator==(const prime_field<p> &l, const prime_field<p> &r) {
return l.number == r.number;
}
template<unsigned int p>
bool operator!=(const prime_field<p> &l, const prime_field<p> &r) {
return l.number != r.number;
}