Macaulay2 Engine
Loading...
Searching...
No Matches
ringmap.cpp
Go to the documentation of this file.
1// Copyright 1996 Michael E. Stillman
2
3#include "ringmap.hpp"
4#include "matrix.hpp"
5#include "matrix-con.hpp"
6#include "polyring.hpp"
7#include "relem.hpp"
8
9#include <iostream>
11{
12 M = nullptr;
13 P = R->cast_to_PolynomialRing();
14 if (P != nullptr)
15 {
16 M = P->getMonoid();
17 K = P->getCoefficientRing();
18 }
19 else
20 K = R;
21
22 nvars = m->n_cols();
23 is_monomial = true;
24
25 ring_elem one = K->from_long(1);
26
27 // Allocate space for the ring map elements
28 _elem = new var[nvars];
29
30 for (int i = 0; i < nvars; i++)
31 {
32 // First initialize these fields:
33 _elem[i].is_zero = false;
34 _elem[i].coeff_is_one = true;
35 _elem[i].monom_is_one = true;
36 _elem[i].bigelem_is_one = true;
37 _elem[i].coeff = ZERO_RINGELEM;
38 _elem[i].monom = nullptr;
39
40 ring_elem f = m->elem(0, i); // This does a copy.
41 _elem[i].bigelem = f;
42
43 if (R->is_zero(f))
44 _elem[i].is_zero = true;
45 else if (P == nullptr)
46 {
47 // Not a polynomial ring, so put everything into coeff
48 if (!K->is_equal(f, one))
49 {
50 _elem[i].coeff_is_one = false;
51 _elem[i].coeff = K->copy(f);
52 }
53 }
54 else
55 {
56// A polynomial ring.
57#ifdef DEVELOPMENT
58#warning "also handle fraction rings"
59#endif
60 Nterm *t = f;
61 if (t->next == nullptr)
62 {
63 // This is a single term
64 if (!K->is_equal(t->coeff, one))
65 {
66 _elem[i].coeff_is_one = false;
67 _elem[i].coeff = K->copy(t->coeff);
68 }
69
70 if (!M->is_one(t->monom)) // should handle M->n_vars() == 0 case
71 // correctly.
72 {
73 _elem[i].monom_is_one = false;
74 _elem[i].monom = M->make_new(t->monom);
75 }
76 }
77 else
78 {
79 // This is a bigterm
80 is_monomial = false;
81 _elem[i].bigelem_is_one = false;
82 }
83 }
84 K->remove(one);
85 }
86}
87
89{
90 for (int i = 0; i < nvars; i++)
91 {
92 if (!_elem[i].coeff_is_one) K->remove(_elem[i].coeff);
93 if (!_elem[i].monom_is_one) M->remove(_elem[i].monom);
94 R->remove(_elem[i].bigelem);
95 }
97 K = nullptr;
98 M = nullptr;
99}
100
101unsigned int RingMap::computeHashValue() const
102{
103 unsigned int hashval = 4565 * get_ring()->hash();
104 for (int i = 0; i < nvars; i++)
105 {
106 hashval =
107 46343 * hashval + get_ring()->computeHashValue(_elem[i].bigelem);
108 }
109 return hashval;
110}
111bool RingMap::is_equal(const RingMap *phi) const
112{
113 // Two ringmap's are identical if their 'bigelem's are the same
114 if (R != phi->get_ring()) return false;
115 if (nvars != phi->nvars) return false;
116
117 for (int i = 0; i < nvars; i++)
118 if (!R->is_equal(elem(i), phi->elem(i))) return false;
119
120 return true;
121}
122
124{
125 RingMap *result = new RingMap(m);
126 return result;
127}
128
130{
131 o << "(";
132 for (int i = 0; i < nvars; i++)
133 {
134 if (i > 0) o << ", ";
135 R->elem_text_out(o, _elem[i].bigelem);
136 }
137 o << ")";
138}
139
140ring_elem RingMap::eval_term(const Ring *sourceK, // source coeff ring
141 const ring_elem a, // coefficient of term
143 int first_var,
144 int nvars_in_source) const
145{
146 for (index_varpower i = vp; i.valid(); ++i)
147 {
148 int v = first_var + i.var();
149 if (v >= nvars || _elem[v].is_zero)
150 return R->from_long(0); // The result is zero.
151 }
152
153 // If K is a coeff ring of R, AND map is an identity on K,
154 // then don't recurse: use this value directly.
155 // Otherwise, we must recurse, I guess.
156 ring_elem result = sourceK->eval(this, a, first_var + nvars_in_source);
157 if (R->is_zero(result)) return result;
158
159 monomial result_monom = nullptr;
160 monomial temp_monom = nullptr;
161 ring_elem result_coeff = K->from_long(1);
162
163 if (P != nullptr)
164 {
165 result_monom = M->make_one();
166 temp_monom = M->make_one();
167 }
168
169 if (!R->is_commutative_ring() || R->cast_to_SchurRing())
170 {
171 // This is the only non-commutative case so far
172 for (index_varpower i = vp; i.valid(); ++i)
173 {
174 int v = first_var + i.var();
175 int e = i.exponent();
176 ring_elem g;
177 if (e >= 0)
178 g = _elem[v].bigelem;
179 else
180 g = R->invert(_elem[v].bigelem);
181 for (int j = 0; j < e; j++)
182 {
183 assert(v < nvars);
184 ring_elem tmp = R->mult(g, result);
185 R->remove(result);
186 result = tmp;
187 }
188 }
189 }
190 else
191 {
192 for (index_varpower i = vp; i.valid(); ++i)
193 {
194 int v = first_var + i.var();
195 int e = i.exponent();
196 assert(v < nvars);
197 if (_elem[v].bigelem_is_one && e > 0)
198 {
199 if (!_elem[v].coeff_is_one)
200 {
201 ring_elem tmp = K->power(_elem[v].coeff, e);
202 K->mult_to(result_coeff, tmp);
203 K->remove(tmp);
204 }
205 if (!_elem[v].monom_is_one)
206 {
207 M->power(_elem[v].monom, e, temp_monom);
208 M->mult(result_monom, temp_monom, result_monom);
209 }
210 }
211 else
212 {
213 ring_elem thispart = R->power(_elem[v].bigelem, e);
214 R->mult_to(result, thispart);
215 R->remove(thispart);
216 if (R->is_zero(result)) break;
217 }
218 }
219 if (P != nullptr)
220 {
221 ring_elem temp = P->make_flat_term(result_coeff, result_monom);
222 K->remove(result_coeff);
223 M->remove(result_monom);
224 M->remove(temp_monom);
225 P->mult_to(result, temp);
226 P->remove(temp);
227 }
228 else
229 {
230 // result_monom has not been used
231 // and result, result_coeff are both in the ring K
232 result = K->mult(result, result_coeff);
233 }
234 }
235 return result;
236}
237
238RingElement /* or null */ *RingMap::eval(const RingElement *r) const
239{
241 get_ring(), r->get_ring()->eval(this, r->get_value(), 0));
242 if (error()) return nullptr;
243 return result;
244}
245
246Matrix /* or null */ *RingMap::eval(const FreeModule *F, const Matrix *m) const
247{
248 MatrixConstructor mat(F, 0);
249 for (int i = 0; i < m->n_cols(); i++)
250 mat.append(m->get_ring()->vec_eval(this, F, m->elem(i)));
251 if (error()) return nullptr;
252 return mat.to_matrix();
253}
254
255// Local Variables:
256// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
257// indent-tabs-mode: nil
258// End:
varpower::ConstExponents const_varpower
ExponentListIterator< int, true > index_varpower
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
const Ring * get_ring() const
Definition matrix.hpp:134
ring_elem elem(int i, int j) const
Definition matrix.cpp:307
int n_cols() const
Definition matrix.hpp:147
Matrix * to_matrix()
void append(vec v)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
unsigned int hash() const
Definition hash.hpp:106
virtual unsigned int computeHashValue(const ring_elem a) const =0
vec vec_eval(const RingMap *map, const FreeModule *F, const vec v) const
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const =0
ring_elem get_value() const
Definition relem.hpp:79
static RingElement * make_raw(const Ring *R, ring_elem f)
Definition relem.cpp:20
const Ring * get_ring() const
Definition relem.hpp:81
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
xxx xxx xxx
Definition ring.hpp:102
RingMap(const Matrix *m)
Definition ringmap.cpp:10
~RingMap()
Definition ringmap.cpp:88
const ring_elem elem(int i) const
Definition ringmap.hpp:114
const Monoid * M
Definition ringmap.hpp:93
bool is_equal(const RingMap *phi) const
Definition ringmap.cpp:111
const Ring * R
Definition ringmap.hpp:89
const Ring * K
Definition ringmap.hpp:92
bool is_monomial
Definition ringmap.hpp:95
virtual unsigned int computeHashValue() const
Definition ringmap.cpp:101
const Ring * get_ring() const
Definition ringmap.hpp:111
const PolynomialRing * P
Definition ringmap.hpp:91
int nvars
Definition ringmap.hpp:98
var * _elem
Definition ringmap.hpp:99
void text_out(buffer &o) const
Definition ringmap.cpp:129
static const RingMap * make(const Matrix *m)
Definition ringmap.cpp:123
RingElement * eval(const RingElement *r) const
Definition ringmap.cpp:238
ring_elem eval_term(const Ring *coeff_ring, const ring_elem coeff, const int *vp, int first_var, int nvars_in_source) const
Definition ringmap.cpp:140
int error()
Definition error.c:48
#define Matrix
Definition factory.cpp:14
#define monomial
Definition gb-toric.cpp:11
void freemem(void *s)
Definition m2-mem.cpp:103
VALGRIND_MAKE_MEM_DEFINED & result(result)
MatrixConstructor — the mutable builder that produces an immutable Matrix.
Matrix — the engine's immutable homomorphism F -> G between free modules.
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
#define ZERO_RINGELEM
Definition ring.hpp:677
RingMap — engine representation of a ring homomorphism.
Nterm * next
Definition ringelem.hpp:157
ring_elem coeff
Definition ringelem.hpp:158
int monom[1]
Definition ringelem.hpp:160
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
Per-source-variable image record: a factored representation of the target-ring element that variable ...
Definition ringmap.hpp:73