Macaulay2 Engine
Loading...
Searching...
No Matches
monomial-sets.hpp
Go to the documentation of this file.
1// Copyright 2018 Michael E. Stillman
2
3#ifndef _monomial_sets_hpp_
4#define _monomial_sets_hpp_
5
47
48// This file contains classes for keeping sets of monomials.
49// There are two types of monomials:
50// a. fixed size (and that size is passed in as a parameter)
51// b. variable size, in which case the first int is the total length (so the range is [m, m + *m).
52//
53// Here are some assumptions about these monomials:
54// 1. each monomial is a contiguous sequence of int's.
55// 2. each monomial is hashed using all entries of the monomial. Equality is equality of all elements.
56// (and size, if variable length).
57
58// Features of these classes:
59
60
61#include "memtailor.h"
62#include <unordered_set>
63#include <unordered_map>
64#include <utility>
65#include <cassert>
66
80// MonomialMemorySpace:
81//
83{
84public:
86
87 // returns a range [begin, end), allocated in the block, such that end-begin == size.
88 std::pair<int*,int*> alloc(int size) { mCount++; return mArena.allocArrayNoCon<int>(size); }
89
90 int* allocate(int size) { auto result = alloc(size); return result.first; }
91
92 // if m is the begin part of the last range allocated here, then this pops that.
93 // Afterwards, one can pop the next, etc. If they are popped out of order though,
94 // undefined behavior results.
95 void popLastAlloc(int* m) { mCount--; mArena.freeTop(m); }
96
97 // If m is a pointer into the last monomial (i.e. >= a.first <= a.second), this resets the monomial
98 // to be [a.first, m). The public interface of memt::Arena should perhaps allow this use, but it does not.
99 // However, the code works fine, unless debugging is turned on. I might need to modify that code, and
100 // document that this can be done.
101 // Reasoning for wanting/using this: in the case when monomials are not fixed size, one can allocate
102 // the maximum size it can be, compute it in place, then shrink the monomial.
103 // UNSAFE. Use of this function requires taking care.
104 void shrinkLastAlloc(int* m) { mArena.freeTop(m); }
105
106 size_t size() const { return mCount; }
107
108 void freeAllAllocs() { mArena.freeAllAllocs(); }
109
110 void freeAllAllocsAndBackingMemory() { mArena.freeAllAllocsAndBackingMemory(); }
111private:
112 size_t mCount;
113 memt::Arena mArena;
114};
115
127{
128public:
130
131 // hash function
132 // TODO: do something good here.
133 std::size_t operator()(const int* m) const
134 {
135 (void) m;
136 return 0;
137 }
138
139 bool operator() (const int* a, const int * b) const
140 {
141 return std::equal(a, a+mMonomialSize, b);
142 // for (int i=0; i<mMonomialSize; i++)
143 // if (*a++ != *b++) return false;
144 // return true;
145 }
146
147private:
149};
150
162{
163public:
165
166 // hash function
167 // TODO: do something good here.
168 std::size_t operator()(const int* m) const
169 {
170 (void) m;
171 return 0;
172 }
173
174 bool operator() (const int* a, const int * b) const
175 {
176 if (*a != *b) return false;
177 return std::equal(a, a + *a, b);
178 }
179};
180
186{
187public:
188 MonomialSetFixedSize(int monomialSize)
189 : mMonomialSize(monomialSize),
190 mMonomialHashAndEq(monomialSize),
192 {
193 }
194
196 int elementSize() const { return mMonomialSize; }
197
199 std::size_t numElements() const { return mHash.size(); }
200
204 std::pair<const int*, bool> findOrInsert(const int* monom)
205 {
206 auto result = mHash.insert(monom);
207 return std::make_pair(* result.first, result.second);
208 }
209
211 const int* find(const int* monom) const
212 {
213 auto result = mHash.find(monom); // result is an iterator
214 bool found = result != mHash.end();
215 if (found)
216 return *result;
217 else
218 return nullptr;
219 }
220private:
223 std::unordered_set<const int*, MonomialHashAndEqFixedSize, MonomialHashAndEqFixedSize> mHash;
224};
225
239{
240public:
245
247 std::size_t numElements() const { return mHash.size(); }
248
252 std::pair<const int*, bool> findOrInsert(const int* monom)
253 {
254 auto result = mHash.insert(monom);
255 return std::make_pair(* result.first, result.second);
256 }
257
259 const int* find(const int* monom) const
260 {
261 auto result = mHash.find(monom); // result is an iterator
262 bool found = result != mHash.end();
263 if (found)
264 return *result;
265 else
266 return nullptr;
267 }
268private:
270 std::unordered_set<const int*, MonomialHashAndEqVarSize, MonomialHashAndEqVarSize> mHash;
271};
272
287{
288public:
290 : mSet(monomialSize)
291 {
292 }
293
294 // There are two ways to insert monomials.
295 // 1. the monomial was just allocated on monomialMemorySpace().
296 // 2. the momomial exists outside of this memory block.
297 // In the latter case, the monomial will be copied to the block.
298 //
299 // Another way is to insert a monomial via a transformer function. TODO.
301
302 int elementSize() const { return mSet.elementSize(); }
303
304 // Number of (different) monomials in this set
305 std::size_t size() const { return mMonomialMemory.size(); }
306
307 // insert: two versions: depending on whether we need to copy the pointer.
308 // decide if monom is in the set: if so, (equiv monom, false) is returned.
309 // If it is not in the set, it is copied into the memory block, and (equiv monom, true) is returned.
310 // Note: the only pointers this function returns (as the first part of the pair) are pointers into
311 // the memory block.
312 std::pair<const int*, bool> findOrInsert(const int* monom)
313 {
314 std::pair<int*, int*> mon { mMonomialMemory.alloc(elementSize()) };
315 std::copy(monom, monom + elementSize(), mon.first);
316 assert(mon.second - mon.first >= elementSize());
317 return findOrInsertTopInternedMonomial(mon.first);
318 }
319
320 // assumption: 'monom' is currently the top (last) monomial on mMonomialMemory.
321 // If the monomial is found in the set, then monom is popped off the memory block.
322 std::pair<const int*, bool> findOrInsertTopInternedMonomial(int*& monom)
323 {
324 // if the monomial is found in the set, then monom is popped
325 auto result = mSet.findOrInsert(monom);
326 if (not result.second) // i.e. monomial was not needed.
327 mMonomialMemory.popLastAlloc(monom);
328 return result;
329 }
330
331 // find: this returns either: (nullptr,false), if not found, or the (canonicalized pointer, true).
332 const int* find(const int* monom) const
333 {
334 return mSet.find(monom);
335 }
336
337 // way to loop through all such monomials
338
339 // way to sort them?
340
341private:
344};
345
346
359{
360public:
362
363 // There are two ways to insert monomials.
364 // 1. the monomial was just allocated on monomialMemorySpace().
365 // 2. the momomial exists outside of this memory block.
366 // In the latter case, the monomial will be copied to the block.
367 //
368 // Another way is to insert a monomial via a transformer function. TODO.
369
371
372 // Number of (different) monomials in this set
373 std::size_t size() const { return mMonomialMemory.size(); }
374
375 // insert: two versions: depending on whether we need to copy the pointer.
376 // decide if monom is in the set: if so, (equiv monom, false) is returned.
377 // If it is not in the set, it is copied into the memory block, and (equiv monom, true) is returned.
378 // Note: the only pointers this function returns (as the first part of the pair) are pointers into
379 // the memory block.
380 std::pair<const int*, bool> findOrInsert(const int* monom)
381 {
382 std::pair<int*, int*> mon { mMonomialMemory.alloc(*monom) };
383 std::copy(monom, monom + *monom, mon.first);
384 assert(mon.second - mon.first >= *monom);
385 return findOrInsertTopInternedMonomial(mon.first);
386 }
387
388 // assumption: 'monom' is currently the top (last) monomial on mMonomialMemory.
389 // If the monomial is found in the set, then monom is popped off the memory block.
390 std::pair<const int*, bool> findOrInsertTopInternedMonomial(int*& monom)
391 {
392 // if the monomial is found in the set, then monom is popped
393 auto result = mSet.findOrInsert(monom);
394 if (not result.second) // i.e. monomial was not needed.
395 mMonomialMemory.popLastAlloc(monom);
396 return result;
397 }
398
399 // find: this returns either: (nullptr,false), if not found, or the (canonicalized pointer, true).
400 const int* find(const int* monom) const
401 {
402 return mSet.find(monom);
403 }
404
405 // way to loop through all such monomials
406
407 // way to sort them?
408
409private:
412};
413
414#endif
415
416// Local Variables:
417// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
418// indent-tabs-mode: nil
419// End:
420
MonomialSetFixedSize mSet
const int * find(const int *monom) const
std::pair< const int *, bool > findOrInsert(const int *monom)
MonomialCollectionFixedSize(int monomialSize)
MonomialMemorySpace mMonomialMemory
MonomialMemorySpace & monomialMemorySpace()
std::pair< const int *, bool > findOrInsertTopInternedMonomial(int *&monom)
std::pair< const int *, bool > findOrInsert(const int *monom)
std::size_t size() const
const int * find(const int *monom) const
MonomialMemorySpace & monomialMemorySpace()
MonomialMemorySpace mMonomialMemory
std::pair< const int *, bool > findOrInsertTopInternedMonomial(int *&monom)
std::size_t operator()(const int *m) const
Combined hash + equality functor for fixed-size monomials, plugged into the std::unordered_set inside...
std::size_t operator()(const int *m) const
Combined hash + equality functor for variable-size monomials, plugged into the std::unordered_set ins...
std::pair< int *, int * > alloc(int size)
void shrinkLastAlloc(int *m)
int * allocate(int size)
void popLastAlloc(int *m)
Bump-pointer arena for monomial storage, backed by a memt::Arena.
std::size_t numElements() const
number of (unique) monomials in this set.
MonomialSetFixedSize(int monomialSize)
std::unordered_set< const int *, MonomialHashAndEqFixedSize, MonomialHashAndEqFixedSize > mHash
MonomialHashAndEqFixedSize mMonomialHashAndEq
const int * find(const int *monom) const
returns nullptr if monom is not present, otherwise returns the pointer equivalent to 'monom'.
int elementSize() const
size of each monomial
std::pair< const int *, bool > findOrInsert(const int *monom)
const int * find(const int *monom) const
returns nullptr if monom is not present, otherwise returns the pointer equivalent to 'monom'.
std::pair< const int *, bool > findOrInsert(const int *monom)
MonomialHashAndEqVarSize mMonomialHashAndEq
std::size_t numElements() const
number of (unique) monomials in this set.
std::unordered_set< const int *, MonomialHashAndEqVarSize, MonomialHashAndEqVarSize > mHash
Hash set of interned variable-size monomials — the variable-length counterpart of MonomialSetFixedSiz...
VALGRIND_MAKE_MEM_DEFINED & result(result)