-
Notifications
You must be signed in to change notification settings - Fork 0
/
polynomial_double_buffered.hpp
251 lines (188 loc) · 6.88 KB
/
polynomial_double_buffered.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#ifndef __DBL_BUF_POLYNOMIAL_H_
#define __DBL_BUF_POLYNOMIAL_H_
/*****************************************************************************\
* 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>
using std::cout; using std::endl;
#include "polynomial.hpp"
#include "polynomial_linked_list.hpp"
extern Monomial_Ordering * generic_grevlex_ptr;
class Double_Buffered_Polynomial;
/**
@class DB_Polynomial_Iterator
@author John Perry
@date 2015
@brief Iterator over double-buffered polynomials.
\ingroup IteratorGroup
*/
class DB_Polynomial_Iterator : public Mutable_Polynomial_Iterator {
public:
/** @name Construction */
///@{
DB_Polynomial_Iterator(const Double_Buffered_Polynomial * f, bool at_end=false);
///@}
/** @name Destruction */
///@{
~DB_Polynomial_Iterator();
///@}
/** @name Iteration */
///@{
virtual void restart_iteration() override;
virtual void moveRight() override;
virtual void moveLeft() override;
virtual bool fellOff() const override;
virtual bool canMoveLeft() const override;
virtual bool canMoveRight() const override;
///@}
/** @name Data access */
///@{
virtual const Monomial & currMonomial() const override;
virtual const Prime_Field_Element & currCoeff() const override;
///@}
/** @name Data modification */
///@{
virtual void set_currCoeff(const Prime_Field_Element & a) override;
virtual void set_currMonomial(const Monomial & t) override;
///@}
protected:
/** @brief pointer to polynomial */
const Double_Buffered_Polynomial * p;
/** @brief pointer to coefficients */
Prime_Field_Element * A;
/** @brief pointer to monomials */
Monomial * T;
/** @brief position of first monomial */
unsigned head;
/** @brief position of last monomial */
unsigned tail;
/** @brief current position in the list */
long long current_position;
};
/**
@class Double_Buffered_Polynomial
@author John Perry
@date 2015
@brief Polynomials implemented using double buffers.
\ingroup polygroup
A double-buffered polynomial maintains at all times two arrays to store
its terms. (Technically, it retains four arrays: two for the monomials,
and two for the coefficients.) Any operation that might change the
\e length of the polynomials reads the data in one buffer and writes
the result to the other buffer. The goal of this approach is to avoid the
penalties associated with allocating, deallocating, and traversing the
nodes of a linked list.
*/
class Double_Buffered_Polynomial : public Mutable_Polynomial {
public:
/** @name Construction */
///@{
Double_Buffered_Polynomial(
Polynomial_Ring & R,
Monomial_Ordering * order = generic_grevlex_ptr
);
explicit Double_Buffered_Polynomial(Abstract_Polynomial const & p);
///@}
/** @name Destruction */
///@{
~Double_Buffered_Polynomial();
///@}
/** @name Basic properties */
///@{
virtual Monomial & leading_monomial() const override;
virtual Prime_Field_Element leading_coefficient() const override;
virtual unsigned length() const override;
virtual bool is_zero() const override;
virtual bool can_reduce(Abstract_Polynomial &other) const override;
virtual Double_Buffered_Polynomial * zero_polynomial() const override;
virtual void set_monomial_ordering(
const Monomial_Ordering * order, bool sort_anew=true
) override;
///@}
/** @name Computation */
///@{
virtual Double_Buffered_Polynomial * monomial_multiple(
const Monomial & t
) const override;
virtual Double_Buffered_Polynomial * scalar_multiple(
const Prime_Field_Element & c)
const override;
virtual Mutable_Polynomial & operator += (const Abstract_Polynomial & p) override;
virtual Mutable_Polynomial & operator -= (const Abstract_Polynomial & p) override;
virtual void add_polynomial_multiple(
const Prime_Field_Element & a,
const Monomial & u,
const Abstract_Polynomial & p,
bool subtract
) override;
virtual void sort_by_order() override;
///@}
/** @name Iteration */
///@{
virtual DB_Polynomial_Iterator * new_iterator() const override;
virtual DB_Polynomial_Iterator * new_mutable_iterator() override;
virtual Polynomial_Iterator * begin() const override;
virtual Polynomial_Iterator * end() const override;
///@}
/** @name Modification */
///@{
virtual void add_last(const Prime_Field_Element & a, const Monomial & t) override;
virtual Polynomial_Linked_List * detach_head() override;
///@}
protected:
/** @name Buffering */
///@{
/**
@brief @c true iff buffer @p b has space to hold @p n elements;
expand other buffer if not.
*/
inline bool test_buffer(unsigned b, unsigned n) { return sizes[b] >= n; }
/**
@brief Expand buffer @p b to hold @f$ 2n @f$ elements.
@param b the buffer to expand
@param n number of monomials you’d like it to hold now
@details This does \e not test to see if the space is already available.
*/
void expand_buffer(unsigned b, unsigned n) {
if (mons[b] != nullptr) {
for (unsigned k = 0; k < sizes[b]; ++k)
mons[b][k].deinitialize();
free(mons[b]);
free(coeffs[b]);
}
unsigned new_size = 2*n;
sizes[b] = new_size;
mons[b] = static_cast<Monomial *>(malloc(new_size*sizeof(Monomial)));
for (unsigned k = 0; k < new_size; ++k) {
mons[b][k].initialize_exponents(number_of_variables());
mons[b][k].clear_ordering_data();
}
coeffs[b] = static_cast<Prime_Field_Element *>(
malloc(new_size*sizeof(Prime_Field_Element))
);
}
///@}
/** @brief to iterate over @c this and possibly change it */
friend class DB_Polynomial_Iterator;
private:
Monomial * mons[2];
Prime_Field_Element * coeffs[2];
unsigned sizes[2];
unsigned active_buffer;
unsigned head;
unsigned tail;
};
#endif