Macaulay2 Engine
Loading...
Searching...
No Matches
M2FreeAlgebra.cpp
Go to the documentation of this file.
1#include "M2FreeAlgebra.hpp"
2
3#include <assert.h>
4#include <iostream>
5#include <string>
6#include <utility>
7#include <vector>
8
9#include "exceptions.hpp"
10#include "monoid.hpp"
11#include "monomial.hpp"
12#include "relem.hpp"
13
15 const PolyList& polys)
16{
17 auto& A0 = A->freeAlgebra();
19 auto end = polys.cend();
20 for (auto i = polys.cbegin(); i != end; ++i)
21 {
22 Poly* f = new Poly;
23 A0.copy(*f, *(*i));
24 result.push_back(f);
25 }
26 return result;
27}
28
30{
31 int comp_unused;
32 f.getCoeffInserter().push_back(coefficientRing()->from_long(1));
33 appendModuleMonomToMonom(m, comp_unused, f.getMonomInserter());
34}
35
42
44 const std::vector<std::string>& names,
46 const std::vector<int>& degrees,
47 const std::vector<int>& wtvecs,
48 const std::vector<int>& heftVector)
49{
50 assert(K != nullptr);
51 auto F = std::unique_ptr<FreeAlgebra>(FreeAlgebra::create(K, names, degreeRing, degrees, wtvecs, heftVector));
52 M2FreeAlgebra* result = new M2FreeAlgebra(std::move(F));
53 result->initialize_ring(K->characteristic(), degreeRing, heftVector);
54 result->zeroV = result->from_long(0);
55 result->oneV = result->from_long(1);
56 result->minus_oneV = result->from_long(-1);
57
58 return result;
59}
60
61M2FreeAlgebra::M2FreeAlgebra(std::unique_ptr<FreeAlgebra> F)
62 : mFreeAlgebra(std::move(F))
63{
64}
65
67{
69 o << "{";
70 for (int i = 0; i < monoid().variableNames().size(); i++)
71 {
72 if (i > 0) o << ",";
73 o << monoid().variableNames()[i];
74 }
75 o << "}";
76}
77
78unsigned int M2FreeAlgebra::computeHashValue(const ring_elem a) const
79{
80 (void) a;
81 return 0; // TODO: change this to a more reasonable hash code.
82}
83
85{
86 // This function is needed at top level to be able to determine if a ring element is a variable
87 //const Poly* f = reinterpret_cast<Poly*>(a.poly_val);
88 auto f = reinterpret_cast<const Poly*>(a.get_Poly());
89
90 // f is a variable iff: #terms is 1, monomial is [3,1,v], coeff is 1
91 if (f->numTerms() != 1) return -1;
92 auto i = f->cbegin();
93 if (!coefficientRing()->is_equal(coefficientRing()->one(), i.coeff())) return -1;
94 return monoid().index_of_variable(i.monom());
95}
96
98{
99 auto result = new Poly;
101 return ring_elem(reinterpret_cast<void *>(result));
102}
103
108
110{
112}
113
114bool M2FreeAlgebra::from_rational(const mpq_srcptr q, ring_elem& result1) const
115{
116 ring_elem cq; // in coeff ring.
117 bool worked = coefficientRing()->from_rational(q, cq);
118 if (!worked) return false;
119 result1 = from_coefficient(cq);
120 return true;
121}
122
124{
125 auto result = new Poly;
126 freeAlgebra().var(*result,v);
127 return ring_elem(reinterpret_cast<void *>(result));
128}
129
130bool M2FreeAlgebra::promote(const Ring *R, const ring_elem f, ring_elem &result) const
131{
132 // std::cout << "called promote NC case" << std::endl;
133 // Currently the only case to handle is R = A --> this, and A is the coefficient ring of this.
134 if (R == coefficientRing())
135 {
137 return true;
138 }
139 return false;
140}
141
142bool M2FreeAlgebra::lift(const Ring *R, const ring_elem f1, ring_elem &result) const
143{
144 // R is the target ring
145 // f1 is an element of 'this'.
146 // set result to be the "lift" of f in the ring R, return true if this is possible.
147 // otherwise return false.
148
149 // case: R is the coefficient ring of 'this'.
150 std::cout << "called lift NC case" << std::endl;
151 if (R == coefficientRing())
152 {
153 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
154 if (f->numTerms() != 1) return false;
155 auto i = f->cbegin();
156 if (monoid().is_one(i.monom()))
157 {
158 result = coefficientRing()->copy(i.coeff());
159 return true;
160 }
161 }
162
163 // at this point, we can't lift it.
164 return false;
165}
166
168{
169 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
170 return freeAlgebra().is_unit(*f);
171}
172
174{
175 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
176 return freeAlgebra().n_terms(*f);
177}
178
180{
181 return n_terms(f1) == 0;
182}
183
184bool M2FreeAlgebra::is_equal(const ring_elem f1, const ring_elem g1) const
185{
186 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
187 auto g = reinterpret_cast<const Poly*>(g1.get_Poly());
188 return freeAlgebra().is_equal(*f,*g);
189}
190
192{
193 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
194 auto g = reinterpret_cast<const Poly*>(g1.get_Poly());
195 return freeAlgebra().compare_elems(*f,*g);
196}
197
199{
200 // FRANK: is this what we want to do?
201 return f;
202}
203
205{
206 (void) f;
207}
208
210{
211 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
212 Poly* result = new Poly;
213 freeAlgebra().negate(*result, *f);
214 return ring_elem(reinterpret_cast<void *>(result));
215}
216
218{
219 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
220 auto g = reinterpret_cast<const Poly*>(g1.get_Poly());
221 auto result = new Poly;
222 freeAlgebra().add(*result,*f,*g);
223 return ring_elem(reinterpret_cast<void *>(result));
224}
225
227{
228 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
229 auto g = reinterpret_cast<const Poly*>(g1.get_Poly());
230 auto result = new Poly;
231 freeAlgebra().subtract(*result,*f,*g);
232 return ring_elem(reinterpret_cast<void *>(result));
233}
234
236{
237 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
238 auto g = reinterpret_cast<const Poly*>(g1.get_Poly());
239 auto result = new Poly;
240 freeAlgebra().mult(*result,*f,*g);
241 return ring_elem(reinterpret_cast<void *>(result));
242}
243
244ring_elem M2FreeAlgebra::power(const ring_elem f1, mpz_srcptr n) const
245{
246 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
247 auto result = new Poly;
248 freeAlgebra().power(*result,*f,n);
249 return ring_elem(reinterpret_cast<void *>(result));
250}
251
253{
254 auto f = reinterpret_cast<const Poly*>(f1.get_Poly());
255 auto result = new Poly;
256 freeAlgebra().power(*result,*f,n);
257 return ring_elem(reinterpret_cast<void *>(result));
258}
259
261{
262 if (not is_unit(f))
263 throw exc::engine_error("attempting to divide by a non-unit");
264
266 // At this point, f should be an element of the coefficient ring, times the monomial 1.
267 // The following will throw an error if it cannot invert the element.
268 ring_elem finv = coefficientRing()->invert(cf);
269 return from_coefficient(finv);
270}
271
273{
274 ring_elem ginv = invert(g); // this will throw an error unless g is invertible in the coeff ring
275 return mult(ginv, f);
276}
277
279 ring_elem &x, ring_elem &y) const
280{
281 (void) a;
282 (void) b;
283 (void) x;
284 (void) y;
285 throw exc::internal_error("M2FreeAlgebra::syzygy is not yet written!");
286
287 // TODO: In the commutative case, this function is to find x and y (as simple as possible)
288 // such that ax + by = 0. No such x and y may exist in the noncommutative case, however.
289 // In this case, the function should return x = y = 0.
290}
291
293{
294 std::cout << "coeffs: ";
295 for (auto i=f->cbeginCoeff(); i != f->cendCoeff(); ++i)
296 {
297 buffer o;
299 std::cout << o.str() << " ";
300 }
301 std::cout << std::endl << " monoms: ";
302 for (auto i=f->cbeginMonom(); i != f->cendMonom(); ++i)
303 {
304 std::cout << (*i) << " ";
305 }
306 std::cout << std::endl;
307}
308
310
311{
312 auto f = reinterpret_cast<const Poly*>(ff.get_Poly());
313 debug_display(f);
314}
315
317{
318 result.getCoeffInserter().push_back(a);
319 monoid().fromMonomial(monom, result.getMonomInserter());
320}
321
323{
324 auto result = new Poly;
325 makeTerm(*result, a, monom);
326 return reinterpret_cast<Nterm*>(result);
327}
328
330 const ring_elem ff,
331 bool p_one,
332 bool p_plus,
333 bool p_parens) const
334{
335 auto f = reinterpret_cast<const Poly*>(ff.get_Poly());
336 freeAlgebra().elem_text_out(o,*f,p_one,p_plus,p_parens);
337}
338
339ring_elem M2FreeAlgebra::eval(const RingMap *map, const ring_elem ff, int first_var) const
340{
341 // map: R --> S, this = R.
342 // f is an ele ment in R
343 // return an element of S.
344 auto f = reinterpret_cast<const Poly*>(ff.get_Poly());
345 return freeAlgebra().eval(map, *f, first_var);
346}
347
349{
350 // Either coeffR should be the actual coefficient ring (possible a "toField"ed ring)
351 // or a polynomial ring. If not, NULL is returned and an error given
352 // In the latter case, the last set of variables are part of
353 // the coefficients.
354
355 auto f = reinterpret_cast<const Poly*>(ff.get_Poly());
356 if (coeffR != coefficientRing())
357 {
358 ERROR("expected coefficient ring");
359 return nullptr;
360 }
361 int nterms = static_cast<int>(f->numTerms());
362 engine_RawMonomialArray monoms = GETMEM(engine_RawMonomialArray, sizeofarray(monoms,nterms));
363 engine_RawRingElementArray coeffs = GETMEM(engine_RawRingElementArray, sizeofarray(coeffs,nterms));
364 engine_RawArrayPair result = newitem(struct engine_RawArrayPair_struct);
365 monoms->len = nterms;
366 coeffs->len = nterms;
367 result->monoms = monoms;
368 result->coeffs = coeffs;
369
370 // fill result
371 std::vector<int> vp;
372 int next = 0;
373 for (auto i=f->cbegin(); i != f->cend(); ++i, ++next)
374 {
375 ring_elem c = coefficientRing()->copy(i.coeff());
376 vp.resize(0);
377 monoid().getMonomialReversed(i.monom(), vp); // should this instead reverse the monomial?
378 coeffs->array[next] = RingElement::make_raw(coeffR, c);
379 monoms->array[next] = EngineMonomial::make(vp); // reverses the monomial
380 }
381
382 return result;
383}
384
385ring_elem M2FreeAlgebra::lead_coefficient(const Ring* coeffRing, const Poly* f) const
386{
387 if (coeffRing != coefficientRing())
388 {
389 throw exc::engine_error("unexpected coefficient ring");
390 }
391 if (f->numTerms() == 0) return coeffRing->zero();
392 return *(f->cbeginCoeff());
393}
394
395Poly* M2FreeAlgebra::get_terms(const Poly* f, int lo, int hi) const
396{
397 auto result = new Poly;
398 auto& outcoeff = result->getCoeffInserter();
399 auto& outmonom = result->getMonomInserter();
400 int which = 0;
401 for(auto i=f->cbegin(); i != f->cend() and which <= hi; ++i, ++which)
402 {
403 if (which < lo) continue;
404 outcoeff.push_back(i.coeff());
405 monoid().copy(i.monom(), outmonom);
406 }
407 return result;
408}
409
411{
412 const Poly* f = reinterpret_cast<const Poly*>(a.get_Poly());
413 return freeAlgebra().support(*f);
414}
415
417{
418 const Poly* f = reinterpret_cast<const Poly*>(f1.get_Poly());
419 return is_homogeneous(f);
420}
421
423{
424 if (f == nullptr) return true;
425 return freeAlgebra().is_homogeneous(*f);
426}
427
429{
430 const Poly* f = reinterpret_cast<const Poly*>(g.get_Poly());
431 return multi_degree(f, d);
432}
433
435{
436 return freeAlgebra().multi_degree(*f, d);
437}
438
443
444// Local Variables:
445// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
446// indent-tabs-mode: nil
447// End:
varpower::ConstExponents const_varpower
PolyList copyPolyVector(const M2FreeAlgebraOrQuotient *A, const PolyList &polys)
Ring-shaped wrapper that exposes a non-commutative FreeAlgebra to the rest of the engine.
Polynomial< CoefficientRingType > Poly
gc_vector< Poly * > PolyList
void appendModuleMonomToMonom(const ModuleMonom &a, int &comp, T &inserter)
static EngineMonomial * make(int v, int e)
Definition monomial.cpp:26
void add(Poly &result, Poly::const_iterator fBegin, Poly::const_iterator fEnd, Poly::const_iterator gBegin, Poly::const_iterator gEnd) const
void power(Poly &result, const Poly &f, int n) const
void negate(Poly &result, const Poly &f) const
bool is_unit(const Poly &f) const
void subtract(Poly &result, const Poly &f, const Poly &g) const
void from_coefficient(Poly &result, const ring_elem a) const
bool is_homogeneous(const Poly &f) const
void mult(Poly &result, const Poly &f, const Poly &g) const
M2_arrayint support(const Poly &f) const
bool multi_degree(const Poly &f, monomial already_allocated_degree_vector) const
void var(Poly &result, int v) const
SumCollector * make_SumCollector() const
static FreeAlgebra * create(const Ring *K, const std::vector< std::string > &names, const PolynomialRing *degreeRing, const std::vector< int > &degrees, const std::vector< int > &wtvecs, const std::vector< int > &heftVector)
void elem_text_out(buffer &o, const Poly &f, bool p_one, bool p_plus, bool p_parens) const
bool is_equal(const Poly &f, const Poly &g) const
long n_terms(const Poly &f) const
ring_elem eval(const RingMap *map, const Poly &f, int first_var) const
int compare_elems(const Poly &f, const Poly &g) const
void getMonomialReversed(Monom monom, std::vector< int > &result) const
void fromMonomial(const_monomial monom, MonomialInserter &result) const
const std::vector< std::string > & variableNames() const
void copy(const Monom &m, MonomialInserter &result) const
int index_of_variable(const Monom &m) const
virtual M2_arrayint support(const ring_elem a) const
long n_terms(const ring_elem f) const
void debug_display(const Poly *f) const
virtual bool multi_degree(const ring_elem f, monomial d) const
virtual void syzygy(const ring_elem a, const ring_elem b, ring_elem &x, ring_elem &y) const
virtual ring_elem from_coefficient(const ring_elem a) const
virtual bool lift(const Ring *R, const ring_elem f, ring_elem &result) const
virtual ring_elem add(const ring_elem f, const ring_elem g) const
virtual ring_elem copy(const ring_elem f) const
virtual bool is_homogeneous(const ring_elem f) const
virtual ring_elem invert(const ring_elem f) const
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const
ring_elem lead_coefficient(const Ring *coeffRing, const Poly *f) const
const FreeAlgebra & freeAlgebra() const
virtual ring_elem mult(const ring_elem f, const ring_elem g) const
virtual bool is_equal(const ring_elem f, const ring_elem g) const
virtual bool is_zero(const ring_elem f) const
const Ring * coefficientRing() const
virtual bool promote(const Ring *R, const ring_elem f, ring_elem &result) const
virtual ring_elem var(int v) const
virtual void text_out(buffer &o) const
virtual int compare_elems(const ring_elem f, const ring_elem g) const
const FreeMonoid & monoid() const
M2FreeAlgebra(std::unique_ptr< FreeAlgebra > F)
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
virtual bool is_unit(const ring_elem f) const
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one, bool p_plus, bool p_parens) const
ring_elem makeTerm(const ring_elem a, const_varpower monom) const
virtual bool from_rational(const mpq_srcptr q, ring_elem &result) const
virtual int index_of_var(const ring_elem a) const
virtual ring_elem divide(const ring_elem f, const ring_elem g) const
virtual ring_elem power(const ring_elem f, mpz_srcptr n) const
Exponentiation. This is the default function, if a class doesn't define this.
static M2FreeAlgebra * create(const Ring *K, const std::vector< std::string > &names, const PolynomialRing *degreeRing, const std::vector< int > &degrees, const std::vector< int > &wtvecs, const std::vector< int > &heftVector)
Poly * get_terms(const Poly *f, int lo, int hi) const
const std::unique_ptr< FreeAlgebra > mFreeAlgebra
virtual engine_RawArrayPairOrNull list_form(const Ring *coeffR, const ring_elem f) const
virtual SumCollector * make_SumCollector() const
virtual unsigned int computeHashValue(const ring_elem a) const
const PolynomialRing * degreeRing() const
virtual ring_elem from_int(mpz_srcptr n) const
virtual ring_elem from_long(long n) const
virtual void remove(ring_elem &f) const
virtual ring_elem negate(const ring_elem f) const
ring_elem fromPoly(Poly *f) const
void appendFromModuleMonom(Poly &f, const ModuleMonom &m) const
ring_elem fromModuleMonom(const ModuleMonom &m) const
virtual const FreeAlgebra & freeAlgebra() const =0
virtual const Ring * coefficientRing() const =0
Abstract Ring subclass that lifts either a FreeAlgebra or a FreeAlgebraQuotient into the engine's Rin...
Monom extended with a module component, a stored index, and a memoised hash — the value type of IntsS...
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual void text_out(buffer &o) const =0
ring_elem one() const
Definition ring.hpp:357
ring_elem zero() const
Definition ring.hpp:359
virtual ring_elem invert(const ring_elem f) const =0
virtual ring_elem from_long(long n) const =0
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one=true, bool p_plus=false, bool p_parens=false) const =0
long characteristic() const
Definition ring.hpp:159
virtual ring_elem copy(const ring_elem f) const =0
virtual bool from_rational(const mpq_srcptr q, ring_elem &result) const =0
Ring()
Definition ring.hpp:136
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
Abstract incremental accumulator that builds a ring_elem from many add(f) calls.
Definition ring.hpp:669
char * str()
Definition buffer.hpp:72
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
#define monomial
Definition gb-toric.cpp:11
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define sizeofarray(s, len)
Definition m2-mem.h:129
struct engine_RawArrayPair_struct * engine_RawArrayPair
Definition m2-types.h:183
engine_RawArrayPair engine_RawArrayPairOrNull
Definition m2-types.h:184
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
EngineMonomial — opaque single-monomial value type used at the engine boundary.
STL namespace.
#define newitem(T)
Definition newdelete.hpp:86
#define GETMEM(T, size)
volatile int x
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
TermIterator< Nterm > end(Nterm *)
Definition ringelem.cpp:5
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
const void * get_Poly() const
Definition ringelem.hpp:128