Gröbner basis project
Codebase for research into Gröbner basis computation
monomial.cpp
1 #ifndef __MONOMIAL_CPP_
2 #define __MONOMIAL_CPP_
3 
4 /*****************************************************************************\
5 * This file is part of DynGB. *
6 * *
7 * DynGB is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * Foobar is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
19 \*****************************************************************************/
20 
21 #include <cstring>
22 #include <bitset>
23 
24 #include "monomial.hpp"
25 
26 #if EPACK
27  #define MASKALL 0b1111111111111111111111111111111111111111111111111111111111111111
28  const uint64_t MASK [] = {
29  0b0000000000000000000000000000000000000000000000000000000011111111,
30  0b0000000000000000000000000000000000000000000000001111111100000000,
31  0b0000000000000000000000000000000000000000111111110000000000000000,
32  0b0000000000000000000000000000000011111111000000000000000000000000,
33  0b0000000000000000000000001111111100000000000000000000000000000000,
34  0b0000000000000000111111110000000000000000000000000000000000000000,
35  0b0000000011111111000000000000000000000000000000000000000000000000,
36  0b1111111100000000000000000000000000000000000000000000000000000000
37  };
38 #endif
39 
54 
55 void * Monomial::operator new(size_t size) {
56  if (monoda == nullptr) monoda = new Grading_Order_Data_Allocator<Monomial>(size);
57  Monomial * result = monoda->get_new_block();
58  return result;
59 }
60 
61 void Monomial::operator delete(void *t) {
62  monoda->return_used_block(static_cast<Monomial *>(t));
63 }
64 
65 void Monomial::initialize_exponents(NVAR_TYPE number_of_vars) {
66  n = number_of_vars;
67  if (moda == nullptr) moda = new Grading_Order_Data_Allocator<EXP_TYPE>(n);
68  exponents = moda->get_new_block();
69  for (NVAR_TYPE i = 0; i < n; ++i) exponents[i] = 0;
70  mask = 0;
71 }
72 
75  if (ordering_data != nullptr) delete ordering_data;
76 }
77 
78 void Monomial::set_exponent(NVAR_TYPE i, DEG_TYPE e) {
79  exponents[i] = e;
80  if (e == 0) {
81  mask &= ~ (1 << i);
82  #if EPACK
83  if (i < NPACK) emask &= ~MASK[i];
84  #endif
85  }
86  else {
87  mask |= (1 << i);
88  #if EPACK
89  if (i < NPACK) emask |= (MASK[i] & (((uint64_t )((PACKSIZE )e)) << (i*NPACK)));
90  #endif
91  }
92 }
93 
95  NVAR_TYPE number_of_vars, const Monomial_Ordering * order
96 ) {
97  common_initialization(order);
98  initialize_exponents(number_of_vars);
99  ordering->set_data(*this);
100  mask = 0;
101  #if EPACK
102  emask = 0;
103  #endif
104 }
105 
108  n = other.n;
109  mask = other.mask;
110  #if EPACK
111  emask = other.emask;
112  #endif
113  exponents = moda->get_new_block();
114  memcpy(exponents, other.exponents, n*sizeof(EXP_TYPE));
115  ordering_data = (other.ordering_data == nullptr) ? nullptr
117  ord_degree = other.ord_degree;
118 }
119 
121  initializer_list<EXP_TYPE> powers, const Monomial_Ordering * order
122 ) {
123  common_initialization(order);
124  mask = 0;
125  #if EPACK
126  emask = 0;
127  #endif
128  initialize_exponents(powers.size());
129  NVAR_TYPE i = 0;
130  for (
131  auto pi = powers.begin();
132  pi != powers.end();
133  ++pi
134  ) {
135  exponents[i] = *pi;
136  if (*pi != 0) {
137  mask |= (1 << i);
138  #if EPACK
139  if (i < NPACK) emask |= (MASK[i] & (((uint64_t )((PACKSIZE )exponents[i])) << (i*NPACK)));
140  #endif
141  }
142  ++i;
143  }
144  ordering->set_data(*this);
145 }
146 
148  NVAR_TYPE size, const EXP_TYPE *powers, const Monomial_Ordering * order
149 ) {
150  common_initialization(order);
151  n = size;
152  mask = 0;
153  #if EPACK
154  emask = 0;
155  #endif
156  if (moda == nullptr) moda = new Grading_Order_Data_Allocator<EXP_TYPE>(n);
157  exponents = moda->get_new_block();
158  for (NVAR_TYPE i = 0; i < n; ++i) {
159  exponents[i] = powers[i];
160  if (exponents[i] != 0) {
161  mask |= (1 << i);
162  #if EPACK
163  if (i < NPACK) emask |= (MASK[i] & (((uint64_t )((PACKSIZE )exponents[i])) << (i*NPACK)));
164  #endif
165  }
166  }
167  ordering->set_data(*this);
168 }
169 
172  if (ordering_data != nullptr)
173  delete ordering_data;
174 }
175 
176 bool Monomial::is_one() const {
177  bool result = true;
178  for (NVAR_TYPE i = 0; result and i < n; ++i)
179  result = result and exponents[i] == 0;
180  return result;
181 }
182 
183 DEG_TYPE Monomial::degree(NVAR_TYPE i) const {
184  //if (i < n) return exponents[i]; else return 0;
185  return exponents[i];
186 }
187 
188 DEG_TYPE Monomial::operator[](NVAR_TYPE i) const { return degree(i); }
189 
190 DEG_TYPE Monomial::total_degree(NVAR_TYPE m) const {
191  DEG_TYPE result = 0;
192  m = ( m == 0 or m > n ) ? n : m;
193  if (exponents != nullptr)
194  for (NVAR_TYPE i = 0; i < m; ++i)
195  result += exponents[i];
196  return result;
197 };
198 
199 DEG_TYPE Monomial::weighted_degree(const WT_TYPE *weights, NVAR_TYPE m)
200 const {
201  DEG_TYPE result = 0;
202  m = ( m == 0 or m > n ) ? n : m;
203  if (weights == nullptr)
204  result = total_degree();
205  else if (exponents != nullptr)
206  for (NVAR_TYPE i = 0; i < m; ++i)
207  result += weights[i]*exponents[i];
208  return result;
209 }
210 
212  if (ordering != mord) {
213  ordering = mord;
214  ordering->set_data(*this);
215  }
216 }
217 
219  if (ordering_data != nullptr)
220  delete ordering_data;
221  ordering_data = mordat;
222 }
223 
224 bool Monomial::operator ==(const Monomial &other) const {
225  bool result = (n == other.n) and (mask == other.mask)
226  #if EPACK
227  and (emask == other.emask)
228  #endif
229  ;
230  #if !EPACK
231  for (NVAR_TYPE i = 0; result and i < n; ++i)
232  #else
233  for (NVAR_TYPE i = NPACK; result and i < n; ++i)
234  #endif
235  result = result and exponents[i] == other.exponents[i];
236  return result;
237 }
238 
239 bool Monomial::operator !=(const Monomial &other) const {
240  return not (*this == other);
241 }
242 
243 bool Monomial::is_coprime(const Monomial &other) const {
244  return (mask & other.mask) == 0;
245 }
246 
247 bool Monomial::is_like(const Monomial &other) const { return *this == other; }
248 
249 bool Monomial::like_multiple(EXP_TYPE * e, const Monomial & v) const {
250  bool result = (n == v.n);
251  for (NVAR_TYPE i = 0; result and i < n; ++i)
252  result = result and exponents[i] == e[i] + v.exponents[i];
253  return result;
254 }
255 
256 bool Monomial::like_multiple(const Monomial &u, const Monomial &v) const {
257  bool result = (n == u.n and n == v.n) and (mask == (u.mask | v.mask))
258  #if EPACK
259  and (emask == (u.emask + v.emask))
260  #endif
261  ;
262  #if !EPACK
263  for (NVAR_TYPE i = 0; result and i < n; ++i)
264  #else
265  for (NVAR_TYPE i = NPACK; result and i < n; ++i)
266  #endif
267  result = result and exponents[i] == u.exponents[i] + v.exponents[i];
268  return result;
269 }
270 
271 bool Monomial::operator >(const Monomial & u) const { return larger_than(u); }
272 
273 bool Monomial::operator >=(const Monomial & u) const
274 { return ordering->first_larger_or_equal(*this, u); }
275 
276 bool Monomial::operator <(const Monomial & u) const { return !(*this >= u); }
277 
278 bool Monomial::operator <=(const Monomial & u) const { return !(*this > u); }
279 
281  const Monomial & u, const Monomial &v
282 ) const {
283  return ordering->first_larger_than_multiple(*this, u, v);
284 }
285 
286 bool Monomial::divisible_by(const Monomial &other) const {
287  bool result = (n == other.n) and (((~ mask) & other.mask) == 0);
288  #if !EPACK
289  for (NVAR_TYPE i = 0; result and i < n; ++i)
290  result = result and exponents[i] >= other.exponents[i];
291  #else
292  for (NVAR_TYPE i = 0; result and i < NPACK; ++i)
293  result = result
294  and ((emask & MASK[i]) >= (other.emask & MASK[i]));
295  for (NVAR_TYPE i = NPACK; result and i < n; ++i)
296  result = result and exponents[i] >= other.exponents[i];
297  #endif
298  return result;
299 }
300 
301 bool Monomial::operator |(const Monomial &other) const {
302  return other.divisible_by(*this);
303 }
304 
306  if (this != &other)
307  {
308  mask = other.mask;
309  #if EPACK
310  emask = other.emask;
311  #endif
312  if (other.n > n) {
313  delete [] exponents;
314  exponents = new EXP_TYPE [other.n];
315  }
316  n = other.n;
317  for (NVAR_TYPE i = 0; i < n; ++i)
318  exponents[i] = other.exponents[i];
319  ordering = other.ordering;
320  if (ordering_data != nullptr) {
321  delete ordering_data;
322  ordering_data = nullptr;
323  }
324  ordering->set_data(*this);
325  }
326  return *this;
327 }
328 
330  mask |= other.mask;
331  #if EPACK
332  emask += other.emask;
333  #endif
334  NVAR_TYPE i;
335  for (i = 0; i + 1 < n; i += 2) {
336  exponents[i] += other.exponents[i];
337  exponents[i + 1] += other.exponents[i + 1];
338  }
339  if (n % 2) exponents[i] += other.exponents[i];
340  ordering->set_data(*this);
341  return *this;
342 }
343 
344 Monomial Monomial::operator *(const Monomial & other) const {
345  Monomial u(n);
346  for (NVAR_TYPE i = 0; i < n; ++i)
347  u.set_exponent(i, exponents[i] + other.exponents[i]);
348  return u;
349 }
350 
351 bool Monomial::operator /=(const Monomial &other) {
352  bool result = (n == other.n);
353  #if EPACK
354  emask -= other.emask;
355  #endif
356  if (result)
357  for (NVAR_TYPE i = 0; i < n; ++i) {
358  exponents[i] -= other.exponents[i];
359  if (exponents[i] == 0) mask &= ~(1 << i);
360  }
361  ordering->set_data(*this);
362  return result;
363 }
364 
365 Monomial Monomial::lcm(const Monomial & u) const {
366  Monomial result(n, monomial_ordering());
367  result.mask = mask | u.mask;
368  #if EPACK
369  result.emask = emask;
370  #endif
372  for (NVAR_TYPE i = 0; i < n; ++i)
373  if (exponents[i] >= u.exponents[i]) result.exponents[i] = exponents[i];
374  else {
375  result.exponents[i] = u.exponents[i];
376  #if EPACK
377  if (i < NPACK) {
378  result.emask &= ~MASK[i];
379  result.emask |= ((((uint64_t )((PACKSIZE )u.exponents[i])) << (i*NPACK)) & MASK[i]);
380  }
381  #endif
382  }
383  ordering->set_data(result);
384  return result;
385 }
386 
387 Monomial Monomial::gcd(const Monomial & u) const {
388  Monomial result(n, monomial_ordering());
389  result.mask = mask & u.mask;
390  #if EPACK
391  result.emask = emask;
392  #endif
393  for (NVAR_TYPE i = 0; i < n; ++i)
394  if (exponents[i] <= u.exponents[i]) { result.exponents[i] = exponents[i]; }
395  else {
396  result.exponents[i] = u.exponents[i];
397  #if EPACK
398  if (i < NPACK) {
399  result.emask &= ~MASK[i];
400  result.emask |= ((((uint64_t )((PACKSIZE )u.exponents[i])) << (i*NPACK)) & MASK[i]);
401  }
402  #endif
403  }
404  ordering->set_data(result);
405  return result;
406 }
407 
409  Monomial result(n, monomial_ordering());
410  result.mask = 0;
411  #if EPACK
412  result.emask = 0;
413  #endif
414  for (NVAR_TYPE i = 0; i < n; ++i)
415  if (exponents[i] <= u.exponents[i])
416  result.exponents[i] = 0;
417  else {
418  result.exponents[i] = exponents[i] - u.exponents[i];
419  result.mask += (1 << i);
420  #if EPACK
421  if (i < NPACK) result.emask |= (((uint64_t )((PACKSIZE )exponents[i])) << (i*NPACK)) & MASK[i];
422  #endif
423  }
424  ordering->set_data(result);
425  return result;
426 }
427 
428 ostream & operator << (ostream & os, const Monomial &t) {
429  t.print(false, os);
430  return os;
431 }
432 
433 bool Monomial::larger_than(const Monomial & u) const {
434  return ordering->first_larger(*this, u);
435 }
436 
437 #define SHOW_MASK false
438 #define SHOW_EPACK false
439 void Monomial::print(bool add_newline, ostream & os, const string * names) const
440 {
441  if (is_one()) cout << "1 ";
442  else
443  for (NVAR_TYPE i = 0; i < n; ++i)
444  if (exponents[i] != 0)
445  {
446  if (names == nullptr)
447  os << "x" << i;
448  else
449  os << names[i];
450  if (exponents[i] != 1)
451  os << "^" << exponents[i];
452  os << ' ';
453  }
454  #if SHOW_MASK
455  os << '(' << mask << ')';
456  #endif
457  #if SHOW_EPACK
458  os << '(';
459  for (NVAR_TYPE i = 0; i < NPACK; ++i)
460  os << std::bitset<NPACK>(((emask & MASK[i]) >> (i*NPACK))) << ' ';
461  os << ')';
462  #endif
463  if (add_newline)
464  os << endl;
465 }
466 
468  t.set_ordering_data(nullptr);
469 }
470 
472  const Monomial & t, const Monomial & u
473 ) const {
474  return t.is_like(u) or first_larger(t, u);
475 }
476 
478  const Monomial & t, const Monomial & u, const Monomial & v
479 ) const {
480  return t.like_multiple(u, v) or first_larger_than_multiple(t, u, v);
481 }
482 
483 #endif
DEG_TYPE total_degree(NVAR_TYPE m=0) const
Sum of exponents of the first m variables.
Definition: monomial.cpp:190
void set_ordering_data(Monomial_Order_Data *mordat)
sets the Monomial_Order_Data associated with this Monomial
Definition: monomial.cpp:218
special memory pool allocator for Grevlex_Order_Data and WGrevlex_Order_Data
Definition: goda.hpp:67
Grading_Order_Data_Allocator< Monomial > * monoda
memory manager for monomials (not their exponents; see moda for that).
Definition: monomial.cpp:53
DEG_TYPE weighted_degree(const WT_TYPE *weights, NVAR_TYPE m=0) const
Definition: monomial.cpp:199
Monomial operator*(const Monomial &other) const
Return result of this by other.
Definition: monomial.cpp:344
bool operator<(const Monomial &u) const
Compares monomial with according to monomial ordering.
Definition: monomial.cpp:276
NVAR_TYPE n
number of variables
Definition: monomial.hpp:284
bool operator|(const Monomial &other) const
operator for divisibility
Definition: monomial.cpp:301
bool first_larger_or_equal(const Monomial &, const Monomial &) const
Definition: monomial.cpp:471
Monomial(NVAR_TYPE number_of_vars, const Monomial_Ordering *order=generic_grevlex_ptr)
The first constructor is equivalent to instantiating 1.
Definition: monomial.cpp:94
Grading_Order_Data_Allocator< EXP_TYPE > * moda
memory manager for monomial exponents
Definition: monomial.cpp:46
Monomial & operator=(const Monomial &other)
assignment
Definition: monomial.cpp:305
const Monomial_Ordering * ordering
Monomial_Ordering associated with this polynomial.
Definition: monomial.hpp:292
TYPE * get_new_block()
allocates and returns a block of memory
Definition: goda.hpp:108
Monomial & operator*=(const Monomial &other)
Multiply this by other.
Definition: monomial.cpp:329
void set_monomial_ordering(const Monomial_Ordering *mord)
sets the Monomial_Ordering associated with this Monomial
Definition: monomial.cpp:211
void set_exponent(NVAR_TYPE i, DEG_TYPE e)
change th exponent to
Definition: monomial.cpp:78
bool larger_than_multiple(const Monomial &u, const Monomial &v) const
Compares monomial with according to monomial ordering.
Definition: monomial.cpp:280
data for a monomial ordering: optional, but stored in Monomial
void print(bool=true, ostream &=cout, const string *names=nullptr) const
prints the monomial to the give stream with the given names; adds a newline if the boolean is true ...
Definition: monomial.cpp:439
bool divisible_by(const Monomial &other) const
Divisible by other?
Definition: monomial.cpp:286
bool is_one() const
all exponents 0?
Definition: monomial.cpp:176
Monomial_Order_Data * ordering_data
optional data for a monomial ordering
Definition: monomial.hpp:294
Monomial colon(const Monomial &u) const
colon operator: exponents needed to make divisible by this
Definition: monomial.cpp:408
Implementation of monomials.
Definition: monomial.hpp:69
bool first_larger_or_equal_than_multiple(const Monomial &, const Monomial &, const Monomial &) const
Definition: monomial.cpp:477
interface to a monomial ordering
virtual void set_data(Monomial &) const
sets monomial ordering’s data; default is to do nothing
Definition: monomial.cpp:467
friend ostream & operator<<(ostream &, const Monomial &u)
essentially u.print(false, ostream)
Definition: monomial.cpp:428
bool operator!=(const Monomial &other) const
unequal/unlike?
Definition: monomial.cpp:239
bool operator>(const Monomial &u) const
Compares monomial with according to monomial ordering.
Definition: monomial.cpp:271
bool operator/=(const Monomial &other)
divide this by other
Definition: monomial.cpp:351
EXP_TYPE * exponents
has size n
Definition: monomial.hpp:286
bool is_coprime(const Monomial &other) const
true iff this has no common factor with other.
Definition: monomial.cpp:243
void initialize_exponents(NVAR_TYPE number_of_vars)
allocates memory for exponents This is useful when you want to allocate an array of monomials...
Definition: monomial.cpp:65
DEG_TYPE degree(NVAR_TYPE i) const
Degree of th variable.
Definition: monomial.cpp:183
Monomial lcm(const Monomial &u) const
Least common multiple: largest exponents.
Definition: monomial.cpp:365
bool operator>=(const Monomial &u) const
Compares monomial with according to monomial ordering.
Definition: monomial.cpp:273
bool operator==(const Monomial &other) const
equal/alike?
Definition: monomial.cpp:224
Monomial_Order_Data * monomial_ordering_data() const
the Monomial_Order_Data associated with this Monomial
Definition: monomial.hpp:167
virtual bool first_larger(const Monomial &, const Monomial &) const =0
const Monomial_Ordering * monomial_ordering() const
the Monomial_Ordering associated with this Monomial
Definition: monomial.hpp:165
void deinitialize()
deallocates memory for exponents This is useful when you want to deallocate an array of monomials...
Definition: monomial.cpp:73
void return_used_block(TYPE *freed_block)
returns a block of memory that is no longer needed to the pool
Definition: goda.hpp:121
Monomial gcd(const Monomial &u) const
Greatest common divisor: smallest exponents.
Definition: monomial.cpp:387
bool larger_than(const Monomial &) const
compares monomial with according to monomial ordering
Definition: monomial.cpp:433
bool is_like(const Monomial &other) const
Have same variables, same powers? Synonymous with operator==().
Definition: monomial.cpp:247
DEG_TYPE ord_degree
degree associated with monomial ordering (used for faster comparisons)
Definition: monomial.hpp:290
virtual Monomial_Order_Data * clone()
default clone returns nullptr
bool operator<=(const Monomial &u) const
Compares monomial with according to monomial ordering.
Definition: monomial.cpp:278
uint64_t mask
divisibility mask (up to 64 variables)
Definition: monomial.hpp:296
bool like_multiple(const Monomial &u, const Monomial &v) const
is this like ?
Definition: monomial.cpp:256
virtual bool first_larger_than_multiple(const Monomial &, const Monomial &, const Monomial &) const =0
returns true iff the first Monomial is larger than the specified multiple of the second ...
void common_initialization(const Monomial_Ordering *ord=nullptr)
things all Monomial initializers must do
Definition: monomial.hpp:74
~Monomial()
Destructor deallocates exponents.
Definition: monomial.cpp:170
DEG_TYPE operator[](NVAR_TYPE i) const
Degree of th variable. Synonymous with degree().
Definition: monomial.cpp:188