Macaulay2 Engine
Loading...
Searching...
No Matches
ExponentVector.hpp
Go to the documentation of this file.
1// Copyright 1997 Michael E. Stillman
2#pragma once
3
38
39#include <assert.h> // for assert
40#include <string.h> // for memcpy
41#include <type_traits> // for make_unsigned
42#include <vector> // for vector
43
44#include "overflow.hpp" // for add, mult, sub, sub_pos
45#include "style.hpp" // for EQ, GT, LT
46#include "buffer.hpp"
47#include "util.hpp"
48
58template <class Exponent, bool overflow_check>
59class ExponentVector;
60// TODO: take advantage of SIMD for operations
61// TODO: confirm that if constexpr (overflow_check) is optimized away
62// TODO: add packing to the template
63
64template <class E, bool OC>
66{
67 public:
68 typedef E Exponent;
70 typedef const Exponent *ConstExponents;
71 typedef typename std::make_unsigned<Exponent>::type HashExponent;
72
73 // result = a
74 static inline void copy(int nvars, ConstExponents a, Exponents result)
75 {
76 memcpy(result, a, nvars * sizeof(Exponent));
77 }
78
79 // result = (0, 0, ..., 0)
80 static inline void one(int nvars, Exponents result)
81 {
82 for (int i = 0; i < nvars; i++) *result++ = 0;
83 }
84
85 // returns whether a_i == 0, all i
86 static inline bool is_one(int nvars, ConstExponents a)
87 {
88 for (int i = 0; i < nvars; i++)
89 if (a[i] != 0) return false;
90 return true;
91 }
92
93 // returns whether a_i == b_i, all i
94 static inline bool equal(int nvars, ConstExponents a, ConstExponents b)
95 {
96 return std::equal(a, a + nvars, b);
97 }
98
99 // result = a + b
100 static inline void mult(int nvars,
104 {
105 if constexpr (OC)
106 for (int i = nvars; i > 0; i--) *result++ = safe::add(*a++, *b++);
107 else
108 for (int i = nvars; i > 0; i--) *result++ = *a++ + *b++;
109 }
110
111 // result = n * a
112 static inline void power(int nvars,
114 const Exponent n,
116 {
117 if constexpr (OC)
118 for (int i = nvars; i > 0; i--) *result++ = safe::mult(*a++, n);
119 else
120 for (int i = nvars; i > 0; i--) *result++ = *a++ * n;
121 }
122
123 // result = a + n * b
124 static inline void multpower(int nvars,
127 const Exponent n,
129 {
130 if constexpr (OC)
131 for (int i = nvars; i > 0; i--)
132 *result++ = safe::add(*a++, safe::mult(*b++, n));
133 else
134 for (int i = nvars; i > 0; i--) *result++ = *a++ + *b++ * n;
135 }
136
137 // returns whether b_i >= a_i, all i
138 static inline bool divides(int nvars, ConstExponents a, ConstExponents b)
139 {
140 // we go upward, because some rings have unused variables at the end
141 for (int i = 0; i < nvars; i++)
142 if (a[i] > b[i]) return false;
143 return true;
144 }
145
146 // result = a - b
147 static inline void divide(int nvars,
151 {
152 if constexpr (OC)
153 for (int i = nvars; i > 0; i--) *result++ = safe::sub(*a++, *b++);
154 else
155 for (int i = 0; i < nvars; i++) *result++ = *a++ - *b++;
156 }
157
158 // result = max(a - b, 0)
159 static inline void quotient(int nvars,
163 {
164 if constexpr (OC)
165 for (int i = nvars; i > 0; i--)
166 {
167 // TODO: if a,b>=0 always, there would never be an overflow
168 assert(*a >= 0 && *b >= 0);
169 *result++ = safe::sub_pos(*a++, *b++);
170 }
171 else
172 for (int i = 0; i < nvars; i++)
173 {
174 Exponent x = *a++;
175 Exponent y = *b++;
176 *result++ = (x <= y ? 0 : x - y);
177 }
178 }
179
180 // result = min(a_i, b_i), all i
181 static inline void gcd(int nvars,
185 {
186 for (int i = nvars; i > 0; i--)
187 {
188 Exponent x = *a++;
189 Exponent y = *b++;
190 *result++ = (x < y ? x : y);
191 }
192 }
193
194 // result = max(a_i, b_i), all i
195 static inline void lcm(int nvars,
199 {
200 for (int i = nvars; i > 0; i--)
201 {
202 Exponent x = *a++;
203 Exponent y = *b++;
204 *result++ = (x > y ? x : y);
205 }
206 }
207
208 // returns GT, LT, or EQ
209 static inline int lex_compare(int nvars, ConstExponents a, ConstExponents b)
210 {
211 for (int i = 0; i < nvars; i++)
212 if (a[i] > b[i])
213 return GT;
214 else if (a[i] < b[i])
215 return LT;
216 return EQ;
217 }
218
219 // returns sum_i a_i
220 static inline Exponent simple_degree(int nvars, ConstExponents a)
221 {
222 // TODO: use std::accumulate?
223 if (nvars == 0) return 0;
224 Exponent sum = a[0];
225 if constexpr (OC)
226 for (int i = 1; i < nvars; i++)
227 sum = safe::add(sum, a[i], "degree overflow");
228 else
229 for (int i = 1; i < nvars; i++) sum += a[i];
230 return sum;
231 }
232
233 // returns sum_i a_i * wt_i
234 static inline Exponent weight(int nvars,
236 const std::vector<Exponent> &wts)
237 {
238 // TODO: use std::inner_product?
239 Exponent top = wts.size();
240 if (nvars < top) top = nvars;
241 if (top == 0) return 0;
242 Exponent sum = safe::mult(a[0], wts[0]);
243 for (int i = 1; i < top; i++)
244 sum = safe::add(sum, safe::mult(a[i], wts[i]), "weight overflow");
245 return sum;
246 }
247 static inline Exponent weight(int nvars, ConstExponents a, M2_arrayint wts)
248 {
249 return weight(nvars, a, M2_arrayint_to_stdvector<int>(wts));
250 }
251
252 // i-th bit of output is 1 if 0 < a[i + k * size_of(int)] for some k
253 static HashExponent mask(int nvars, ConstExponents a);
254 // FIXME: merge diverging specializations
255
256 // assigns c and d such that a*c = d*b = lcm(a,b)
257 static inline void syz(int nvars,
260 Exponents c,
261 Exponents d)
262 {
263 for (int i = 0; i < nvars; i++)
264 {
265 Exponent t = a[i] - b[i];
266 if (t >= 0)
267 {
268 c[i] = 0;
269 d[i] = t;
270 }
271 else
272 {
273 c[i] = -t;
274 d[i] = 0;
275 }
276 }
277 }
278
279 // TODO: do we need this to work without a monoid?
280 // compare with elem_text_out in monoid.hpp
281 static inline void elem_text_out(buffer &o,
282 int nvars,
284 const std::vector<std::string> &varnames,
285 bool p_one)
286 {
287 int len_ = 0;
288 for (unsigned int v = 0; v < nvars; v++)
289 if (a[v] != 0)
290 {
291 len_++;
292 if (varnames.size() < v)
293 o << ".";
294 else
295 o << varnames[v];
296 int e = a[v];
297 int single = (varnames[v].size() == 1);
298 if (e > 1 && single)
299 o << e;
300 else if (e > 1)
301 o << "^" << e;
302 else if (e < 0)
303 o << "^(" << e << ")";
304 }
305 if (len_ == 0 && p_one) o << "1";
306 }
307};
308
309// Legacy specialization
313
314// TODO: compare with ntuple_monomials in e/f4/
315template <>
317{
318 HashExponent result = 0, bit = 1;
319 for (int i = nvars - 1; i >= 0; i--)
320 {
321 if (exp[i] > 0) result |= bit;
322 bit <<= 1;
323 if (bit == 0) bit = 1;
324 }
325 return result;
326}
327
328// Local Variables:
329// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
330// indent-tabs-mode: nil
331// End:
ExponentVector< int, true > exponents
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Append-only GC-backed byte buffer used throughout the engine for text output.
static void syz(int nvars, ConstExponents a, ConstExponents b, Exponents c, Exponents d)
static Exponent weight(int nvars, ConstExponents a, const std::vector< Exponent > &wts)
static Exponent simple_degree(int nvars, ConstExponents a)
static void gcd(int nvars, ConstExponents a, ConstExponents b, Exponents result)
std::make_unsigned< Exponent >::type HashExponent
static void divide(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static Exponent weight(int nvars, ConstExponents a, M2_arrayint wts)
static void one(int nvars, Exponents result)
static void mult(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static bool equal(int nvars, ConstExponents a, ConstExponents b)
static void power(int nvars, ConstExponents a, const Exponent n, Exponents result)
static bool is_one(int nvars, ConstExponents a)
static void copy(int nvars, ConstExponents a, Exponents result)
static void multpower(int nvars, ConstExponents a, ConstExponents b, const Exponent n, Exponents result)
static void elem_text_out(buffer &o, int nvars, ConstExponents a, const std::vector< std::string > &varnames, bool p_one)
static void quotient(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static int lex_compare(int nvars, ConstExponents a, ConstExponents b)
const Exponent * ConstExponents
static void lcm(int nvars, ConstExponents a, ConstExponents b, Exponents result)
static bool divides(int nvars, ConstExponents a, ConstExponents b)
Exponent * Exponents
static HashExponent mask(int nvars, ConstExponents a)
VALGRIND_MAKE_MEM_DEFINED & result(result)
static int32_t mult(int32_t x, int32_t y, const char *msg)
Definition overflow.hpp:236
static int32_t add(int32_t x, int32_t y, const char *msg)
Definition overflow.hpp:116
static int32_t sub(int32_t x, int32_t y, const char *msg)
Definition overflow.hpp:144
static int32_t sub_pos(int32_t x, int32_t y, const char *msg)
Definition overflow.hpp:172
volatile int x
Overflow-checked integer arithmetic for monomial exponents and degree sums.
const int EQ
Definition style.hpp:40
const int GT
Definition style.hpp:41
const int LT
Definition style.hpp:39
Engine-wide stylistic constants: LT / EQ / GT codes, INTSIZE, GEOHEAP_SIZE.
std::vector< T > M2_arrayint_to_stdvector(M2_arrayint arr)
Definition util.hpp:96
Conversion helpers between M2 boundary types and standard C++ containers.