Loading...
Searching...
No Matches
serialize-cereal.h
1#ifndef SYMENGINE_SERIALIZE_CEREAL_H
2#define SYMENGINE_SERIALIZE_CEREAL_H
3#include <symengine/basic.h>
4#include <symengine/number.h>
5#include <symengine/integer.h>
6#include <symengine/symbol.h>
7#include <symengine/visitor.h>
8#include <symengine/utilities/stream_fmt.h>
9
10#include <cereal/cereal.hpp>
11#include <cereal/version.hpp>
12#include <cereal/types/polymorphic.hpp>
13#include <cereal/types/string.hpp>
14#include <cereal/details/helpers.hpp>
15#include <cereal/types/map.hpp>
16#include <cereal/types/unordered_map.hpp>
17#include <cereal/types/set.hpp>
18#include <cereal/types/vector.hpp>
19#include <cereal/types/utility.hpp>
20#include <cereal/archives/portable_binary.hpp>
21
22namespace SymEngine
23{
24
25template <class Archive>
26inline void save_basic(Archive &ar, const Basic &b)
27{
28 const auto t_code = b.get_type_code();
30 << __FILE__ << ":" << __LINE__
32 << ": " << __PRETTY_FUNCTION__
33#endif
34 << " not supported: " << type_code_name(t_code)
35 << " (" << t_code << ")"
36#if !defined(NDEBUG)
37 << ", " << b.__str__()
38#endif
39 );
40}
41template <class Archive>
42inline void save_basic(Archive &ar, const Symbol &b)
43{
44 ar(b.__str__());
45}
46template <class Archive>
47inline void save_basic(Archive &ar, const Mul &b)
48{
49 ar(b.get_coef());
50 ar(b.get_dict());
51}
52template <class Archive>
53inline void save_basic(Archive &ar, const Add &b)
54{
55 ar(b.get_coef());
56 ar(b.get_dict());
57}
58template <class Archive>
59inline void save_basic(Archive &ar, const Pow &b)
60{
61 ar(b.get_base());
62 ar(b.get_exp());
63}
64template <typename Archive>
65void save_helper(Archive &ar, const integer_class &intgr)
66{
68 s << intgr; // stream to string
69 ar(s.str());
70}
71template <typename Archive>
72void save_helper(Archive &ar, const rational_class &rat)
73{
74 integer_class num = get_num(rat);
75 integer_class den = get_den(rat);
76 save_helper(ar, num);
77 save_helper(ar, den);
78}
79// Following is an ugly hack for templated integer classes
80// Not sure why a direct version doesn't work
81template <typename Archive>
82void save_basic(Archive &ar, const URatPoly &b)
83{
84 ar(b.get_var());
85 const URatDict &urd = b.get_poly();
86 size_t l = urd.size();
87 ar(l);
88 for (auto &p : urd.dict_) {
89 unsigned int first = p.first;
90 const rational_class &second = p.second;
91 ar(first);
92 save_helper(ar, second);
93 }
94}
95template <class Archive>
96inline void save_basic(Archive &ar, const Integer &b)
97{
98 ar(b.__str__());
99}
100template <class Archive>
101inline void save_basic(Archive &ar, const RealDouble &b)
102{
103 ar(b.i);
104}
105template <class Archive>
106inline void save_basic(Archive &ar, const Rational &b)
107{
108 ar(b.get_num(), b.get_den());
109}
110template <class Archive>
111inline void save_basic(Archive &ar, const ComplexBase &b)
112{
113 ar(b.real_part(), b.imaginary_part());
114}
115template <class Archive>
116inline void save_basic(Archive &ar, const Interval &b)
117{
118 ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
119}
120template <class Archive>
121inline void save_basic(Archive &ar, const BooleanAtom &b)
122{
123 ar(b.get_val());
124}
125template <class Archive>
126inline void save_basic(Archive &ar, const Infty &b)
127{
128 ar(b.get_direction());
129}
130
131template <class Archive>
132inline void save_basic(Archive &ar, const NaN &b)
133{
134}
135
136template <class Archive>
137inline void save_basic(Archive &ar, const Constant &b)
138{
139 ar(b.get_name());
140}
141template <class Archive>
142inline void save_basic(Archive &ar, const OneArgFunction &b)
143{
144 ar(b.get_arg());
145}
146template <class Archive>
147inline void save_basic(Archive &ar, const TwoArgFunction &b)
148{
149 ar(b.get_arg1(), b.get_arg2());
150}
151
152template <class Archive>
153inline void save_basic(Archive &ar, const Relational &b)
154{
155 ar(b.get_arg1(), b.get_arg2());
156}
157template <class Archive>
158inline void save_basic(Archive &ar, const And &b)
159{
160 ar(b.get_container());
161}
162template <class Archive>
163inline void save_basic(Archive &ar, const Or &b)
164{
165 ar(b.get_container());
166}
167template <class Archive>
168inline void save_basic(Archive &ar, const Xor &b)
169{
170 ar(b.get_container());
171}
172template <class Archive>
173inline void save_basic(Archive &ar, const Not &b)
174{
175 ar(b.get_arg());
176}
177template <class Archive>
178inline void save_basic(Archive &ar, const Contains &b)
179{
180 ar(b.get_expr(), b.get_set());
181}
182template <class Archive>
183inline void save_basic(Archive &ar, const Piecewise &b)
184{
185 ar(b.get_vec());
186}
187template <class Archive>
188inline void save_basic(Archive &ar, const Reals &b)
189{
190}
191template <class Archive>
192inline void save_basic(Archive &ar, const Rationals &b)
193{
194}
195template <class Archive>
196inline void save_basic(Archive &ar, const EmptySet &b)
197{
198}
199template <class Archive>
200inline void save_basic(Archive &ar, const Integers &b)
201{
202}
203template <class Archive>
204inline void save_basic(Archive &ar, const UniversalSet &b)
205{
206}
207template <class Archive>
208inline void save_basic(Archive &ar, const Union &b)
209{
210 ar(b.get_container());
211}
212template <class Archive>
213inline void save_basic(Archive &ar, const Complement &b)
214{
215 ar(b.get_universe(), b.get_container());
216}
217template <class Archive>
218inline void save_basic(Archive &ar, const ImageSet &b)
219{
220 ar(b.get_symbol(), b.get_expr(), b.get_baseset());
221}
222template <class Archive>
223inline void save_basic(Archive &ar, const FiniteSet &b)
224{
225 ar(b.get_container());
226}
227template <class Archive>
228inline void save_basic(Archive &ar, const ConditionSet &b)
229{
230 ar(b.get_symbol(), b.get_condition());
231}
232#ifdef HAVE_SYMENGINE_MPFR
233template <class Archive>
234inline void save_basic(Archive &ar, const RealMPFR &b)
235{
236 ar(b.__str__(), b.get_prec());
237}
238#endif
239template <class Archive>
240inline void save_basic(Archive &ar, const GaloisField &b)
241{
242 throw NotImplementedError("GaloisField saving is not implemented yet.");
243}
244template <class Archive>
245inline void save_basic(Archive &ar, const SeriesCoeffInterface &)
246{
247 throw NotImplementedError("Series saving is not implemented yet.");
248}
249template <class Archive>
250inline void save_basic(Archive &ar, const MultiArgFunction &b)
251{
252 ar(b.get_args());
253}
254template <class Archive>
255inline void save_basic(Archive &ar, const FunctionSymbol &b)
256{
257 ar(b.get_name(), b.get_args());
258}
259template <class Archive>
260inline void save_basic(Archive &ar, const Derivative &b)
261{
262 ar(b.get_arg(), b.get_symbols());
263}
264template <class Archive>
265inline void save_basic(Archive &ar, const Subs &b)
266{
267 ar(b.get_arg(), b.get_dict());
268}
269template <class Archive>
270inline void save_basic(Archive &ar, const NumberWrapper &b)
271{
272 throw NotImplementedError("NumberWrapper saving is not implemented yet.");
273}
274template <class Archive>
275inline void save_basic(Archive &ar, const FunctionWrapper &b)
276{
277 throw NotImplementedError("FunctionWrapper saving is not implemented yet.");
278}
279
280template <class Archive>
281inline void save_basic(Archive &ar, RCP<const Basic> const &ptr)
282{
283#if CEREAL_VERSION >= 10301
284 std::shared_ptr<void> sharedPtr = std::static_pointer_cast<void>(
285 std::make_shared<RCP<const Basic>>(ptr));
286 uint32_t id = ar.registerSharedPointer(sharedPtr);
287#else
288 uint32_t id = ar.registerSharedPointer(ptr.get());
289#endif
290 ar(CEREAL_NVP(id));
291
292 if (id & cereal::detail::msb_32bit) {
293 ar(ptr->get_type_code());
294 switch (ptr->get_type_code()) {
295#define SYMENGINE_ENUM(type, Class) \
296 case type: \
297 save_basic(ar, static_cast<const Class &>(*ptr)); \
298 break;
299#include "symengine/type_codes.inc"
300#undef SYMENGINE_ENUM
301 default:
302 save_basic(ar, *ptr);
303 }
304 }
305}
306
308template <class Archive, class T>
309inline void CEREAL_SAVE_FUNCTION_NAME(Archive &ar, RCP<const T> const &ptr)
310{
311 save_basic(ar, rcp_static_cast<const Basic>(ptr));
312}
313template <class Archive>
314RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
315{
316 double val;
317 ar(val);
318 return real_double(val);
319}
320template <class Archive>
321RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
322{
323 RCP<const Number> direction;
324 ar(direction);
325 return Infty::from_direction(direction);
326}
327template <class Archive>
328RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
329{
331}
332template <class Archive>
333RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
334{
335 std::string name;
336 ar(name);
337 return symbol(name);
338}
339template <class Archive>
340RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
341{
342 RCP<const Number> coeff;
343 map_basic_basic dict;
344 ar(coeff);
345 ar(dict);
346 return make_rcp<const Mul>(coeff, std::move(dict));
347}
348template <class Archive>
349RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
350{
351 RCP<const Number> coeff;
352 umap_basic_num dict;
353 ar(coeff);
354 ar(dict);
355 return make_rcp<const Add>(coeff, std::move(dict));
356}
357template <class Archive>
358RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
359{
360 RCP<const Basic> base, exp;
361 ar(base);
362 ar(exp);
363 return make_rcp<const Pow>(base, exp);
364}
365template <typename Archive>
366void load_helper(Archive &ar, integer_class &intgr)
367{
369 ar(int_str);
370 intgr = integer_class(std::move(int_str));
371}
372template <typename Archive>
373void load_helper(Archive &ar, const rational_class &rat)
374{
375 integer_class num, den;
376 load_helper(ar, num);
377 load_helper(ar, den);
378}
379// Following is an ugly hack for templated integer classes
380// Not sure why the other clean version doesn't work
381template <typename Archive>
382RCP<const Basic> load_basic(Archive &ar, const URatPoly &b)
383{
384 RCP<const Basic> var;
385 size_t l;
386 ar(var);
387 ar(l);
389 auto hint = d.begin();
390 for (size_t i = 0; i < l; i++) {
391 unsigned int first;
392 rational_class second;
393 ar(first);
394 load_helper(ar, second);
395#if !defined(__clang__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
397#else
398 d.emplace_hint(hint, std::move(first), std::move(second));
399#endif
400 }
401 return make_rcp<const URatPoly>(var, URatDict(std::move(d)));
402}
403template <class Archive>
404RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
405{
407 ar(int_str);
408 return integer(integer_class(int_str));
409}
410template <class Archive>
411RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
412{
413 std::string name;
414 ar(name);
415 return constant(name);
416}
417template <class Archive>
418RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
419{
421 ar(num, den);
423}
424template <class Archive>
425RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
426{
427 RCP<const Number> num, den;
428 ar(num, den);
429 return Complex::from_two_nums(*num, *den);
430}
431template <class Archive, class T>
432RCP<const Basic>
433load_basic(Archive &ar, RCP<const T> &,
435 int>::type * = nullptr)
436{
437 RCP<const Number> num, den;
438 ar(num, den);
439 return addnum(num, mulnum(I, den));
440}
441template <class Archive>
442RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
443{
444 RCP<const Number> start, end;
445 bool left_open, right_open;
448}
449template <class Archive>
450RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
451{
452 bool val;
453 ar(val);
454 return boolean(val);
455}
456template <class Archive>
457RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
458{
459 set_boolean container;
460 ar(container);
462}
463template <class Archive>
464RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
465{
466 set_boolean container;
467 ar(container);
469}
470template <class Archive>
471RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
472{
473 vec_boolean container;
474 ar(container);
476}
477template <class Archive>
478RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
479{
480 RCP<const Boolean> arg;
481 ar(arg);
482 return make_rcp<const Not>(arg);
483}
484template <class Archive>
485RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
486{
487 PiecewiseVec vec;
488 ar(vec);
490}
491template <class Archive>
492RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
493{
494 RCP<const Basic> expr;
495 RCP<const Set> contains_set;
498}
499template <class Archive>
500RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
501{
502 return reals();
503}
504template <class Archive>
505RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
506{
507 return rationals();
508}
509template <class Archive>
510RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
511{
512 return emptyset();
513}
514template <class Archive>
515RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
516{
517 return integers();
518}
519template <class Archive>
520RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
521{
522 return universalset();
523}
524template <class Archive>
525RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
526{
527 set_set union_set;
528 ar(union_set);
530}
531template <class Archive>
532RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
533{
534 RCP<const Set> universe, container;
537}
538template <class Archive>
539RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
540{
541 RCP<const Basic> sym, expr;
542 RCP<const Set> base;
543 ar(sym, expr, base);
544 return make_rcp<const ImageSet>(sym, expr, base);
545}
546template <class Archive>
547RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
548{
549 set_basic set;
550 ar(set);
551 return make_rcp<const FiniteSet>(set);
552}
553template <class Archive>
554RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
555{
556 RCP<const Basic> sym;
557 RCP<const Boolean> condition;
558 ar(sym, condition);
560}
561#ifdef HAVE_SYMENGINE_MPFR
562template <class Archive>
563RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
564{
566 unsigned prec;
567 ar(num, prec);
568 return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
569}
570#endif
571template <class Archive>
572RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
573{
574 RCP<const Basic> arg;
575 multiset_basic set;
576 ar(arg, set);
578}
579template <class Archive>
580RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
581{
582 RCP<const Basic> arg;
583 map_basic_basic dict;
584 ar(arg, dict);
585 return make_rcp<const Subs>(arg, std::move(dict));
586}
587
588template <class Archive, class T>
589RCP<const Basic>
590load_basic(Archive &ar, RCP<const T> &,
592 int>::type * = nullptr)
593{
594 RCP<const Basic> arg;
595 ar(arg);
596 return make_rcp<const T>(arg);
597}
598template <class Archive, class T>
599RCP<const Basic>
600load_basic(Archive &ar, RCP<const T> &,
602 int>::type * = nullptr)
603{
604 RCP<const Basic> arg1, arg2;
605 ar(arg1, arg2);
606 return make_rcp<const T>(arg1, arg2);
607}
608template <class Archive>
609RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
610{
611 std::string name;
612 vec_basic vec;
613 ar(name, vec);
615}
616template <class Archive>
617RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
618{
620 << __FILE__ << ":" << __LINE__
622 << ": " << __PRETTY_FUNCTION__
623#endif
624 << "Loading of this type is not implemented.");
625}
626template <class Archive, class T>
627RCP<const Basic>
628load_basic(Archive &ar, RCP<const T> &,
630 int>::type * = nullptr)
631{
632 vec_basic args;
633 ar(args);
635}
636template <class Archive, class T>
637RCP<const Basic>
638load_basic(Archive &ar, RCP<const T> &,
640 int>::type * = nullptr)
641{
642 RCP<const Basic> arg1, arg2;
643 ar(arg1, arg2);
644 return make_rcp<const T>(arg1, arg2);
645}
646template <class Archive, class T>
647RCP<const Basic> load_basic(
648 Archive &ar, RCP<const T> &,
654 int>::type * = nullptr)
655{
657 << __FILE__ << ":" << __LINE__
659 << ": " << __PRETTY_FUNCTION__
660#endif
661 << "Loading of this type is not implemented.");
662}
663
665template <class Archive, class T>
666inline void CEREAL_LOAD_FUNCTION_NAME(Archive &ar, RCP<const T> &ptr)
667{
668 uint32_t id;
669 ar(CEREAL_NVP(id));
670
671 if (id & cereal::detail::msb_32bit) {
673 ar(type_code);
674 switch (type_code) {
675#define SYMENGINE_ENUM(type_enum, Class) \
676 case type_enum: { \
677 if (not std::is_base_of<T, Class>::value) { \
678 throw std::runtime_error("Cannot convert to type."); \
679 } else { \
680 RCP<const Class> dummy_ptr; \
681 ptr = rcp_static_cast<const T>( \
682 rcp_static_cast<const Basic>(load_basic(ar, dummy_ptr))); \
683 break; \
684 } \
685 }
686#include "symengine/type_codes.inc"
687#undef SYMENGINE_ENUM
688 default:
689 throw std::runtime_error("Unknown type");
690 }
691 std::shared_ptr<void> sharedPtr = std::static_pointer_cast<void>(
692 std::make_shared<RCP<const Basic>>(ptr));
693
694 ar.registerSharedPointer(id, sharedPtr);
695 } else {
697 = std::static_pointer_cast<RCP<const T>>(ar.getSharedPointer(id));
698 ptr = *sharedPtr.get();
699 }
700}
701} // namespace SymEngine
702#endif // SYMENGINE_SERIALIZE_CEREAL_H
The base class for SymEngine.
T begin(T... args)
static RCP< const Number > from_two_nums(const Number &re, const Number &im)
Definition complex.cpp:109
static RCP< const Number > from_two_ints(const Integer &n, const Integer &d)
Definition rational.cpp:44
T end(T... args)
T get(T... args)
T make_pair(T... args)
T make_shared(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition add.cpp:19
RCP< const Reals > reals()
Definition sets.h:560
RCP< const EmptySet > emptyset()
Definition sets.h:590
RCP< const UniversalSet > universalset()
Definition sets.h:596
RCP< const Integers > integers()
Definition sets.h:572
void hash_combine(hash_t &seed, const T &v)
Definition basic-inl.h:95
RCP< const Number > addnum(const RCP< const Number > &self, const RCP< const Number > &other)
Add self and other
Definition number.h:81
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
Definition pow.cpp:271
RCP< const Rationals > rationals()
Definition sets.h:566
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
Definition symbol.h:82
void CEREAL_SAVE_FUNCTION_NAME(Archive &ar, RCP< const T > const &ptr)
Saving for SymEngine::RCP.
void CEREAL_LOAD_FUNCTION_NAME(Archive &ar, RCP< const T > &ptr)
Loading for SymEngine::RCP.
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)
Definition integer.h:197
RCP< const Constant > constant(const std::string &name)
inline version to return Constant
Definition constants.h:53
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
Definition number.h:93
T str(T... args)