Gröbner basis project
Codebase for research into Gröbner basis computation
dense_univariate_rational_poly.cpp
1 #ifndef __DENSE_UNIVARIATE_RATIONAL_POLY_CPP_
2 #define __DENSE_UNIVARIATE_RATIONAL_POLY_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 "dense_univariate_rational_poly.hpp"
22 
23 template <typename T, typename U>
24 void divide_by_common_term(T & a, U & b) {
25  T c = (a < 0) ? -a : a;
26  //U d = (b < 0) ? -b : b;
27  U d = b;
28  while (d != 0) {
29  T r = c % d;
30  c = d;
31  d = r;
32  }
33  a /= c;
34  b /= c;
35 }
36 
38  DEG_TYPE n
39 ) {
40  coeffs = new MPQCOEF_TYPE [n];
41  for (DEG_TYPE i = 0; i < n; ++i)
42  coeffs[i] = 0;
43  size = n;
44  deg = 0;
45 }
46 
49 ) {
50  size = other.size;
51  deg = other.deg;
52  coeffs = new MPQCOEF_TYPE [size] { 0 };
53  for (DEG_TYPE i = 0; i < size; ++i)
54  coeffs[i] = other.coeffs[i];
55 }
56 
58  DEG_TYPE n, int64_t * nums, uint64_t * denoms
59 ) {
60  size = n + 1;
61  deg = n;
62  coeffs = new MPQCOEF_TYPE [size] { 0 };
63  for (DEG_TYPE i = 0; i <= deg; ++i)
64  coeffs[i] = long(nums[i]) / (unsigned long)(denoms[i]);
65 }
66 
68  if (n + 1 > size) {
69  MPQCOEF_TYPE * new_coeffs = new MPQCOEF_TYPE [n + 1];
70  for (DEG_TYPE i = 0; i < deg + 1; ++i)
71  new_coeffs[i] = coeffs[i];
72  delete [] coeffs;
73  coeffs = new_coeffs;
74  for (DEG_TYPE i = deg + 1; i < n + 1; ++i)
75  coeffs[i] = 0;
76  size = n + 1;
77  }
78 }
79 
81  for (DEG_TYPE i = 0; i <= deg; ++i)
82  if (coeffs[i] != 0)
83  coeffs[i] *= (long)a;
84 }
85 
87  for (DEG_TYPE i = 0; i <= deg; ++i)
88  if (coeffs[i] != 0)
89  coeffs[i] *= a;
90 }
91 
93  COEF_TYPE a, UCOEF_TYPE b
94 ) {
95  for (DEG_TYPE i = 0; i <= deg; ++i)
96  if (coeffs[i] != 0) {
97  coeffs[i] *= (long)a;
98  coeffs[i] /= (unsigned long)b;
99  }
100 }
101 
103  DEG_TYPE k
104 ) {
105  expand_poly(deg + k);
106  for (DEG_TYPE i = deg; i > 0; --i) {
107  if (coeffs[i] != 0) {
108  coeffs[i + k] = coeffs[i];
109  coeffs[i] = 0;
110  }
111  }
112  coeffs[k] = coeffs[0];
113  coeffs[0] = 0;
114 }
115 
118 ) {
119  DEG_TYPE n = deg + q.deg + 1; // add 1 in case deg == q.deg == 0
120  n = (n > size) ? n : size;
121  MPQCOEF_TYPE * new_coeffs = new MPQCOEF_TYPE [n];
122  for (DEG_TYPE i = 0; i < n; ++i)
123  new_coeffs[i] = 0;
124  for (DEG_TYPE i = 0; i < deg + 1; ++i)
125  for (DEG_TYPE j = 0; j < q.deg + 1; ++j) {
126  if (coeffs[i] != 0 and q.coeffs[j] != 0)
127  new_coeffs[i + j] += coeffs[i] * q.coeffs[j];
128  }
129  delete [] coeffs;
130  coeffs = new_coeffs;
131  size = n;
132  deg = deg + q.deg;
133 }
134 
136  for (DEG_TYPE i = 0; i <= deg; ++i)
137  if (coeffs[i] != 0)
138  coeffs[i] = -coeffs[i];
139 }
140 
143 ) {
144  DEG_TYPE new_deg = (deg > q.deg) ? deg : q.deg;
145  expand_poly(new_deg);
146  deg = new_deg;
147  for (DEG_TYPE i = 0; i <= q.deg; ++i)
148  if (q.coeffs[i] != 0)
149  coeffs[i] += q.coeffs[i];
150  if (coeffs[deg] == 0) {
151  DEG_TYPE i = deg;
152  while (i > 0 and coeffs[i] == 0)
153  --i;
154  deg = i;
155  }
156 }
157 
160 ) {
161  DEG_TYPE new_deg = (deg > q.deg) ? deg : q.deg;
162  expand_poly(new_deg);
163  deg = new_deg;
164  for (DEG_TYPE i = 0; i <= q.deg; ++i)
165  if (q.coeffs[i] != 0)
166  coeffs[i] -= q.coeffs[i];
167  if (coeffs[deg] == 0) {
168  DEG_TYPE i = deg;
169  while (i > 0 and coeffs[i] == 0)
170  --i;
171  deg = i;
172  }
173 }
174 
177  const Dense_Univariate_Rational_Polynomial & other) const {
178  DEG_TYPE m = (deg < other.degree()) ? deg : other.degree();
179  DEG_TYPE n = (deg > other.degree()) ? deg : other.degree();
181  DEG_TYPE i = 0;
182  for ( /* already initialized */; i <= m; ++i)
183  result.coeffs[i] = coeffs[i] - other.coeffs[i];
184  // only one of the next two loops will be performed
185  while (i < deg) {
186  result.coeffs[i] = coeffs[i];
187  ++i;
188  }
189  while (i < other.degree()) {
190  result.coeffs[i] = -other.coeffs[i];
191  ++i;
192  }
193  return result;
194 }
195 
196 #endif
MPQCOEF_TYPE * coeffs
list of coefficients; index 0 is the constant’s
DEG_TYPE size
number of slots for coefficients
void multiply_by(const Dense_Univariate_Rational_Polynomial &)
highly inefficient polynomial multiplication ( )
void add(const Dense_Univariate_Rational_Polynomial &)
adds other to this
void expand_poly(DEG_TYPE)
expand to allow for higher-degree monomials
void subtract(const Dense_Univariate_Rational_Polynomial &)
subtracts other from this
void multiply_by_monomial_of_degree(DEG_TYPE)
a hopefully efficient multiplication algorithm
DEG_TYPE deg
degree of the polynomial (largest nonzero exponent)
void scale_by(COEF_TYPE a)
multiplies every monomial by a constant integer
quick-’n-dirty Dense_Univariate rational polynomial class
DEG_TYPE degree() const
returns the polynomial’s degree
void divide_by_common_term(COEF_TYPE &, UCOEF_TYPE &)
divides out the common term of the two given numbers
Dense_Univariate_Rational_Polynomial(DEG_TYPE)
construct with the number of expected terms
Dense_Univariate_Rational_Polynomial operator-(const Dense_Univariate_Rational_Polynomial &) const
returns the difference between this and the other