18#ifndef HYPERCOMPLEX_POLYNOMIAL_HPP_
19#define HYPERCOMPLEX_POLYNOMIAL_HPP_
32 for (uint64_t i=1; i < mod; i++) {
33 if ((y*i) % mod == 1)
return i;
35 throw std::invalid_argument(
"non-invertible element");
40template <const u
int64_t MaxDeg>
43 int64_t* coefficients =
new int64_t[MaxDeg+1];
53 for (uint64_t i=0; i <= MaxDeg; i++) coefficients[i] = arr[i];
63 for (uint64_t i=0; i <= MaxDeg; i++) coefficients[i] = P[i];
72 for (uint64_t i=0; i <= MaxDeg; i++) coefficients[i] = 0;
76 delete[] coefficients;
85 if (
this == &P)
return *
this;
87 for (uint64_t i=0; i <= MaxDeg; i++) coefficients[i] = P[i];
96 int64_t temparr[MaxDeg+1];
97 for (uint64_t i=0; i <= MaxDeg; i++) temparr[i] = -coefficients[i];
107 assert(0 <= i && i <= MaxDeg);
108 return coefficients[i];
116 assert(0 <= i && i <= MaxDeg);
117 return coefficients[i];
126template <const u
int64_t MaxDeg>
131 for (uint64_t i=0; i <= MaxDeg; i++) {
132 if (P1[i] != P2[i])
return false;
142template <const u
int64_t MaxDeg>
155template <const u
int64_t MaxDeg>
157 for (uint64_t i=0; i < MaxDeg; i++) os << P[i] <<
",";
167template <const u
int64_t MaxDeg>
169 int64_t temparr[MaxDeg+1];
170 for (uint64_t i=0; i <= MaxDeg; i++) temparr[i] = P[i] * x;
180template <const u
int64_t MaxDeg>
185 int64_t temparr[MaxDeg+1];
186 for (uint64_t i=0; i <= MaxDeg; i++) temparr[i] = P1[i] + P2[i];
196template <const u
int64_t MaxDeg>
201 int64_t temparr[MaxDeg+1];
202 for (uint64_t i=0; i <= MaxDeg; i++) temparr[i] = P1[i] - P2[i];
212template <const u
int64_t MaxDeg>
217 int64_t prod[2*MaxDeg+1];
218 int64_t conv[MaxDeg+1];
219 for (uint64_t i=0; i < 2*MaxDeg+1; i++) prod[i] = 0;
220 for (uint64_t i=0; i <= MaxDeg; i++) conv[i] = 0;
221 for (uint64_t i=0; i <= MaxDeg; i++) {
222 for (uint64_t j=0; j <= MaxDeg; j++)
223 prod[i+j] += P1[i]*P2[j];
225 for (uint64_t i=0; i < 2*MaxDeg+1; i++) conv[i%(MaxDeg+1)] += prod[i];
235template <const u
int64_t MaxDeg>
237 int64_t temparr[MaxDeg+1];
238 for (uint64_t i=0; i <= MaxDeg; i++) {
239 temparr[i] = P[i] % x;
240 if (temparr[i] < 0) temparr[i] += x;
250template <const u
int64_t MaxDeg>
252 int64_t lower = -mod/2;
253 int64_t upper = mod/2;
254 for (uint64_t i = 0; i <= MaxDeg; i++) {
256 if ((*P)[i] < lower) (*P)[i] = (*P)[i] + mod;
257 if ((*P)[i] > upper) (*P)[i] = (*P)[i] - mod;
259 if ((*P)[i] <= lower) (*P)[i] = (*P)[i] + mod;
260 if ((*P)[i] > upper) (*P)[i] = (*P)[i] - mod;
270template <const u
int64_t MaxDeg>
290 uint64_t deg_r = MaxDeg+1;
291 for (uint64_t i=0; i <= MaxDeg; i++) temp[i] = P_[i];
293 uint64_t deg_newr = 0;
294 for (uint64_t i=0; i <= MaxDeg+1; i++) {
295 if (newr[i]) deg_newr = i;
299 while (deg_newr > 0) {
301 while (deg_r >= deg_newr) {
302 for (uint64_t i=0; i <= MaxDeg+1; i++) temp[i] = 0;
303 for (uint64_t i=0; i <= deg_newr; i++)
304 temp[i + deg_r - deg_newr] = newr[i];
305 q[deg_r - deg_newr] =
307 for (uint64_t i=0; i <= deg_r; i++)
308 temp[i] = (temp[i] * q[deg_r - deg_newr]) % mod;
310 for (uint64_t i=0; i <= deg_r; i++) r[i] = r[i] - temp[i];
321 newt = (t - (q * newt)) % mod;
325 for (uint64_t i=0; i <= MaxDeg+1; i++) q[i] = 0;
326 for (uint64_t i=0; i <= MaxDeg+1; i++) {
327 if (newr[i]) deg_newr = i;
329 for (uint64_t i=0; i <= MaxDeg+1; i++) {
335 assert(newr[MaxDeg+1] == 0);
340 for (uint64_t i=0; i <= MaxDeg; i++) inverse[i] = newt[i];
341 inverse = (multiplier * inverse) % mod;
346 assert((inverse * P) % mod == unity);
std::ostream & operator<<(std::ostream &os, const Polynomial< MaxDeg > &P)
Print operator.
Definition: Polynomial.hpp:156
int64_t RingInverse(const int64_t x, const int64_t mod)
Integer multiplicative inverse in a modular ring.
Definition: Polynomial.hpp:29
Polynomial< MaxDeg > operator-(const Polynomial< MaxDeg > &P1, const Polynomial< MaxDeg > &P2)
Subtraction operator.
Definition: Polynomial.hpp:197
Polynomial< MaxDeg > operator+(const Polynomial< MaxDeg > &P1, const Polynomial< MaxDeg > &P2)
Addition operator.
Definition: Polynomial.hpp:181
void CenteredLift(Polynomial< MaxDeg > *P, const int64_t mod)
Center-lift polynomial in a modular quotient ring.
Definition: Polynomial.hpp:251
bool operator!=(const Polynomial< MaxDeg > &P1, const Polynomial< MaxDeg > &P2)
Inequality operator.
Definition: Polynomial.hpp:143
bool operator==(const Polynomial< MaxDeg > &P1, const Polynomial< MaxDeg > &P2)
Equality operator.
Definition: Polynomial.hpp:127
Polynomial< MaxDeg > operator*(const int64_t x, const Polynomial< MaxDeg > &P)
Multiplication-by-scalar operator.
Definition: Polynomial.hpp:168
Polynomial< MaxDeg > operator%(const Polynomial< MaxDeg > &P, const int64_t x)
Coefficient reduction modulo a scalar.
Definition: Polynomial.hpp:236
Definition: Polynomial.hpp:41
Polynomial()
This is the default constructor.
Definition: Polynomial.hpp:71
Polynomial operator-() const
Create an additive inverse of a given polynomial.
Definition: Polynomial.hpp:95
Polynomial(const Polynomial &P)
This is the copy constructor.
Definition: Polynomial.hpp:62
Polynomial(const int64_t *arr)
This is the main constructor.
Definition: Polynomial.hpp:52
int64_t const & operator[](const uint64_t i) const
Access operator (const)
Definition: Polynomial.hpp:106
Polynomial & operator=(const Polynomial &P)
Assignment operator.
Definition: Polynomial.hpp:83
int64_t & operator[](const uint64_t i)
Access operator (non-const)
Definition: Polynomial.hpp:115