Macaulay2 Engine
Loading...
Searching...
No Matches
res-moninfo-sparse.hpp
Go to the documentation of this file.
1// Copyright 2016-2017 Michael E. Stillman
2
3#ifndef _res_moninfo_sparse_hpp_
4#define _res_moninfo_sparse_hpp_
5
57
58#include <iostream> // for ostream
59#include <memory> // for unique_ptr
60#include <vector> // for vector
61
63#include "skew.hpp" // for SkewMultiplication
64
65// Format for monomials here:
66// a. length (in bytes) (int32)
67// b. hash value (int32)
68// c. component (int32)
69// d. v1 v2 ... vd
70// where d = length-2
71// v1 >= v2 >= ... >= vd >= 0 are indices of variables.
84// or, maybe also have degree before this, and other weight values...
85// SO, general form:
86// [length, hashval, component, w1, ..., wr, v, ..., vd]
88{
90 int nslots;
91 std::unique_ptr<res_monomial_word[]>
92 hashfcn; // array 0..mNumVars-1 of hash values for each variable
94 std::vector<int> mVarDegrees; // array 0..mNumVars-1 of primary (heft)
95 // degrees for each variable.
96
97 int mFirstVar; // = 2, if no weight vector, otherwise 2 + mNumWeights
98
99 int mFirstWeight; // index of the first weight value slot
100 int mNumWeights; // number of weight function values
101
102 // flattened array 0..mNumWeights of array 0..mNumVars-1 of weights
103 std::vector<int> mWeightVectors;
104
105 mutable unsigned long ncalls_hash_value;
106 mutable unsigned long ncalls_compare;
107 mutable unsigned long ncalls_compare_grevlex;
108 mutable unsigned long ncalls_mult;
109 mutable unsigned long ncalls_get_component;
110 mutable unsigned long ncalls_from_expvector;
111 mutable unsigned long ncalls_to_expvector;
112 mutable unsigned long ncalls_to_varpower;
113 mutable unsigned long ncalls_from_varpower;
114 mutable unsigned long ncalls_is_equal;
115 mutable unsigned long ncalls_is_equal_true;
116 mutable unsigned long ncalls_divide;
117 mutable unsigned long ncalls_weight;
118 mutable unsigned long ncalls_unneccesary;
119 mutable unsigned long ncalls_quotient_as_vp;
120
121 public:
125
127 const std::vector<int>& var_degrees,
128 const std::vector<int>& weightvecs,
129 const MonomialOrderingType moType);
130
132
133 int n_vars() const { return mNumVars; }
134 int max_monomial_size() const { return nslots; }
135 int monomial_size(res_const_packed_monomial m) const { return *m; }
136 void show() const;
137
139 {
141 return m[1];
142 }
143 // This hash value is an ADDITIVE hash (trick due to A. Steel)
144
146 {
147 for (int i = *src; i > 0; --i) *target++ = *src++;
148 }
149
151 {
152 m[2] = component;
153 }
154
160
162 {
163 // assumes the following is set already:
164 // result[0] -- length
165 // result[2] -- component
166 // result[mFirstVar..len-1] -- monomial part
167 // sets:
168 // result[1] -- hash code
169 // result[FirstWeight..mFirstVar-1] -- weight vector values
170 const int* wt = mWeightVectors.data();
171 for (int j = 0; j < mNumWeights; j++, wt += mNumVars)
172 {
173 res_monomial_word val = 0;
174 for (int* v = result + mFirstVar; v != result + *result; ++v)
175 val += wt[*v];
176 result[mFirstWeight + j] = val;
177 }
178 res_monomial_word val = 0;
179 for (int* v = result + mFirstVar; v != result + *result; ++v)
180 val += hashfcn[*v];
181 result[1] = val;
182 }
184 component_index comp,
186 {
187 // Pack the vector e[0]..e[mNumVars-1],comp. Create the hash value at the
188 // same time.
190 result[0] = 0; // length
191 result[1] = 0; // hash value, not set here (other than this...)
192 result[2] = comp; // component
193
194 int next_var_slot = mFirstVar;
195
196 for (int i = mNumVars - 1; i >= 0; --i)
197 {
198 if (e[i] > 0)
199 {
200 for (int j = 0; j < e[i]; j++)
201 {
202 result[1] += hashfcn[i];
203 result[next_var_slot] = i;
204 next_var_slot++;
205 }
206 }
207 }
208 result[0] = next_var_slot; // this is the length of this monomial
210 return true;
211 }
212
215 int* skewvars) const
216 {
217 return skew->skew_vars(m + 2 + mNumWeights, skewvars);
218 }
219
223 {
224 return skew->mult_sign(m + 2 + mNumWeights, n + 2 + mNumWeights);
225 }
226
228 {
229 // The monomial "1"
230 result[0] = mFirstVar; // length
231 result[1] = 0; // hash value
232 result[2] = comp; // component
233 for (int i = 3; i < mFirstVar; i++) result[i] = 0;
234 return true;
235 }
236
239 component_index& result_comp) const
240 {
241 // Unpack the monomial m.
243 result_comp = m[2];
244 for (int i = 0; i < mNumVars; i++) result[i] = 0;
245 auto top = *m;
246 for (int i = mFirstVar; i < top; i++) result[m[i]]++;
247 return true;
248 }
249
252 {
253 // 'result' must have enough space allocated
255 int len = 0;
256 res_varpower_word* r = result + 1;
257
258 if (mFirstVar != *m) // ie, m != 1.
259 {
260 int currentvar = m[mFirstVar];
261 int deg = 1;
262 const int* mend = m + *m;
263 for (auto p = m + mFirstVar + 1; p != mend; ++p)
264 {
265 if (*p == currentvar)
266 deg++;
267 else
268 {
269 *r++ = currentvar;
270 *r++ = deg;
271 len++;
272 currentvar = *p;
273 deg = 1;
274 }
275 }
276 }
277 result[0] = len;
278 }
279
281 component_index comp,
283 {
284 // 'result' must have enough space allocated
286 int len = 0;
287 int* r = result + mFirstVar;
288 for (index_res_varpower_monomial j = m; j.valid(); ++j)
289 {
290 res_varpower_word v = j.var();
291 res_varpower_word e = j.exponent();
292 for (int i = 0; i < e; i++) *r++ = v;
293 len += e;
294 }
295 result[0] = len;
296 result[2] = comp;
298 }
299
301 {
303 if (*m != *n) return false;
304 for (int j = *m; j > 0; --j)
305 if (*m++ != *n++) return false;
307 return true;
308 }
309
312 {
313 // Don't consider component
315 if (*m != *n) return false;
316 if (m[1] != n[1]) return false;
317 int len = *m;
318 for (int j = len; j > 0; --j)
319 if (*m++ != *n++) return false;
321 return true;
322 }
323
324#if 0
325 bool check_monomial(res_const_packed_monomial m) const {
326 // Determine if m represents a well-formed monomial.
327 // basically, this means that weight values are non-negative, and variables are in descending order, all >= 0.
328 // REWRITE
329
330 m++;
331 for (int j=nslots-1; j>0; --j)
332 if (mask & (*m++)) return false;
333 return true;
334 }
335#endif
336
340 {
341 // a: mFirstVar + degA
342 // b: mFirstVar + degB
343 // result size is mFirstVar + degA + degB = size(a) + size(b) - mFirstVar
344 ncalls_mult++;
345 result[0] = a[0] + b[0] - mFirstVar;
346 for (int i = 1; i < mFirstVar; ++i) result[i] = a[i] + b[i];
347 // Now we merge the rest
348 const int* v1 = a + mFirstVar;
349 const int* v2 = b + mFirstVar;
350 const int* end1 = a + *a;
351 const int* end2 = b + *b;
352 int* res = result + mFirstVar;
353 if (v1 == end1)
354 {
355 while (v2 != end2) *res++ = *v2++;
356 return;
357 }
358 if (v2 == end2)
359 {
360 while (v1 != end1) *res++ = *v1++;
361 return;
362 }
363 for (;;)
364 {
365 if (*v1 >= *v2)
366 {
367 *res++ = *v1;
368 v1++;
369 if (v1 == end1)
370 {
371 while (v2 != end2) *res++ = *v2++;
372 return;
373 }
374 }
375 else
376 {
377 *res++ = *v2;
378 v2++;
379 if (v2 == end2)
380 {
381 while (v1 != end1) *res++ = *v1++;
382 return;
383 }
384 }
385 }
386 }
387
391 {
392 // computes m/n, or tries to. If n divides m, then return true and set
393 // 'result' to m/n
394 // otherwise return false. In the latter case, it is possible that result
395 // will have been written into partially,
396 // but the result is not a well-formed monomial.
398 if (*m < *n) return false;
399 const int* vm = m + mFirstVar;
400 const int* vn = n + mFirstVar;
401 const int* vend = n + *n;
402 int* vresult = result + mFirstVar;
403 for (; vn != vend; ++vn)
404 {
405 if (*vn > *vm) return false;
406 if (*vn == *vm) ++vm;
407 *vresult++ = *vm++;
408 }
409 for (int i = 1; i < mFirstVar; ++i) result[i] = m[i] - n[i];
410 result[0] = m[0] - n[0] + mFirstVar;
411 return true;
412 }
413
417 {
418 unchecked_mult(m, n, result);
419 return true;
420 // return check_monomial(result);
421 }
422
423 void show(res_const_packed_monomial m) const;
424
426
429 {
431 for (int i = 3; i < mFirstVar; i++)
432 {
433 int cmp = m[i] - n[i];
434 if (cmp > 0) return 1;
435 if (cmp < 0) return -1;
436 }
437 const int* m1 = m + mFirstVar;
438 const int* n1 = n + mFirstVar;
439 const int* mend = m + *m;
440 const int* nend = n + *n;
441 while (*m1 == *n1)
442 {
443 m1++;
444 n1++;
445 if (m1 == mend)
446 {
447 if (n1 == nend)
448 break;
449 else
450 {
451 return -1;
452 }
453 }
454 else
455 {
456 if (n1 == nend) return 1;
457 ;
458 }
459 }
460 res_monomial_word cmp = m[2] - n[2];
461 if (cmp < 0) return 1;
462 if (cmp > 0) return -1;
463 return 0;
464 }
465
470 component_index tie1,
471 component_index tie2) const
472 {
473 // REWRITE
475#if 0
476 printf("compare_schreyer: ");
477 printf(" m=");
478 showAlpha(m);
479 printf(" n=");
480 showAlpha(n);
481 printf(" m0=");
482 showAlpha(m0);
483 printf(" n0=");
484 showAlpha(n0);
485 printf(" tiebreakers: %ld %ld\n", tie1, tie2);
486#endif
487 int* m1 = new int[*m + *m0]; // need less than this
488 int* n1 = new int[*n + *n0]; // need less than this
489 mult(m, m0, m1);
490 mult(n, n0, n1);
491 int cmp = compare_grevlex(m1, n1);
492 if (cmp == 0)
493 {
494 if (tie1 > tie2)
495 cmp = -1;
496 else if (tie1 < tie2)
497 cmp = 1;
498 else
499 cmp = 0;
500 }
501 delete[] m1;
502 delete[] n1;
503 return cmp;
504 }
505
507 {
508 // REWRITE?
509 result[0] = 1;
510 result[1] = v;
511 result[2] = 1;
512 }
513
515 {
516 return static_cast<int>(res_varpower_monomials::weight(a, mVarDegrees));
517 }
518
522 // sets result to be m:n, as a varpower.
523 // 'result' should have enough space to hold deg(m) integers. How do we know
524 // here??
525 {
527
528 const int* vm = m + mFirstVar;
529 const int* vn = n + mFirstVar;
530 const int* vend = n + *n;
531 int* vresult = result + mFirstVar;
532 for (; vn != vend; ++vn)
533 {
534 if (*vn > *vm) continue;
535 if (*vn == *vm) ++vm;
536 *vresult++ = *vm++;
537 }
538 // now make these into a varpower monomial.
539 int len = 0;
540 res_varpower_word* r = result + 1;
541
542 int currentvar = result[mFirstVar];
543 int deg = 1;
544 for (auto p = result + mFirstVar + 1; p != vresult; ++p)
545 {
546 if (*p == currentvar)
547 deg++;
548 else
549 {
550 *r++ = currentvar;
551 *r++ = deg;
552 len++;
553 currentvar = *p;
554 deg = 1;
555 }
556 }
557 result[0] = len;
558 }
559
560 void dump(std::ostream& o, res_const_packed_monomial mon);
561};
562#endif
563
564// Local Variables:
565// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
566// indent-tabs-mode: nil
567// End:
static Exponent weight(ConstExponents m, const std::vector< T > &wts)
unsigned long ncalls_from_expvector
bool from_expvector(res_const_ntuple_monomial e, component_index comp, res_packed_monomial result) const
bool monomial_part_is_equal(res_const_packed_monomial m, res_const_packed_monomial n) const
int degree_of_vp(res_const_varpower_monomial a) const
component_index get_component(res_const_packed_monomial m) const
void unchecked_mult(res_const_packed_monomial a, res_const_packed_monomial b, res_packed_monomial result) const
void showAlpha(res_const_packed_monomial m) const
unsigned long ncalls_from_varpower
unsigned long ncalls_weight
void quotient_as_vp(res_const_packed_monomial m, res_const_packed_monomial n, res_varpower_monomial result) const
ResMonoidSparse(int mNumVars, const std::vector< int > &var_degrees, const std::vector< int > &weightvecs, const MonomialOrderingType moType)
bool to_expvector(res_const_packed_monomial m, res_ntuple_monomial result, component_index &result_comp) const
unsigned long ncalls_compare
bool mult(res_const_packed_monomial m, res_const_packed_monomial n, res_packed_monomial result) const
res_monomial_word mask
int max_monomial_size() const
unsigned long ncalls_hash_value
void to_varpower_monomial(res_const_packed_monomial m, res_varpower_monomial result) const
int compare_schreyer(res_const_packed_monomial m, res_const_packed_monomial n, res_const_packed_monomial m0, res_const_packed_monomial n0, component_index tie1, component_index tie2) const
int monomial_size(res_const_packed_monomial m) const
void setWeightAndHash(res_packed_monomial result) const
unsigned long ncalls_is_equal_true
unsigned long ncalls_to_varpower
std::vector< int > mVarDegrees
unsigned long ncalls_mult
int skew_mult_sign(const SkewMultiplication *skew, res_const_packed_monomial m, res_const_packed_monomial n) const
unsigned long ncalls_quotient_as_vp
unsigned long ncalls_unneccesary
res_const_packed_monomial const_monomial
bool one(component_index comp, res_packed_monomial result) const
bool divide(res_const_packed_monomial m, res_const_packed_monomial n, res_packed_monomial result) const
void variable_as_vp(int v, res_varpower_monomial result) const
unsigned long ncalls_compare_grevlex
std::vector< int > mWeightVectors
unsigned long ncalls_is_equal
int compare_grevlex(res_const_packed_monomial m, res_const_packed_monomial n) const
int skew_vars(const SkewMultiplication *skew, res_const_packed_monomial m, int *skewvars) const
unsigned long ncalls_divide
unsigned long ncalls_to_expvector
void from_varpower_monomial(res_const_varpower_monomial m, component_index comp, res_packed_monomial result) const
void copy(res_const_packed_monomial src, res_packed_monomial target) const
void set_component(component_index component, res_packed_monomial m) const
bool is_equal(res_const_packed_monomial m, res_const_packed_monomial n) const
res_packed_monomial monomial
void dump(std::ostream &o, res_const_packed_monomial mon)
res_monomial_word hash_value(res_const_packed_monomial m) const
unsigned long ncalls_get_component
std::unique_ptr< res_monomial_word[]> hashfcn
int mult_sign(const int *exp1, const int *exp2) const
Definition skew.cpp:91
int skew_vars(const int *exp, int *result) const
Definition skew.cpp:61
Sign-rule helper used by every ring that has a skew-commutative subset of variables (exterior factor,...
Definition skew.hpp:54
int p
VALGRIND_MAKE_MEM_DEFINED & result(result)
myword component_index
ExponentListIterator< myword, false > index_res_varpower_monomial
const res_varpower_word * res_const_varpower_monomial
res_varpower_word * res_varpower_monomial
res_ntuple_word * res_ntuple_monomial
const res_monomial_word * res_const_packed_monomial
myword res_monomial_word
MonomialOrderingType
res_varpower_monomials::Exponent res_varpower_word
res_monomial_word * res_packed_monomial
const res_ntuple_word * res_const_ntuple_monomial
Typed-monomial vocabulary shared by ResMonoid, ResPolyRing, SchreyerFrame, and F4Res.
SkewMultiplication — configuration object naming the skew-commuting variables of a ring.