Macaulay2 Engine
Loading...
Searching...
No Matches
VectorArithmetic.hpp
Go to the documentation of this file.
1#ifndef __vector_arithmetic_hpp__
2#define __vector_arithmetic_hpp__
3
38
39// #include <utility> // for swap
40// #include <assert.h> // for assert
41// #include <stddef.h> // for size_t
42// #include <iostream> // for operator<<, ostream, endl, basic_...
43// #include <variant> // for visit, variant
44// #include <vector> // for vector
45
46// #include "m2tbb.hpp" // for null_mutex
47
48// #include "ARingElem.hpp" // for ARingElem
49// #include "NCAlgebras/Range.hpp" // for Range
50// #include "ZZp.hpp" // for Z_mod
51// #include "aring-glue.hpp" // for ConcreteRing
52// #include "aring.hpp" // for DummyRing, ring_GFFlintBig, ring_...
53// #include "buffer.hpp" // for buffer
54// #include "ring.hpp" // for Ring
55// #include "ringelem.hpp" // for ring_elem
56
57// class CoefficientRingR;
58// class CoefficientRingZZp;
59// class MemoryBlock;
60// namespace M2 { class ARingGFFlint; }
61// namespace M2 { class ARingGFFlintBig; }
62// namespace M2 { class ARingGFGivaro; }
63// namespace M2 { class ARingGFM2; }
64// namespace M2 { class ARingQQGMP; }
65// namespace M2 { class ARingZZp; }
66// namespace M2 { class ARingZZpFFPACK; }
67// namespace M2 { class ARingZZpFlint; }
68
69
70
71#include "m2tbb.hpp"
72#include "NCAlgebras/Range.hpp" // for Range
73#include "newdelete.hpp" // for VECTOR
74#include "MemoryBlock.hpp" // for MemoryBlock
75#include "ringelem.hpp"
76#include "aring-glue.hpp"
77#include <variant>
78#include <type_traits>
79
80class Ring;
81using ComponentIndex = int;
82
98{
99 template<typename RingType> friend class ConcreteVectorArithmetic;
100
101public:
102 ElementArray() : mValue(nullptr) {}
103 bool isNull() const { return mValue == nullptr; }
105
106private:
107 // disallow copy...
108 ElementArray(void *p) : mValue(p) {} // transfers ownership of this pointer to this object
109
110 //ElementArray(ElementArray &b) { mValue = nullptr; std::swap(mValue,b.mValue); }
111 //ElementArray(const ElementArray && b) : mValue(b.mValue) { b.mValue = nullptr; }
112 //ElementArray(ElementArray &b) = delete;
113 void* getValue() const { return mValue; }
114 void setValue(void* newValue) { mValue = newValue; }
115
116 void* mValue;
117};
118
131{
132 mutable long mNumAdditions;
133public:
135
137 long numAdditions() const { return mNumAdditions; }
138};
139
140template<typename RingType>
142{
143public:
144 using FieldElement = typename RingType::ElementType;
145
146 using ElementArrayContainer = typename RingType::ElementContainerType;
147 // we may want to change the container type of dense vectors in the future.
148
149 friend class VectorArithmetic;
150
152
153 private:
155 const RingType* mRing;
157
159 {
160 return reinterpret_cast<ElementArrayContainer*>(f.getValue());
161 }
162
163public:
164 ConcreteVectorArithmetic(const Ring* origR, const RingType* R) : mOriginalRing(origR), mRing(R) {}
165
166 const Ring* ring() const { return mOriginalRing; }
167
168 const VectorArithmeticStats& stats() const {return mStats; }
169
171 // Allocation/Deallocation //
174 {
175 auto& v = * elementArray(sparse);
176 auto tempPtr = new ElementArrayContainer(v.size());
177
178 int n = 0;
179 for (auto& d : *tempPtr)
180 {
181 mRing->init_set(d, v[n]);
182 ++n;
183 }
184 return ElementArray {tempPtr};
185 }
186
188 {
189 auto tempPtr = new ElementArrayContainer(nelems);
190 for (auto& d : *tempPtr)
191 {
192 mRing->init(d);
193 mRing->set_zero(d);
194 }
195 return ElementArray {tempPtr};
196 }
197
199 {
200 return allocateElementArray(0);
201 }
202
204 {
205 auto& svec = * elementArray(coeffs);
206 for (auto& e : svec) {
207 mRing->clear(e);
208 }
209 delete &svec;
210 coeffs.setValue(nullptr);
211 }
212
216
217 size_t size(const ElementArray& coeffs) const
218 {
219 return elementArray(coeffs)->size();
220 }
221
223 const ElementArray& sparse,
224 const Range<const int>& comps) const
225 {
226 // Note: this function simply fills in the values coming from '(sparse, comps)'.
227 // Other values are not touched.
228 // In our intended uses, the input `dense` is the vector consisting of all zeros.
229
230 auto& dvec = * elementArray(dense);
231 auto& svec = * elementArray(sparse);
232
233 assert(comps.size() == svec.size());
234 assert(comps[comps.size()-1] < dvec.size());
235
236 auto len = comps.size();
237 for (ComponentIndex i = 0; i < len; i++) mRing->set(dvec[comps[i]],svec[i]);
238 }
239
241 const ElementArray& sparse,
242 const Range<const int>& comps) const
243 {
244 // ASSUMPTION: svec[0] == 1.
245 auto& dvec = * elementArray(dense);
246 auto& svec = * elementArray(sparse);
247
248 typename RingType::Element a(*mRing,dvec[comps[0]]);
249 for (int i=1; i < comps.size(); ++i)
250 mRing->subtract_multiple(dvec[comps[i]], a, svec[i]);
251 mRing->set_zero(dvec[comps[0]]);
252 }
253
255 const ElementArray& sparse,
256 const Range<const int>& comps,
257 ElementArray& result_multiplier) const
258 {
259 // ASSUMPTION: svec[0] == 1, comps.size() >= 1
260 auto& dvec = * elementArray(dense);
261 auto& svec = * elementArray(sparse);
262 auto& mults = * elementArray(result_multiplier);
263
264 FieldElement b;
265 mRing->init(b);
266 mRing->set(b, dvec[comps[0]]);
267
268 FieldElement one;
269 mRing->init(one);
270 mRing->set_from_long(one, 1);
271 if (not mRing->is_equal(svec[0], one)) // should be minus_one
272 mRing->negate(b, b);
273
274 for (int i=1; i < comps.size(); ++i)
275 {
276 mRing->subtract_multiple(dvec[comps[i]], b, svec[i]);
277 mStats.incrementNumAdditions();
278 }
279 mRing->set_zero(dvec[comps[0]]);
280
281 mRing->negate(b, b);
282 mults.push_back(b); // this transfers ownership of b.
283 }
284
286 int first,
287 int last) const
288 {
289 auto& dvec = * elementArray(dense);
290 for (int i = first; i <= last; i++)
291 {
292 if (mRing->is_zero(dvec[i])) continue;
293 // these lines give the gist of how to handle delayed modulus
294 //if (dvec[i] > mCharacteristic) dvec[i] %= mCharacteristic;
295 //else if (dvec[i] < 0) dvec[i] %= mCharacteristic;
296 //if (dvec[i] == 0) continue;
297 return i;
298 }
299 return last + 1;
300 }
301
303 ElementArray& sparse, // output value: sets this value
304 Range<int>& comps, // output value: sets comps
305 int first,
306 int last,
307 MemoryBlock& monomialSpace) const
308 {
309 mtbb::null_mutex noLock;
311 sparse,
312 comps,
313 first,
314 last,
315 monomialSpace,
316 noLock);
317 }
318
319 template<typename LockType>
321 ElementArray& sparse, // output value: sets this value
322 Range<int>& comps, // output value: sets comps
323 int first,
324 int last,
325 MemoryBlock& monomialSpace,
326 LockType& lock) const
327 {
328 auto& dvec = * elementArray(dense);
329
330 int len = 0;
331
332 // first can be -1 if the row is zero. in this case, we should
333 // not be accessing dense[i] for i negative.
334 for (int i = first; i >= 0 and i <= last; i++)
335 if (not mRing->is_zero(dvec[i])) len++;
336
337 comps = monomialSpace.safeAllocateArray<int,LockType>(len,lock);
339 sparse = allocateElementArray(len);
340 auto& svec = * elementArray(sparse);
341
342 int next = 0;
343 for (int i = first; i >= 0 and i <= last; i++)
344 if (not mRing->is_zero(dvec[i]))
345 {
346 mRing->set(svec[next],dvec[i]);
347 comps[next] = i;
348 ++next;
349 mRing->set_zero(dvec[i]);
350 }
351 }
352
354 ElementArray& sparse, // output value: sets this value
355 int*& comps,
356 int first,
357 int last) const
358 {
359 auto& dvec = * elementArray(dense);
360
361 int len = 0;
362
363 // first can be -1 if the row is zero. in this case, we should
364 // not be accessing dense[i] for i negative.
365 for (int i = first; i >= 0 and i <= last; i++)
366 if (not mRing->is_zero(dvec[i])) len++;
367
368 //comps = f4Vec.allocate(len);
369 comps = new int[len];
370
371 sparse = allocateElementArray(len);
372 auto& svec = * elementArray(sparse);
373
374 int next = 0;
375 for (int i = first; i >= 0 and i <= last; i++)
376 if (not mRing->is_zero(dvec[i]))
377 {
378 mRing->set(svec[next],dvec[i]);
379 comps[next] = i;
380 ++next;
381 mRing->set_zero(dvec[i]);
382 }
383 }
384
386 int first,
387 int last) const
388 {
389 auto& dvec = * elementArray(dense);
390
391 // first can be -1 if the row is zero. in this case, we should
392 // not be accessing dvec[i] for i negative.
393 for (int i = first; i >= 0 and i <= last; i++)
394 mRing->set_zero(dvec[i]);
395 }
396
397 void makeMonic(ElementArray& sparse) const
398 {
399 auto& svec = * elementArray(sparse);
400
401 typename RingType::Element leadCoeffInv(*mRing);
402
403 mRing->invert(leadCoeffInv,svec[0]);
404
405 for (auto& c : svec) { mRing->mult(c, c, leadCoeffInv); }
406 }
407
408 template<typename Container>
409 void appendToContainer(const ElementArray& sparse,
410 Container& c) const
411 {
412 auto& svec = * elementArray(sparse);
413 for (const auto& a : svec)
414 {
415 ring_elem tmp;
416 mRing->to_ring_elem(tmp,a);
417 c.push_back(tmp);
418 }
419 }
420
421 template<typename Container>
422 ElementArray elementArrayFromContainer(const Container& c) const
423 {
424 ElementArray sparse = allocateElementArray(c.size()); // initializes all elements
425 auto& svec = * elementArray(sparse);
426 for (auto i = 0; i < c.size(); ++i)
427 {
428 mRing->from_ring_elem(svec[i], c[i]);
429 }
430 return sparse;
431 }
432
433 template<typename Container>
435 {
436 ElementArray sparse = allocateElementArray(c.size()); // initializes all elements
437 auto& svec = * elementArray(sparse);
438 for (auto i = 0; i < c.size(); ++i)
439 {
440 mRing->set_from_long(svec[i], c[i]);
441 }
442 return sparse;
443 }
444
445 template<typename Container>
447 {
448 ElementArray sparse = allocateElementArray(c.size()); // initializes all elements
449 auto& svec = * elementArray(sparse);
450 for (auto i = 0; i < c.size(); ++i)
451 {
452 __mpz_struct* x = const_cast<__mpz_struct*>(c[i].get_mpz_t());
453 mRing->set_from_mpz(svec[i], x);
454 }
455 return sparse;
456 }
457
459 int index) const
460 {
461 auto& svec = * elementArray(sparse);
462 ring_elem tmp;
463 mRing->to_ring_elem(tmp,svec[index]);
464 return tmp;
465 }
466
467 std::ostream& displayElement(std::ostream& o, const ElementArray& v, int index) const
468 {
469 auto& vec = * elementArray(v);
470
471 buffer b;
472 mRing->elem_text_out(b, vec[index], true, true, true);
473 o << b.str();
474 return o;
475 }
476
477 std::ostream& displayElementArray(std::ostream& o, const ElementArray& v) const
478 {
479 auto& vec = * elementArray(v);
480
481 bool first = true;
482 o << "[(" << vec.size() << ")";
483 for (const auto& a : vec)
484 {
485 buffer b;
486 mRing->elem_text_out(b, a, true, true, true);
487 if (first)
488 first = false;
489 else
490 o << ",";
491 o << b.str();
492 }
493 o << "]" << std::endl;
494 return o;
495 }
496
497 std::ostream& displayAsDenseArray(std::ostream& o,
498 size_t len,
499 const ElementArray& v,
500 const Range<const int>& comps
501 ) const
502 {
503 auto& vec = * elementArray(v);
504 auto i = comps.cbegin();
505 auto c = vec.cbegin();
506 o << "[(" << vec.size() << ") ";
507 for (auto j = 0; j < len; ++j)
508 {
509 if (i == comps.cend() or *i != j)
510 o << ". ";
511 else
512 {
513 buffer b;
514 mRing->elem_text_out(b, *c, true, true, true);
515 o << b.str() << " ";
516 ++i;
517 ++c;
518 }
519 }
520 o << "]" << std::endl;
521 return o;
522 }
523
524 long to_modp_long(const ElementArray& coeffs, size_t loc) const
525 {
526 (void) coeffs;
527 (void) loc;
528 return 0; // DANGER WILL ROBINSON!
529 }
530
534
535 void pushBackOne(ElementArray& coeffs) const
536 {
537 auto& svec = * elementArray(coeffs);
538 FieldElement one;
539 mRing->init(one);
540 mRing->set_from_long(one, 1);
541 svec.emplace_back(one); // This grabs 'one' in cases where it is allocated... I think...!
542 }
543
544 void pushBackMinusOne(ElementArray& coeffs) const
545 {
546 auto& svec = * elementArray(coeffs);
548 mRing->init(minus_one);
549 mRing->set_from_long(minus_one,-1);
550 svec.emplace_back(minus_one);
551 }
552
554 const ElementArray& take_from_here,
555 size_t loc) const
556 {
557 auto& svec = * elementArray(coeffs);
558 auto& svec2 = * elementArray(take_from_here);
559 assert(loc < svec2.size());
560 FieldElement a;
561 mRing->init_set(a, svec2[loc]);
562 svec.emplace_back(a);
563 }
564
566 const ElementArray& take_from_here,
567 size_t loc) const
568 {
569 auto& svec = * elementArray(coeffs);
570 auto& svec2 = * elementArray(take_from_here);
571 assert(loc < svec2.size());
572 FieldElement a;
573 mRing->init_set(a, svec2[loc]);
574 mRing->negate(a, a);
575 svec.emplace_back(a);
576 }
577
578 // We want to remove this function!
579 // TODO: Decide what to do with this function
580 void from_ring_elem(ElementArray& coeffs, ring_elem numer, ring_elem denom) const
581 // Appends numer/denom to coeffs array
582 {
583 (void) denom;
584 auto& svec = * elementArray(coeffs);
585 FieldElement inumer;
586 mRing->init(inumer);
587 mRing->from_ring_elem(inumer, numer);
588 svec.emplace_back(inumer);
589 }
590};
591
592template<>
594{
595 auto& svec = * elementArray(coeffs);
596 return mRing->coerceToLongInteger(svec[loc]);
597}
598
599template<>
600inline long ConcreteVectorArithmetic<M2::ARingZZp>::to_modp_long(const ElementArray& coeffs, size_t loc) const
601{
602 auto& svec = * elementArray(coeffs);
603 return mRing->coerceToLongInteger(svec[loc]);
604}
605
606template<>
608{
609 auto& svec = * elementArray(coeffs);
610 return mRing->coerceToLongInteger(svec[loc]);
611}
612
613template<>
615 ring_elem numer,
616 ring_elem denom) const
617{
618 // TODO: this function ignores denom, this is non-intuitive and bug-prone.
619 // TODO: this will fail: input is alas ZZ integers... not QQ elements...
620 (void) denom;
621 auto& svec = * elementArray(coeffs);
622 //ring_elem val = numer;
623 FieldElement inumer;
624 //FieldElement idenom;
625 mRing->init(inumer);
626 mRing->from_ring_elem(inumer, numer);
627 svec.emplace_back(inumer);
628
629 // auto& svec = * elementArray(coeffs);
630 // ring_elem val = numer;
631 // FieldElement inumer;
632 // FieldElement idenom;
633 // mRing->init(inumer);
634 // mRing->from_ring_elem(numer, inumer);
635 // mRing->init(idenom);
636 // mRing->from_ring_elem(idenom, denom);
637 // if (not mRing->is_one(idenom))
638 // mRing->divide(inumer, inumer, idenom);
639
640}
641
642// `overloaded` construct (not standard until C++20)
643//template<class... Ts>
644//struct overloaded : Ts... { using Ts::operator()...; };
645
646//template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
647
664// this is the dispatching class using std::variant
666{
667 // does the order of the variant types matter?
668 using CVA_Type = std::variant<ConcreteVectorArithmetic<M2::ARingZZpFlint>*,
678
679private:
681
682public:
684 {
685 // if the rings coming in are defined in a similar way, we could avoid the switch
686 // statement here as well and make it compile time. It would make the class templated
687 // on the variant class describing all the rings.
688 switch (R->ringID())
689 {
692 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingZZpFlint>* >(R)->ring()};
693 break;
696 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingGFFlintBig>* >(R)->ring()};
697 break;
700 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingGFFlint>* >(R)->ring()};
701 break;
702 case M2::ring_QQ:
704 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingQQGMP>* >(R)->ring()};
705 break;
708 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingZZpFFPACK>* >(R)->ring()};
709 break;
710 case M2::ring_ZZp:
712 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingZZp>* >(R)->ring()};
713 break;
714 case M2::ring_GFM2:
716 {R, &dynamic_cast< const M2::ConcreteRing<M2::ARingGFM2>* >(R)->ring()};
717 break;
718 case M2::ring_old:
719 if (R->cast_to_Z_mod() != nullptr)
721 else
722 {
723 std::cout << "Using GC ring in VectorArithmetic." << std::endl;
725 }
726 break;
727 default:
728 // dummy ring type for default
729 // throw an error here...
730 std::cerr << "*** error! *** ring ID not found....!" << std::endl;
732 }
733 }
734
736 std::visit([&](auto& arg) -> void { delete arg; }, mConcreteVector);
737 }
738
739 const Ring* ring() const {
740 return std::visit([&](auto& arg) -> const Ring* { return arg->ring(); }, mConcreteVector);
741 }
742
743 // provide simple visitor interface to underlying std::variant types
744 size_t size(const ElementArray& coeffs) const {
745 return std::visit([&](auto& arg) -> size_t { return arg->size(coeffs); }, mConcreteVector);
746 }
747
749 // Allocation/Deallocation //
753 return std::visit([&](auto& arg) -> ElementArray { return arg->allocateElementArray(nelems);}, mConcreteVector);
754 }
755
757 return std::visit([&](auto& arg) -> ElementArray { return arg->allocateElementArray();}, mConcreteVector);
758 }
759
761 return std::visit([&](auto& arg) -> ElementArray { return arg->copyElementArray(sparse);}, mConcreteVector);
762 }
763
766 std::visit([&](auto& arg) { arg->deallocateElementArray(coeffs); }, mConcreteVector);
767 }
768
773 const ElementArray& coeffs,
774 const Range<const int>& comps) const {
775 std::visit([&](auto& arg) { arg->fillDenseArray(dense,coeffs,comps); }, mConcreteVector);
776 }
777
779 const ElementArray& coeffs,
780 const Range<const int>& comps) const {
781 std::visit([&](auto& arg) { arg->denseCancelFromSparse(dense,coeffs,comps); }, mConcreteVector);
782 }
783
785 const ElementArray& coeffs,
786 const Range<const int>& comps,
787 ElementArray& result_multipler) const {
788 std::visit([&](auto& arg) { arg->denseCancelFromSparse(dense,coeffs,comps,result_multipler); }, mConcreteVector);
789 }
790
792 int first,
793 int last) const {
794 return std::visit([&](auto& arg) -> int { return arg->denseNextNonzero(dense,first,last); }, mConcreteVector);
795 }
796
798 ElementArray& coeffs, // sets coeffs
799 Range<int>& comps, // sets comps
800 int first,
801 int last,
802 MemoryBlock& monomialSpace) const {
803 std::visit([&](auto& arg) { arg->denseToSparse(dense,coeffs,comps,first,last,monomialSpace); }, mConcreteVector);
804 }
805
807 ElementArray& coeffs, // sets coeffs
808 int*& comps, // sets comps
809 int first,
810 int last) const {
811 std::visit([&](auto& arg) { arg->denseToSparse(dense,coeffs,comps,first,last); }, mConcreteVector);
812 }
813
814 template<typename LockType>
816 ElementArray& coeffs, // sets coeffs
817 Range<int>& comps, // sets comps
818 int first,
819 int last,
820 MemoryBlock& monomialSpace,
821 LockType& lock) const {
822 // the existence of 'template' here is a bit jarring to me, but it tells the compiler
823 // that safeDenseToSparse is a template function
824 std::visit([&](auto& arg) { arg->template safeDenseToSparse<LockType>(dense,coeffs,comps,first,last,monomialSpace,lock); }, mConcreteVector);
825 }
826
827 void setZeroInRange(ElementArray& dense, int first, int last) const {
828 std::visit([&](auto& arg) { arg->setZeroInRange(dense, first, last); }, mConcreteVector);
829 }
830
831 void makeMonic(ElementArray& coeffs) const {
832 std::visit([&](auto& arg) { arg->makeMonic(coeffs); }, mConcreteVector);
833 }
834
838
839 template<class Container>
840 void appendToContainer(const ElementArray& coeffs,
841 Container& c) const {
842 std::visit([&](auto& arg) { arg->template appendToContainer<Container>(coeffs, c); }, mConcreteVector);
843 }
844
845 template<class Container>
846 ElementArray elementArrayFromContainer(const Container& c) const {
847 return std::visit([&](auto& arg) -> ElementArray { return arg->template elementArrayFromContainer<Container>(c); }, mConcreteVector);
848 }
849
850 template<class Container>
852 return std::visit([&](auto& arg) -> ElementArray { return arg->template elementArrayFromContainerOfLongs<Container>(c); }, mConcreteVector);
853 }
854
855 template<class Container>
857 return std::visit([&](auto& arg) -> ElementArray { return arg->template elementArrayFromContainerOf_mpz_class<Container>(c); }, mConcreteVector);
858 }
859
861 int index) const {
862 return std::visit([&](auto& arg) -> ring_elem { return arg->ringElemFromElementArray(coeffs,index); }, mConcreteVector);
863 }
864
868
869 std::ostream& displayElement(std::ostream& o, const ElementArray& v, int index) const
870 {
871 return std::visit([&](auto& arg) -> std::ostream& { return arg->displayElement(o, v, index); }, mConcreteVector);
872 }
873
874 std::ostream& displayElementArray(std::ostream& o, const ElementArray& v) const
875 {
876 return std::visit([&](auto& arg) -> std::ostream& { return arg->displayElementArray(o, v); }, mConcreteVector);
877 }
878
879 std::ostream& displayAsDenseArray(std::ostream& o,
880 size_t len,
881 const ElementArray& v,
882 const Range<const int>& comps
883 ) const
884 {
885 return std::visit([&](auto& arg) -> std::ostream& { return arg->displayAsDenseArray(o, len, v, comps); }, mConcreteVector);
886 }
887
888 long getNumAdditions() const
889 {
890 return std::visit([&](auto& arg) -> long { return arg->mStats.numAdditions(); }, mConcreteVector);
891 }
892
893 long to_modp_long(const ElementArray& coeffs, size_t loc) const
894 {
895 return std::visit([&](auto& arg) -> long { return arg->to_modp_long(coeffs, loc); }, mConcreteVector);
896 }
897
901
902 void pushBackOne(ElementArray& coeffs) const
903 {
904 return std::visit([&](auto& arg) { arg->pushBackOne(coeffs); }, mConcreteVector);
905 }
906
907 void pushBackMinusOne(ElementArray& coeffs) const
908 {
909 return std::visit([&](auto& arg) { arg->pushBackMinusOne(coeffs); }, mConcreteVector);
910 }
911
913 const ElementArray& take_from_here,
914 size_t loc) const
915 {
916 return std::visit([&](auto& arg) { arg->pushBackElement(coeffs,take_from_here,loc); }, mConcreteVector);
917 }
918
920 const ElementArray& take_from_here,
921 size_t loc) const
922 {
923 return std::visit([&](auto& arg) { arg->pushBackNegatedElement(coeffs,take_from_here,loc); }, mConcreteVector);
924 }
925
927 ring_elem numer,
928 ring_elem denom_not_used_except_QQ
929 ) const
930 {
931 return std::visit([&](auto& arg) { arg->from_ring_elem(coeffs,numer,denom_not_used_except_QQ); }, mConcreteVector);
932 }
933
935 return std::visit([&](auto& arg) -> const VectorArithmeticStats& { return arg->stats(); }, mConcreteVector);
936 }
937
938 };
939
940#endif
941
942// Local Variables:
943// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
944// indent-tabs-mode: nil
945// End:
Bump-pointer arena allocator for transient inner-loop allocations.
Home-rolled std::span substitute and zipped-range view for the NC engines.
ConcreteRing<RingType> — the templated bridge between aring and the legacy Ring API.
void denseCancelFromSparse(ElementArray &dense, const ElementArray &sparse, const Range< const int > &comps, ElementArray &result_multiplier) const
ElementArray elementArrayFromContainer(const Container &c) const
ElementArray copyElementArray(const ElementArray &sparse) const
void denseToSparse(ElementArray &dense, ElementArray &sparse, Range< int > &comps, int first, int last, MemoryBlock &monomialSpace) const
void deallocateElementArray(ElementArray &coeffs) const
size_t size(const ElementArray &coeffs) const
Linear Algebra /////.
VectorArithmeticStats mStats
std::ostream & displayElement(std::ostream &o, const ElementArray &v, int index) const
void pushBackOne(ElementArray &coeffs) const
Append support /////.
void setZeroInRange(ElementArray &dense, int first, int last) const
void safeDenseToSparse(ElementArray &dense, ElementArray &sparse, Range< int > &comps, int first, int last, MemoryBlock &monomialSpace, LockType &lock) const
ElementArray elementArrayFromContainerOfLongs(const Container &c) const
std::ostream & displayElementArray(std::ostream &o, const ElementArray &v) const
void fillDenseArray(ElementArray &dense, const ElementArray &sparse, const Range< const int > &comps) const
ElementArray allocateElementArray(ComponentIndex nelems) const
const Ring * ring() const
const VectorArithmeticStats & stats() const
void makeMonic(ElementArray &sparse) const
long to_modp_long(const ElementArray &coeffs, size_t loc) const
ElementArrayContainer * elementArray(const ElementArray &f) const
std::ostream & displayAsDenseArray(std::ostream &o, size_t len, const ElementArray &v, const Range< const int > &comps) const
void pushBackMinusOne(ElementArray &coeffs) const
void from_ring_elem(ElementArray &coeffs, ring_elem numer, ring_elem denom) const
ring_elem ringElemFromElementArray(const ElementArray &sparse, int index) const
ConcreteVectorArithmetic(const Ring *origR, const RingType *R)
void denseToSparse(ElementArray &dense, ElementArray &sparse, int *&comps, int first, int last) const
int denseNextNonzero(ElementArray &dense, int first, int last) const
ElementArray allocateElementArray() const
void denseCancelFromSparse(ElementArray &dense, const ElementArray &sparse, const Range< const int > &comps) const
void appendToContainer(const ElementArray &sparse, Container &c) const
void pushBackElement(ElementArray &coeffs, const ElementArray &take_from_here, size_t loc) const
typename RingType::ElementContainerType ElementArrayContainer
void pushBackNegatedElement(ElementArray &coeffs, const ElementArray &take_from_here, size_t loc) const
typename RingType::ElementType FieldElement
ElementArray elementArrayFromContainerOf_mpz_class(const Container &c) const
void * getValue() const
void swap(ElementArray &b)
friend class ConcreteVectorArithmetic
bool isNull() const
void setValue(void *newValue)
Type-erased owning handle to a dense coefficient vector held by a ConcreteVectorArithmetic<Ring>.
std::pair< T *, T * > safeAllocateArray(size_t nelems, MutexType &mutex)
Thin RAII wrapper around memtailor::Arena providing bump-pointer array allocation with optional mutex...
const T * cend() const
Definition Range.hpp:65
const T * cbegin() const
Definition Range.hpp:64
int size() const
Definition Range.hpp:54
virtual M2::RingID ringID() const
Definition ring.hpp:164
const CoefficientRingR * getCoefficientRingR() const
Definition ring.cpp:24
virtual const Z_mod * cast_to_Z_mod() const
Definition ring.hpp:237
xxx xxx xxx
Definition ring.hpp:102
void setZeroInRange(ElementArray &dense, int first, int last) const
std::variant< ConcreteVectorArithmetic< M2::ARingZZpFlint > *, ConcreteVectorArithmetic< M2::ARingGFFlintBig > *, ConcreteVectorArithmetic< M2::ARingGFFlint > *, ConcreteVectorArithmetic< M2::ARingQQGMP > *, ConcreteVectorArithmetic< M2::ARingZZpFFPACK > *, ConcreteVectorArithmetic< M2::ARingZZp > *, ConcreteVectorArithmetic< M2::ARingGFM2 > *, ConcreteVectorArithmetic< CoefficientRingR > *, ConcreteVectorArithmetic< CoefficientRingZZp > *, ConcreteVectorArithmetic< M2::DummyRing > * > CVA_Type
VectorArithmetic(const Ring *R)
ElementArray allocateElementArray(ComponentIndex nelems) const
Create a coefficient vector with room for nelems coefficients.
void deallocateElementArray(ElementArray &coeffs) const
Deallocate all the coefficients, and the array itself.
void denseToSparse(ElementArray &dense, ElementArray &coeffs, int *&comps, int first, int last) const
const VectorArithmeticStats & stats() const
std::ostream & displayAsDenseArray(std::ostream &o, size_t len, const ElementArray &v, const Range< const int > &comps) const
ElementArray elementArrayFromContainer(const Container &c) const
long getNumAdditions() const
ring_elem ringElemFromElementArray(const ElementArray &coeffs, int index) const
ElementArray copyElementArray(const ElementArray &sparse) const
int denseNextNonzero(ElementArray &dense, int first, int last) const
std::ostream & displayElementArray(std::ostream &o, const ElementArray &v) const
long to_modp_long(const ElementArray &coeffs, size_t loc) const
ElementArray allocateElementArray() const
void denseToSparse(ElementArray &dense, ElementArray &coeffs, Range< int > &comps, int first, int last, MemoryBlock &monomialSpace) const
void safeDenseToSparse(ElementArray &dense, ElementArray &coeffs, Range< int > &comps, int first, int last, MemoryBlock &monomialSpace, LockType &lock) const
void fillDenseArray(ElementArray &dense, const ElementArray &coeffs, const Range< const int > &comps) const
Linear Algebra /////.
void makeMonic(ElementArray &coeffs) const
std::ostream & displayElement(std::ostream &o, const ElementArray &v, int index) const
(Debugging) Display /////
void pushBackMinusOne(ElementArray &coeffs) const
void pushBackElement(ElementArray &coeffs, const ElementArray &take_from_here, size_t loc) const
ElementArray elementArrayFromContainerOfLongs(const Container &c) const
ElementArray elementArrayFromContainerOf_mpz_class(const Container &c) const
void denseCancelFromSparse(ElementArray &dense, const ElementArray &coeffs, const Range< const int > &comps) const
void from_ring_elem(ElementArray &coeffs, ring_elem numer, ring_elem denom_not_used_except_QQ) const
void pushBackOne(ElementArray &coeffs) const
Append support /////.
size_t size(const ElementArray &coeffs) const
const Ring * ring() const
void denseCancelFromSparse(ElementArray &dense, const ElementArray &coeffs, const Range< const int > &comps, ElementArray &result_multipler) const
void appendToContainer(const ElementArray &coeffs, Container &c) const
Translation //////////.
void pushBackNegatedElement(ElementArray &coeffs, const ElementArray &take_from_here, size_t loc) const
Lightweight counter attached to a ConcreteVectorArithmetic<Ring> for tracking how many coefficient ad...
CoefficientRingZZp * get_CoeffRing() const
Definition ZZp.hpp:93
char * str()
Definition buffer.hpp:72
void dvec(const Ring *R, const vec v)
Definition debug.cpp:88
int minus_one
int p
@ ring_old
refers to all rings which are not ConcreteRing's.
Definition aring.hpp:94
@ ring_GFM2
Definition aring.hpp:84
@ ring_ZZpFfpack
Definition aring.hpp:82
@ ring_ZZpFlint
Definition aring.hpp:83
@ ring_GFFlintZech
Definition aring.hpp:86
@ ring_GFFlintBig
Definition aring.hpp:85
@ ring_ZZp
Definition aring.hpp:81
@ ring_QQ
Definition aring.hpp:79
Engine TBB shim — single point of inclusion for every parallel primitive.
void swap(mpfr::mpreal &x, mpfr::mpreal &y)
Definition mpreal.h:3244
our_new_delete — per-class opt-in routing of new / delete through bdwgc.
volatile int x
int ComponentIndex
ring_elem — the universal value type carried by every Ring* in the engine.