Macaulay2 Engine
Loading...
Searching...
No Matches
ExponentList.cpp
Go to the documentation of this file.
1// (c) 1995 Michael E. Stillman
2
3#include "ExponentList.hpp"
4
5#include <assert.h> // for assert
6
7#include "buffer.hpp" // for buffer
8#include "error.h" // for ERROR
9#include "overflow.hpp" // for add, mult
10
11#define MAX_VAR 2147483647
12#define MIN_EXP -2147483647
13#define MAX_EXP 2147483647
14
15static bool check_var(int v, int e)
16{
17 if (v < 0 || v > MAX_VAR)
18 {
19 ERROR("Monomial expects variable number in range 0..%d", MAX_VAR);
20 return false;
21 }
22 if (e < MIN_EXP || e > MAX_EXP || e == 0)
23 {
24 ERROR("Monomial expects non-zero exponents in range %d..%d",
25 MIN_EXP,
26 MAX_EXP);
27 return false;
28 }
29 return true;
30}
31
32template <>
34{
35 // TODO: should result be cleared?
36 result.resize(m->len + 1);
37 int *result_vp = result.data();
38 *result_vp++ = result.size();
39 int *melems = m->array;
40
41 for (int i = 0; i < m->len; i += 2) // FIXME: reconcile
42 {
43 int v = *melems++;
44 int e = *melems++;
45 check_var(v, e);
46 *result_vp++ = v;
47 *result_vp++ = e;
48 }
49}
50
51template <>
53{
54 int len = length(vp);
55 M2_arrayint result = M2_makearrayint(len); // FIXME: reconcile
56 for (int i = 0; i < len; i++) result->array[i] = *vp++;
57 return result;
58}
59
60template <>
62{
63 for (int j = 0; j < n; j++) result[j] = 0;
64 for (index_varpower i = a; i.valid(); ++i)
65 {
66 int v = i.var();
67 int e = i.exponent();
68 assert(v < n);
69 result[v] = e;
70 }
71}
72
73template <>
74void varpower::from_expvector(int n, ConstExponents a, Vector& result)
75{
76 int len = 0;
77 for (int i = 0; i < n; i++)
78 if (a[i] != 0) len++;
79
80 result.resize(2 * len + 1);
81 Exponents result_vp = result.data();
82 *result_vp++ = result.size(); // FIXME: reconcile
83 for (int i = n - 1; i >= 0; i--)
84 if (a[i] != 0)
85 {
86 *result_vp++ = i;
87 *result_vp++ = a[i];
88 }
89}
90
91template <>
93{
94 // TODO: should result be cleared?
95 result.resize(length(a) + length(b)); // potential length
96 Exponents result_vp = result.data();
97 Exponents orig_result_vp = result_vp;
98 result_vp++;
99
100 index_varpower i = a;
101 index_varpower j = b;
102
103 // merge the two varpowers to staticVP
104 int va = (i.valid() ? i.var() : -1);
105 int vb = (j.valid() ? j.var() : -1);
106 for (;;)
107 {
108 if (va > vb)
109 {
110 *result_vp++ = va;
111 *result_vp++ = i.exponent();
112 ++i;
113 va = (i.valid() ? i.var() : -1);
114 }
115 else if (vb > va)
116 {
117 *result_vp++ = vb;
118 *result_vp++ = j.exponent();
119 ++j;
120 vb = (j.valid() ? j.var() : -1);
121 }
122 else
123 {
124 if (va == -1) break;
125 int z = safe::add(i.exponent(), j.exponent());
126 if (z != 0)
127 {
128 *result_vp++ = va;
129 *result_vp++ = z;
130 }
131 ++i;
132 ++j;
133 va = (i.valid() ? i.var() : -1);
134 vb = (j.valid() ? j.var() : -1);
135 }
136 }
137 int newlen = static_cast<int>(result_vp - orig_result_vp);
138 *orig_result_vp = newlen;
139 result.resize(newlen);
140}
141
142template <>
145 Vector& result)
146// return a:b
147{
148 // TODO: should result be cleared?
149 result.resize(length(a)); // potential length
150 Exponents result_vp = result.data();
151 Exponents orig_result_vp = result_vp;
152 result_vp++;
153
154 index_varpower i = a;
155 index_varpower j = b;
156
157 int va = (i.valid() ? i.var() : -1);
158 int vb = (j.valid() ? j.var() : -1);
159 for (;;)
160 {
161 if (va > vb)
162 {
163 *result_vp++ = va;
164 *result_vp++ = i.exponent();
165 ++i;
166 va = (i.valid() ? i.var() : -1);
167 }
168 else if (vb > va)
169 {
170 ++j;
171 vb = (j.valid() ? j.var() : -1);
172 }
173 else
174 {
175 if (va == -1) break;
176 int ea = i.exponent();
177 int eb = j.exponent();
178 if (ea > eb)
179 {
180 *result_vp++ = va;
181 *result_vp++ = ea - eb; // overflow cannot occur
182 }
183 ++i;
184 ++j;
185 va = (i.valid() ? i.var() : -1);
186 vb = (j.valid() ? j.var() : -1);
187 }
188 }
189 *orig_result_vp = static_cast<int>(result_vp - orig_result_vp);
190}
191
192template <>
193void varpower::power(ConstExponents a, int n, Vector& result)
194{
195 if (n == 0)
196 {
197 result.push_back(1);
198 return;
199 }
200 result.resize(length(a));
201 int *result_vp = result.data();
202 *result_vp++ = result.size();
203 for (index_varpower i = a; i.valid(); ++i)
204 {
205 *result_vp++ = i.var();
206 *result_vp++ = safe::mult(i.exponent(), n);
207 }
208}
209
210template <>
212// FIXME: Note the switch in order of parameters. Does b divide a?
213{
214 index_varpower i = a;
215 index_varpower j = b;
216 int va = (i.valid() ? i.var() : -1);
217 int vb = (j.valid() ? j.var() : -1);
218 for (;;)
219 {
220 if (va > vb)
221 {
222 ++i;
223 va = (i.valid() ? i.var() : -1);
224 }
225 else if (va < vb)
226 return false;
227 else
228 {
229 if (va == -1) return true;
230 int ea = i.exponent();
231 int eb = j.exponent();
232 if (ea < eb) return false;
233 ++i;
234 ++j;
235 va = (i.valid() ? i.var() : -1);
236 vb = (j.valid() ? j.var() : -1);
237 }
238 }
239}
240
241template <>
243// sa, sb are set so that a * sa = b * sb
244// and sa, sb have disjoint support.
245{
246 sa.resize(length(a));
247 sb.resize(length(b));
248 int *result_vp1 = sa.data();
249 int *result_vp2 = sa.data();
250 int *orig_result_vp1 = result_vp1;
251 int *orig_result_vp2 = result_vp2;
252 result_vp1++;
253 result_vp2++;
254
255 index_varpower i = a;
256 index_varpower j = b;
257
258 int va = (i.valid() ? i.var() : -1);
259 int vb = (j.valid() ? j.var() : -1);
260 for (;;)
261 {
262 if (va > vb)
263 {
264 // va should be placed into sb
265 *result_vp2++ = va;
266 *result_vp2++ = i.exponent();
267 ++i;
268 va = (i.valid() ? i.var() : -1);
269 }
270 else if (va < vb)
271 {
272 // vb should be placed into sa
273 *result_vp1++ = vb;
274 *result_vp1++ = j.exponent();
275 ++j;
276 vb = (j.valid() ? j.var() : -1);
277 }
278 else
279 {
280 if (va == -1) break;
281 int ea = i.exponent();
282 int eb = j.exponent();
283 if (ea < eb)
284 {
285 *result_vp1++ = va;
286 *result_vp1++ = eb - ea;
287 }
288 else if (ea > eb)
289 {
290 *result_vp2++ = va;
291 *result_vp2++ = ea - eb;
292 }
293 ++i;
294 ++j;
295 va = (i.valid() ? i.var() : -1);
296 vb = (j.valid() ? j.var() : -1);
297 }
298 }
299 *orig_result_vp1 = static_cast<int>(result_vp1 - orig_result_vp1);
300 *orig_result_vp2 = static_cast<int>(result_vp2 - orig_result_vp2);
301}
302
303template <>
305{
306 // TODO: should result be cleared?
307 result.resize(length(a) + length(b)); // potential length
308 Exponents result_vp = result.data();
309 Exponents orig_result_vp = result_vp;
310 result_vp++;
311
312 index_varpower i = a;
313 index_varpower j = b;
314
315 // merge the two varpowers to staticVP
316 int va = (i.valid() ? i.var() : -1);
317 int vb = (j.valid() ? j.var() : -1);
318 for (;;)
319 {
320 if (va > vb)
321 {
322 *result_vp++ = va;
323 *result_vp++ = i.exponent();
324 ++i;
325 va = (i.valid() ? i.var() : -1);
326 }
327 else if (vb > va)
328 {
329 *result_vp++ = vb;
330 *result_vp++ = j.exponent();
331 ++j;
332 vb = (j.valid() ? j.var() : -1);
333 }
334 else
335 {
336 if (va == -1) break;
337 int ea = i.exponent();
338 int eb = j.exponent();
339 if (ea < eb) ea = eb;
340 *result_vp++ = va;
341 *result_vp++ = ea;
342 ++i;
343 ++j;
344 va = (i.valid() ? i.var() : -1);
345 vb = (j.valid() ? j.var() : -1);
346 }
347 }
348 *orig_result_vp = static_cast<int>(result_vp - orig_result_vp);
349}
350
351template <>
353{
354 // TODO: should result be cleared?
355 result.resize(std::min(length(a), length(b))); // potential length
356 int *result_vp = result.data();
357 int *orig_result_vp = result_vp;
358 result_vp++;
359
360 index_varpower i = a;
361 index_varpower j = b;
362
363 // merge the two varpowers to staticVP
364 int va = (i.valid() ? i.var() : -1);
365 int vb = (j.valid() ? j.var() : -1);
366 for (;;)
367 {
368 if (va > vb)
369 {
370 ++i;
371 va = (i.valid() ? i.var() : -1);
372 }
373 else if (vb > va)
374 {
375 ++j;
376 vb = (j.valid() ? j.var() : -1);
377 }
378 else
379 {
380 if (va == -1) break;
381 int ea = i.exponent();
382 int eb = j.exponent();
383 if (ea > eb) ea = eb;
384 *result_vp++ = va;
385 *result_vp++ = ea;
386 ++i;
387 ++j;
388 va = (i.valid() ? i.var() : -1);
389 vb = (j.valid() ? j.var() : -1);
390 }
391 }
392 *orig_result_vp = static_cast<int>(result_vp - orig_result_vp);
393}
394
395template <>
397// divide a by b^infinity
398{
399 // TODO: should result be cleared?
400 result.resize(length(a));
401 int *result_vp = result.data();
402 int *orig_result_vp = result_vp;
403 result_vp++;
404
405 index_varpower i = a;
406 index_varpower j = b;
407
408 int va = (i.valid() ? i.var() : -1);
409 int vb = (j.valid() ? j.var() : -1);
410 for (;;)
411 {
412 if (va > vb)
413 {
414 *result_vp++ = va;
415 *result_vp++ = i.exponent();
416 ++i;
417 va = (i.valid() ? i.var() : -1);
418 }
419 else if (vb > va)
420 {
421 ++j;
422 vb = (j.valid() ? j.var() : -1);
423 }
424 else
425 {
426 if (va == -1) break;
427 ++i;
428 ++j;
429 va = (i.valid() ? i.var() : -1);
430 vb = (j.valid() ? j.var() : -1);
431 }
432 }
433
434 *orig_result_vp = static_cast<int>(result_vp - orig_result_vp);
435}
436
437template <>
439{
440 // TODO: should result be cleared?
441 // length of result is the same as that of a
442 result.resize(length(a));
443 int *result_vp = result.data();
444 *result_vp++ = result.size();
445 for (index_varpower i = a; i.valid(); ++i)
446 {
447 *result_vp++ = i.var(); // var
448 *result_vp++ = 1; // exponent
449 }
450}
451
452// Local Variables:
453// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
454// indent-tabs-mode: nil
455// End:
#define MIN_EXP
#define MAX_EXP
#define MAX_VAR
static bool check_var(int v, int e)
ExponentListIterator< int, true > index_varpower
Variable-length sparse (variable, exponent) encoding of monomials.
exponents::Exponents exponents_t
Append-only GC-backed byte buffer used throughout the engine for text output.
gc_vector< Exponent > Vector
static void radical(ConstExponents a, Vector &result)
const Exponent * ConstExponents
static void lcm(ConstExponents a, ConstExponents b, Vector &result)
static void mult(ConstExponents a, ConstExponents b, Vector &result)
static void from_arrayint(M2_arrayint m, Vector &result)
static void quotient(ConstExponents a, ConstExponents b, Vector &result)
static void from_expvector(int n, exponents::ConstExponents a, Vector &result)
static void gcd(ConstExponents a, ConstExponents b, Vector &result)
static void monsyz(ConstExponents a, ConstExponents b, Vector &sa, Vector &sb)
static void erase(ConstExponents a, ConstExponents b, Vector &result)
static bool divides(ConstExponents a, ConstExponents b)
static M2_arrayint to_arrayint(ConstExponents vp)
static const Exponent length(ConstExponents m)
static void to_expvector(int n, ConstExponents a, exponents::Exponents result)
static void power(ConstExponents a, Exponent n, Vector &result)
Engine error-reporting primitives: ERROR, INTERNAL_ERROR, error, error_message.
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
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
Overflow-checked integer arithmetic for monomial exponents and degree sums.