Commit
This commit is contained in:
parent
3c39a7e58f
commit
ca7e3db1b1
4 changed files with 267 additions and 77 deletions
|
|
@ -10,4 +10,4 @@ add_compile_options(-Wall -Wextra -Wpedantic -O2 -funroll-loops)
|
||||||
|
|
||||||
add_executable(karatsuba src/karatsuba.cpp)
|
add_executable(karatsuba src/karatsuba.cpp)
|
||||||
add_executable(pseudorandom src/pseudorandom.cpp)
|
add_executable(pseudorandom src/pseudorandom.cpp)
|
||||||
add_executable(types src/types.cpp)
|
add_executable(multivar src/multivar.cpp)
|
||||||
|
|
|
||||||
147
src/multivar.cpp
Normal file
147
src/multivar.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <version>
|
||||||
|
|
||||||
|
#include "types.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constraint: degrees should have the same size across the board
|
||||||
|
*/
|
||||||
|
template<typename R>
|
||||||
|
struct monomial {
|
||||||
|
R coefficient;
|
||||||
|
vector<size_t> degrees;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const monomial<R>& r) {
|
||||||
|
os << r.coefficient;
|
||||||
|
for (size_t i = 0; i < r.degrees.size(); i++) {
|
||||||
|
os << " " << "X_" << i << "^" << r.degrees[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename R>
|
||||||
|
int lexi_compare(const monomial<R> &lhs, const monomial<R> &rhs) {
|
||||||
|
for (int i = 0; i < lhs.degrees.size(); i++) {
|
||||||
|
if (lhs.degrees[i] > rhs.degrees[i]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lhs.degrees[i] < rhs.degrees[i]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// All degree terms are the same
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ordered according to lexicographic order
|
||||||
|
* @tparam R ring
|
||||||
|
*/
|
||||||
|
template<typename R>
|
||||||
|
struct multipoly {
|
||||||
|
list<monomial<R>> monomials;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const multipoly<R>& poly) {
|
||||||
|
if (poly.monomials.empty()) {
|
||||||
|
os << "0";
|
||||||
|
} else {
|
||||||
|
auto ite = poly.monomials.begin();
|
||||||
|
os << *ite;
|
||||||
|
++ite;
|
||||||
|
for (; ite != poly.monomials.end(); ++ite) {
|
||||||
|
os << " + " << *ite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
multipoly<R> &add_monomial(multipoly<R> &poly, const monomial<R> &monomial) {
|
||||||
|
auto ite = poly.monomials.begin();
|
||||||
|
for (; ite != poly.monomials.end(); ++ite) {
|
||||||
|
int cmp = lexi_compare(monomial, *ite);
|
||||||
|
if (cmp < 0) {
|
||||||
|
poly.monomials.insert(ite, monomial);
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
if (cmp == 0) {
|
||||||
|
ite->coefficient = ite->coefficient + monomial.coefficient;
|
||||||
|
if (ite->coefficient == 0) {
|
||||||
|
poly.monomials.erase(ite);
|
||||||
|
}
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail to insert before the very back
|
||||||
|
poly.monomials.insert(ite, monomial);
|
||||||
|
return poly;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
multipoly<R> operator+(const multipoly<R> &lhs, const multipoly<R> &rhs) {
|
||||||
|
auto result = lhs;
|
||||||
|
for (auto &rhs_mono : rhs.monomials) {
|
||||||
|
add_monomial(result, rhs_mono);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
multipoly<R> operator-(const multipoly<R> &lhs, const multipoly<R> &rhs) {
|
||||||
|
auto result = lhs;
|
||||||
|
for (auto &rhs_mono : rhs.monomials) {
|
||||||
|
auto negate_rhs = rhs_mono;
|
||||||
|
negate_rhs.coefficient = -negate_rhs.coefficient;
|
||||||
|
add_monomial(result, negate_rhs);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
multipoly<R> operator*(const multipoly<R> &lhs, const multipoly<R> &rhs) {
|
||||||
|
auto result = lhs;
|
||||||
|
// TODO Implement multiplication
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename R>
|
||||||
|
bool is_zero(multipoly<R> &poly) {
|
||||||
|
return poly.monomials.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
auto m1 = monomial{2, vector<size_t>{3, 4}};
|
||||||
|
auto m2 = monomial{2, vector<size_t>{4, 2}};
|
||||||
|
auto m3 = monomial{3, vector<size_t>{3, 2}};
|
||||||
|
cout << "m1, m2, m3: " << m1 << ", " << m2 << ", " << m3 << endl;
|
||||||
|
cout << "compare m1, m2: " << lexi_compare(m1, m2) << endl;
|
||||||
|
cout << "compare m1, m3: " << lexi_compare(m1, m3) << endl;
|
||||||
|
cout << "compare m1, m1: " << lexi_compare(m1, m1) << endl;
|
||||||
|
|
||||||
|
cout << endl;
|
||||||
|
auto poly = multipoly<int>();
|
||||||
|
cout << "poly - step 0: " << poly << endl;
|
||||||
|
add_monomial(poly, m1);
|
||||||
|
cout << "poly - step 1: " << poly << endl;
|
||||||
|
add_monomial(poly, m2);
|
||||||
|
cout << "poly - step 2: " << poly << endl;
|
||||||
|
add_monomial(poly, m3);
|
||||||
|
cout << "poly - step 3: " << poly << endl;
|
||||||
|
add_monomial(poly, m1);
|
||||||
|
cout << "poly - step 4: " << poly << endl;
|
||||||
|
|
||||||
|
cout << "poly + poly: " << poly + poly << endl;
|
||||||
|
auto sub = poly - poly;
|
||||||
|
cout << "poly - poly: " << sub << endl;
|
||||||
|
cout << "poly - poly is zero: " << is_zero(sub) << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* Until next time, let's boilerplate later
|
|
||||||
*/
|
|
||||||
#include <cmath>
|
|
||||||
#include <iostream>
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
struct rational {
|
|
||||||
R num;
|
|
||||||
R denom;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
rational<R> operator+(rational<R> &l, rational<R> &r) {
|
|
||||||
return rational(l.num * r.denom + r.num * l.denom, l.denom * r.denom);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
rational<R> operator-(rational<R> &l, rational<R> &r) {
|
|
||||||
return rational(l.num * r.denom - r.num * l.denom, l.denom * r.denom);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
rational<R> operator*(rational<R> &l, rational<R> &r) {
|
|
||||||
return rational(l.num * r.num, l.denom * r.denom);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
rational<R> operator/(rational<R> &l, rational<R> &r) {
|
|
||||||
return rational(l.num * r.denom, r.denom * l.num);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Take care of normalization
|
|
||||||
template<typename R>
|
|
||||||
bool operator==(rational<R> &l, rational<R> &r) {
|
|
||||||
return l.num == r.num && l.denom == r.denom;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename R>
|
|
||||||
bool operator!=(rational<R> &l, rational<R> &r) {
|
|
||||||
return l.num != r.num || l.denom != r.denom;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
template<typename R>
|
|
||||||
ostream operator<< (ostream &os, rational<R> &r) {
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
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 /, ==, !=
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
cout << "Hello World!" << endl;
|
|
||||||
}
|
|
||||||
119
src/types.hpp
Normal file
119
src/types.hpp
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
Reference in a new issue