Macaulay2 Engine
Loading...
Searching...
No Matches
aring.cpp
Go to the documentation of this file.
1#include "interface/aring.h"
2
3#include <algorithm>
4#include <utility>
5#include <vector>
6#include <memory>
7
8#include "aring-glue.hpp"
9#include "aring-m2-gf.hpp"
10#include "aring-qq.hpp"
11#include "aring-tower.hpp"
12#include "aring-zzp-ffpack.hpp"
13#include "aring-zzp.hpp"
14#include "exceptions.hpp"
15#include "polyring.hpp"
16#include "relem.hpp"
17
18// include flint headers last to avoid #1674
20#include "aring-gf-flint.hpp"
21#include "aring-zz-flint.hpp"
22#include "aring-zzp-flint.hpp"
23
25
30
31const RingQQ *rawARingQQ() { return globalQQ; }
32const Ring * /* or null */ rawARingZZFlint()
33{
35}
36
37const Ring * /* or null */ rawARingQQFlint()
38{
40}
41
42const Ring /* or null */ *rawARingZZp(unsigned long p)
43{
44 if (p <= 1 || p >= 32750)
45 {
46 ERROR("ZZP: expected a prime number p in range 2 <= p <= 32749");
47 return nullptr;
48 }
50}
51const Ring /* or null */ *rawARingZZpFlint(unsigned long p)
52{
54}
55
56static const PolynomialRing * /* or null */ checkGaloisFieldInput(
57 const RingElement *f)
58{
59 // Check that the ring R of f is a polynomial ring in one var over a ZZ/p
60 // Check that f is monic
61 // If any of these fail, then return 0.
63 if (R == nullptr)
64 {
65 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
66 return nullptr;
67 }
68 if (R->n_vars() != 1)
69 {
70 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
71 return nullptr;
72 }
73 if (R->n_quotients() != 1)
74 {
75 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
76 return nullptr;
77 }
78 if (R->characteristic() == 0)
79 {
80 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
81 return nullptr;
82 }
83 return R;
84}
85const Ring /* or null */ *rawARingGaloisField1(const RingElement *f)
86{
88 if (R == nullptr) return nullptr; // error message has already been logged
89 try
90 {
92 } catch (const exc::engine_error& e)
93 {
94 ERROR(e.what());
95 return nullptr;
96 }
97}
98const Ring /* or null */ *rawARingGaloisFieldFlintBig(const RingElement *f)
99{
101 if (R == nullptr) return nullptr; // error message has already been logged
102 try
103 {
105 } catch (const exc::engine_error& e)
106 {
107 ERROR(e.what());
108 return nullptr;
109 }
110}
111
112const Ring /* or null */ *rawARingGaloisFieldFlintZech(const RingElement *f)
113{
115 if (R == nullptr) return nullptr; // error message has already been logged
116 try
117 {
119 } catch (const exc::engine_error& e)
120 {
121 ERROR(e.what());
122 return nullptr;
123 }
124}
125
136
137// TODO: remove this function during givaro removal
138const Ring /* or null */ *rawARingGaloisField(int prime, int dimension)
139{
140 if (dimension < 0)
141 {
142 ERROR(" givaroGF/FFPACK: help, dimension is negative ! ");
143 return nullptr;
144 }
145 try
146 {
147#if 1
148
149 if (prime <= 1)
150 {
151 ERROR("givaroGF/FFPACK: expected a prime number p ");
152 return nullptr;
153 }
154
155 //-- NEED_POLYNOMIAL_REPRESENTATION is not usable(namespace problems) and
156 // is not correct, because the answer depends on the template used for
157 // Givaro::GFqDom.
158 /*if (Givaro::NEED_POLYNOMIAL_REPRESENTATION(prime,dimension) )
159 {
160 ERROR("givaro Galois Field: polynomial representation is needed -
161 todo ");
162 return 0;
163 }*/
164 if (dimension == 1 && M2::ARingZZpFFPACK::getMaxModulus() > prime)
165 {
166 // std::cout << "maximum modulus = " <<
167 // M2::ARingZZpFFPACK::getMaxModulus() << std::endl;
169 }
170 if (dimension == 1)
171 {
172 ERROR("maximum modulus = %f\n", M2::ARingZZpFFPACK::getMaxModulus());
173 return nullptr;
174 }
175 #if 0
176 return M2::ConcreteRing<M2::ARingGFGivaro>::create(prime, dimension);
177 #endif
178 ERROR("calling rawARingGaloisField with no longer allowed values, givaro is no longer available");
179 return nullptr;
180#else
181 ERROR("add --enable-fflas-ffpack --enable-givaro when building M2");
182 return 0;
183#endif
184 } catch (const exc::engine_error& e)
185 {
186 ERROR(e.what());
187 return nullptr;
188 }
189}
190
191#if 0
192// TODO: remove this function during givaro removal
193const Ring /* or null */ *rawARingGaloisFieldFromQuotient(const RingElement *a)
194{
195 // Check that the ring R of f is a polynomial ring in one var over a ZZ/p
196 // Check that f has degree >= 2
197 // Check that f is monic
198 // If any of these fail, then return 0.
200 if (R == 0)
201 {
202 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
203 return 0;
204 }
205 if (R->n_vars() != 1)
206 {
207 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
208 return 0;
209 }
210 if (R->n_quotients() != 1)
211 {
212 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
213 return 0;
214 }
215 if (R->characteristic() == 0)
216 {
217 ERROR("expected poly ring of the form ZZ/p[x]/(f)");
218 return 0;
219 }
220
221 if (!R->is_equal(a->get_value(), R->var(0)))
222 {
223 ERROR(
224 "primitive element needs to be the generator of the ring, we "
225 "think...!");
226 return 0;
227 }
228
229 try
230 {
231 RingElement F(R, R->quotient_element(0));
232 M2_arrayint modPoly = F.getSmallIntegerCoefficients();
233 if (modPoly == 0)
234 {
235 ERROR("internal error: this should not happen");
236 return NULL;
237 }
238 M2_arrayint primitiveElementPoly = a->getSmallIntegerCoefficients();
239 if (primitiveElementPoly == 0) return NULL;
240
242 R->characteristic(), modPoly, primitiveElementPoly, *R);
243 } catch (const exc::engine_error& e)
244 {
245 ERROR(e.what());
246 return NULL;
247 }
248}
249#endif
250
251
252#if 0
253// TODO: remove this function during givaro removal
255{
256#if 1
258 dynamic_cast<const M2::ConcreteRing<M2::ARingGFGivaro> *>(R);
259 if (RGF == 0)
260 {
261 ERROR("expected a GaloisField");
262 return 0;
263 }
264 const M2::ARingGFGivaro &A = RGF->ring();
265 return A.getModPolynomialCoeffs();
266#else
267 ERROR("add --enable-fflas-ffpack --enable-givaro when building M2");
268 return 0;
269#endif
270}
271#endif
272
273#if 0
274// TODO: remove this function during givaro removal
276{
277#if 1
279 dynamic_cast<const M2::ConcreteRing<M2::ARingGFGivaro> *>(f->get_ring());
280 if (RGF == 0)
281 {
282 ERROR("expected a GaloisField");
283 return 0;
284 }
285 const M2::ARingGFGivaro &A = RGF->ring();
286 M2::ARingGFGivaro::ElementType a;
287 A.from_ring_elem(a, f->get_value());
288 return A.fieldElementToM2Array(a);
289#else
290 ERROR("add --enable-fflas-ffpack --enable-givaro when building M2");
291 return 0;
292#endif
293}
294#endif
295
296const Ring /* or null */ *rawARingTower1(const Ring *K, M2_ArrayString names)
297{
298 try
299 {
301 dynamic_cast<const M2::ConcreteRing<M2::ARingZZpFFPACK> *>(K);
302 if (Kp == nullptr)
303 {
304 ERROR("expected a base ring ZZ/p");
305 return nullptr;
306 }
307 const M2::ARingZZpFFPACK &A = Kp->ring();
308
309 // Get the names into the correct form:
310 auto varnames = M2_ArrayString_to_stdvector(names);
313 std::unique_ptr<M2::ARingTower>(T));
314 } catch (const exc::engine_error& e)
315 {
316 ERROR(e.what());
317 return nullptr;
318 }
319}
320
321const Ring /* or null */ *rawARingTower2(const Ring *R1,
322 M2_ArrayString new_names)
323{
324 try
325 {
327 dynamic_cast<const M2::ConcreteRing<M2::ARingTower> *>(R1);
328 if (K == nullptr)
329 {
330 ERROR("expected a tower ring");
331 return nullptr;
332 }
333 const M2::ARingTower &A = K->ring();
334
335 auto new_varnames = M2_ArrayString_to_stdvector(new_names);
336 M2::ARingTower *T = M2::ARingTower::create(A, new_varnames);
338 std::unique_ptr<M2::ARingTower>(T));
339 } catch (const exc::engine_error& e)
340 {
341 ERROR(e.what());
342 return nullptr;
343 }
344}
345
346const Ring /* or null */ *rawARingTower3(const Ring *R1,
347 engine_RawRingElementArray eqns)
348{
349 try
350 {
352 dynamic_cast<const M2::ConcreteRing<M2::ARingTower> *>(R1);
353 if (K == nullptr)
354 {
355 ERROR("expected a tower ring");
356 return nullptr;
357 }
358 const M2::ARingTower &A = K->ring();
359
360 std::vector<M2::ARingTower::ElementType> extensions;
361
362 for (int i = 0; i < eqns->len; i++)
363 {
364 const RingElement *f = eqns->array[i];
366 if (f->get_ring() != R1)
367 {
368 ERROR("extension element has incorrect base ring");
369 return nullptr;
370 }
371 A.from_ring_elem(f1, f->get_value());
372 extensions.push_back(f1);
373 }
374 M2::ARingTower *T = M2::ARingTower::create(A, extensions);
376 std::unique_ptr<M2::ARingTower>(T));
377 } catch (const exc::engine_error& e)
378 {
379 ERROR(e.what());
380 return nullptr;
381 }
382}
383
384// Local Variables:
385// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
386// indent-tabs-mode: nil
387// End:
M2::ARingGFFlintBig — arbitrary-degree GF(p^k) via FLINT fq_nmod.
M2::ARingGFFlint — small GF(p^k) via FLINT Zech-logarithm tables.
M2::RingQQ RingQQ
const RingQQ * globalQQ
Definition aring.cpp:24
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
M2::ARingGFM2 — native engine Galois field, no FLINT dependency.
Tiny dispatcher header that picks the default ARingQQ from among the QQ aring implementations.
M2::ARingTower — iterated finite-field extension tower for very large GF(p^k).
M2::ARingZZ — FLINT-backed arbitrary-precision integers with small-value inlining.
M2::ARingZZpFFPACK — Z/p via FFLAS-FFPACK's Givaro::Modular<double> field.
M2::ARingZZpFlint — Z/p via FLINT's nmod_t precomputed-reciprocal reduction.
M2::ARingZZp — portable Z/p for small primes via log / exp tables.
M2_arrayintOrNull rawARingGFPolynomial(const Ring *R)
M2_arrayintOrNull rawARingGFCoefficients(const RingElement *f)
const Ring * rawARingGaloisFieldFromQuotient(const RingElement *prim)
Engine-boundary C API for constructing aring-backed coefficient rings.
ARingPolynomial ElementType
void from_ring_elem(ElementType &result, const ring_elem &a) const
static ARingTower * create(const BaseRingType &baseRing, const std::vector< std::string > &names)
aring-style coefficient ring for tower polynomial rings (Z/p)[x_0][x_1]...[x_{n-1}...
static double getMaxModulus()
wrapper for the FFPACK::ModularBalanced<double> field implementation
const RingType & ring() const
static ConcreteRing< RingType > * create(std::unique_ptr< RingType > R)
static RingQQ * create()
int n_quotients() const
Definition polyring.hpp:219
virtual ring_elem var(int v) const =0
Nterm * quotient_element(int i) const
Definition polyring.hpp:220
int n_vars() const
Definition polyring.hpp:196
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual bool is_equal(const ring_elem f, const ring_elem g) const =0
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
long characteristic() const
Definition ring.hpp:159
ring_elem get_value() const
Definition relem.hpp:79
bool getSmallIntegerCoefficients(std::vector< long > &result_coeffs) const
Definition relem.cpp:421
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
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
int p
const Ring * rawARingGaloisFieldFlintZech(const RingElement *f)
Definition aring.cpp:112
const Ring * rawARingGaloisField1(const RingElement *f)
Definition aring.cpp:85
static const PolynomialRing * checkGaloisFieldInput(const RingElement *f)
Definition aring.cpp:56
const Ring * rawARingGaloisField(int prime, int dimension)
Definition aring.cpp:138
const Ring * rawARingTower3(const Ring *R1, engine_RawRingElementArray eqns)
Definition aring.cpp:346
void initializeRationalRing()
Definition aring.cpp:26
const Ring * rawARingQQFlint()
Definition aring.cpp:37
const RingQQ * rawARingQQ()
Definition aring.cpp:31
const Ring * rawARingZZFlint()
Definition aring.cpp:32
const Ring * rawARingTower2(const Ring *R1, M2_ArrayString new_names)
Definition aring.cpp:321
const Ring * rawARingZZp(unsigned long p)
Definition aring.cpp:42
const Ring * rawARingGaloisFieldFlintBig(const RingElement *f)
Definition aring.cpp:98
const Ring * rawARingZZpFlint(unsigned long p)
Definition aring.cpp:51
const Ring * rawARingTower1(const Ring *K, M2_ArrayString names)
Definition aring.cpp:296
const int ERROR
Definition m2-mem.cpp:55
M2_arrayint M2_arrayintOrNull
Definition m2-types.h:99
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
#define T
Definition table.c:13
void M2_ArrayString_to_stdvector(M2_ArrayString strs, std::vector< std::string > &result)
Definition util.hpp:52