-
Notifications
You must be signed in to change notification settings - Fork 0
/
dense_univariate_integer_poly.hpp
157 lines (151 loc) · 5.52 KB
/
dense_univariate_integer_poly.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#ifndef __DENSE_UNIVARIATE_INTEGER_POLY_HPP_
#define __DENSE_UNIVARIATE_INTEGER_POLY_HPP_
/*****************************************************************************\
* This file is part of DynGB. *
* *
* DynGB is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 2 of the License, or *
* (at your option) any later version. *
* *
* DynGB is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
\*****************************************************************************/
#include <iostream>
#include "system_constants.hpp"
using std::ostream;
/**
@ingroup polygroup
@class Dense_Univariate_Integer_Polynomial
@author John Perry
@date 2016
@brief quick-’n-dirty Dense_Univariate integer polynomial class
@warning You must have @c deg smaller than @c size,
as @c deg indexes the monomial of largest degree,
which can be at most @c size - 1.
*/
class Dense_Univariate_Integer_Polynomial {
public:
/** @name Construction */
///@{
/** @brief construct with the number of expected terms */
explicit Dense_Univariate_Integer_Polynomial(DEG_TYPE);
/** @brief copy constructor */
Dense_Univariate_Integer_Polynomial(
const Dense_Univariate_Integer_Polynomial &
);
/** @brief from serialized data */
Dense_Univariate_Integer_Polynomial(DEG_TYPE, int64_t *);
///@}
/** @name Destruction */
///@{
~Dense_Univariate_Integer_Polynomial() { delete [] coeffs; }
///@}
/** @name Modification */
///@{
/**
@brief expand to allow for higher-degree monomials
@details Do this at the beginning of any computation that
could expand the size of the polynomial.
*/
void expand_poly(DEG_TYPE);
/** @brief set the coefficient of @f$x^k@f$ to @f$\frac{a}{b}@f$ */
void set_coefficient(DEG_TYPE k, MPZCOEF_TYPE a);
/**
@brief multiplies every monomial by a constant
*/
void scale_by(MPZCOEF_TYPE a);
/**
@brief a hopefully efficient multiplication algorithm
@details Moves exponents from higher degrees to even higher degrees,
freeing up space for smaller exponents.
*/
void multiply_by_monomial_of_degree(DEG_TYPE);
/**
@brief highly inefficient polynomial multiplication (@f$O(mn)@f$)
*/
void multiply_by(const Dense_Univariate_Integer_Polynomial &);
/** @brief negates the coefficients */
void negate();
/**
@brief reasonably efficient, given our dense representation
@param q polynomial to add to @c this
*/
void add(const Dense_Univariate_Integer_Polynomial & q);
/**
@brief @see add()
@param q polynomial to add to @c this
@return @c this, after adding @p q
*/
Dense_Univariate_Integer_Polynomial & operator +=(
const Dense_Univariate_Integer_Polynomial & q
) {
add(q);
return *this;
}
///@}
/** @name Computation */
///@{
/** @brief returns the result of subtracting the other from @c this */
Dense_Univariate_Integer_Polynomial operator-(
const Dense_Univariate_Integer_Polynomial &
) const;
///@}
/** @name Basic properties */
///@{
/** @brief the @f$k@f$th coefficient */
MPZCOEF_TYPE coeff(DEG_TYPE k) const { return coeffs[k]; }
/** @brief synonym for @c coeff(k) */
MPZCOEF_TYPE operator[](DEG_TYPE k) const { return coeffs[k]; }
/** @brief the polynomial’s degree (exponent of largest nonzero term) */
DEG_TYPE degree() const { return deg; }
/** @brief returns @c True if and only if every valid coefficient is zero */
bool is_zero() const {
bool result = true;
for (DEG_TYPE i = 0; result and i <= deg; ++i)
result = (coeffs[i] == 0);
return result;
}
/** @brief all the coefficients */
const MPZCOEF_TYPE * coefficient_array() { return coeffs; }
///@}
/** @name I/O */
///@{
friend ostream & operator<<(
ostream & os, const Dense_Univariate_Integer_Polynomial & p
) {
if (p.coeffs[p.deg] < 0) { os << '-'; }
for (DEG_TYPE i = p.deg; i > 0; --i) {
if (p.coeffs[i] != 0) {
if (p.coeffs[i] != 1 and p.coeffs[i] != -1) {
if (p.coeffs[i] > 0) { os << p.coeffs[i]; }
else { os << -p.coeffs[i]; }
os << '*';
}
if (i != 1) { os << "t^" << i; }
else { os << "t"; }
}
if (p.coeffs[i - 1] < 0) { os << " - "; }
else if (p.coeffs[i - 1] > 0) { os << " + "; }
}
if (p.coeffs[0] != 0) {
if (p.coeffs[0] > 0) { os << p.coeffs[0]; }
else if (p.coeffs[0] < 0) { os << -p.coeffs[0]; }
}
return os;
}
///@}
protected:
/** @brief list of numerators; index 0 is the constant’s */
MPZCOEF_TYPE * coeffs;
/** @brief degree of the polynomial (largest nonzero exponent) */
DEG_TYPE deg;
/** @brief number of slots for coefficients */
DEG_TYPE size;
};
#endif