1 #ifndef SYMENGINE_SERIALIZE_CEREAL_H
2 #define SYMENGINE_SERIALIZE_CEREAL_H
11 #include <symengine/utilities/stream_fmt.h>
13 #include <cereal/cereal.hpp>
14 #include <cereal/version.hpp>
15 #include <cereal/types/polymorphic.hpp>
16 #include <cereal/types/string.hpp>
17 #include <cereal/details/helpers.hpp>
18 #include <cereal/types/map.hpp>
19 #include <cereal/types/unordered_map.hpp>
20 #include <cereal/types/set.hpp>
21 #include <cereal/types/vector.hpp>
22 #include <cereal/types/utility.hpp>
23 #include <cereal/archives/portable_binary.hpp>
28 template <
class Archive>
31 using Archive::Archive;
34 void save_rcp_basic(
const RCP<const Basic> &ptr)
36 uintptr_t addr = (uintptr_t)(
void *)ptr.get();
39 auto id = _addresses.find(addr);
40 uint8_t first_seen = (
id == _addresses.end());
46 TypeID type_code = ptr->get_type_code();
47 save_typeid(*
this, type_code);
49 #define SYMENGINE_ENUM(type, Class) \
51 save_basic(*this, static_cast<const Class &>(*ptr)); \
53 #include "symengine/type_codes.inc"
56 save_basic(*
this, *ptr);
58 _addresses.insert(addr);
62 std::set<uintptr_t> _addresses;
67 template <
class Archive>
70 using Archive::Archive;
74 RCP<const T> load_rcp_basic()
83 if (first_seen >= 2) {
84 throw SerializationError(
"Invalid input");
88 auto it = _rcp_map.find(addr);
89 if (it == _rcp_map.end()) {
90 throw SerializationError(
"Invalid shared pointer");
92 RCP<const Basic> b = it->second;
93 switch (b->get_type_code()) {
94 #define SYMENGINE_ENUM(type_enum, Class) \
96 if (not std::is_base_of<T, Class>::value) { \
97 throw SerializationError("Cannot convert to given type"); \
99 return rcp_static_cast<const T>(b); \
102 #include "symengine/type_codes.inc"
103 #undef SYMENGINE_ENUM
105 throw SerializationError(
"Unknown typeID");
110 load_typeid(*
this, type_code);
112 #define SYMENGINE_ENUM(type_enum, Class) \
114 RCP<const Class> dummy_ptr; \
115 RCP<const Basic> basic_ptr = load_basic(*this, dummy_ptr); \
116 _rcp_map[addr] = basic_ptr; \
117 if (not std::is_base_of<T, Class>::value) { \
118 throw SerializationError("Cannot convert to given type"); \
120 return rcp_static_cast<const T>(basic_ptr); \
123 #include "symengine/type_codes.inc"
124 #undef SYMENGINE_ENUM
126 throw SerializationError(
"Unknown typeID");
128 }
catch (cereal::Exception &e) {
129 throw SerializationError(e.what());
134 std::unordered_map<uintptr_t, RCP<const Basic>> _rcp_map;
139 template <
class Archive>
140 inline void save_basic(Archive &ar,
const Basic &b)
142 const auto t_code = b.get_type_code();
143 throw SerializationError(StreamFmt()
144 << __FILE__ <<
":" << __LINE__
146 <<
": " << __PRETTY_FUNCTION__
148 <<
" not supported: " << type_code_name(t_code)
149 <<
" (" << t_code <<
")"
151 <<
", " << b.__str__()
155 template <
class Archive>
156 inline void save_basic(Archive &ar,
const Symbol &b)
160 template <
class Archive>
161 inline void save_basic(Archive &ar,
const Dummy &b)
163 ar(b.get_name(), b.get_index());
165 template <
class Archive>
166 inline void save_basic(Archive &ar,
const Mul &b)
171 template <
class Archive>
172 inline void save_basic(Archive &ar,
const Add &b)
177 template <
class Archive>
178 inline void save_basic(Archive &ar,
const Pow &b)
183 template <
typename Archive>
184 void save_helper(Archive &ar,
const integer_class &intgr)
186 std::ostringstream s;
190 template <
typename Archive>
191 void save_helper(Archive &ar,
const rational_class &rat)
193 integer_class num = get_num(rat);
194 integer_class den = get_den(rat);
195 save_helper(ar, num);
196 save_helper(ar, den);
200 template <
typename Archive>
201 void save_basic(Archive &ar,
const URatPoly &b)
204 const URatDict &urd = b.get_poly();
205 size_t l = urd.size();
207 for (
auto &p : urd.dict_) {
208 unsigned int first = p.first;
209 const rational_class &second = p.second;
211 save_helper(ar, second);
214 template <
class Archive>
215 inline void save_basic(Archive &ar,
const Integer &b)
219 template <
class Archive>
220 inline void save_basic(Archive &ar,
const RealDouble &b)
224 template <
class Archive>
225 inline void save_basic(Archive &ar,
const Rational &b)
227 ar(b.get_num(), b.get_den());
229 template <
class Archive>
230 inline void save_basic(Archive &ar,
const ComplexBase &b)
232 ar(b.real_part(), b.imaginary_part());
234 template <
class Archive>
235 inline void save_basic(Archive &ar,
const Interval &b)
237 ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
239 template <
class Archive>
240 inline void save_basic(Archive &ar,
const BooleanAtom &b)
244 template <
class Archive>
245 inline void save_basic(Archive &ar,
const Infty &b)
247 ar(b.get_direction());
250 template <
class Archive>
251 inline void save_basic(Archive &ar,
const NaN &b)
255 template <
class Archive>
256 inline void save_basic(Archive &ar,
const Constant &b)
260 template <
class Archive>
261 inline void save_basic(Archive &ar,
const OneArgFunction &b)
265 template <
class Archive>
266 inline void save_basic(Archive &ar,
const TwoArgFunction &b)
268 ar(b.get_arg1(), b.get_arg2());
271 template <
class Archive>
272 inline void save_basic(Archive &ar,
const Relational &b)
274 ar(b.get_arg1(), b.get_arg2());
276 template <
class Archive>
277 inline void save_basic(Archive &ar,
const And &b)
279 ar(b.get_container());
281 template <
class Archive>
282 inline void save_basic(Archive &ar,
const Or &b)
284 ar(b.get_container());
286 template <
class Archive>
287 inline void save_basic(Archive &ar,
const Xor &b)
289 ar(b.get_container());
291 template <
class Archive>
292 inline void save_basic(Archive &ar,
const Not &b)
296 template <
class Archive>
297 inline void save_basic(Archive &ar,
const Contains &b)
299 ar(b.get_expr(), b.get_set());
301 template <
class Archive>
302 inline void save_basic(Archive &ar,
const Piecewise &b)
306 template <
class Archive>
307 inline void save_basic(Archive &ar,
const Reals &b)
310 template <
class Archive>
311 inline void save_basic(Archive &ar,
const Rationals &b)
314 template <
class Archive>
315 inline void save_basic(Archive &ar,
const EmptySet &b)
318 template <
class Archive>
319 inline void save_basic(Archive &ar,
const Integers &b)
322 template <
class Archive>
323 inline void save_basic(Archive &ar,
const UniversalSet &b)
326 template <
class Archive>
327 inline void save_basic(Archive &ar,
const Union &b)
329 ar(b.get_container());
331 template <
class Archive>
332 inline void save_basic(Archive &ar,
const Complement &b)
334 ar(b.get_universe(), b.get_container());
336 template <
class Archive>
337 inline void save_basic(Archive &ar,
const ImageSet &b)
339 ar(b.get_symbol(), b.get_expr(), b.get_baseset());
341 template <
class Archive>
342 inline void save_basic(Archive &ar,
const FiniteSet &b)
344 ar(b.get_container());
346 template <
class Archive>
347 inline void save_basic(Archive &ar,
const ConditionSet &b)
349 ar(b.get_symbol(), b.get_condition());
351 #ifdef HAVE_SYMENGINE_MPFR
352 template <
class Archive>
353 inline void save_basic(Archive &ar,
const RealMPFR &b)
355 ar(b.__str__(), b.get_prec());
358 template <
class Archive>
359 inline void save_basic(Archive &ar,
const GaloisField &b)
361 throw NotImplementedError(
"GaloisField saving is not implemented yet.");
363 template <
class Archive>
364 inline void save_basic(Archive &ar,
const SeriesCoeffInterface &)
366 throw NotImplementedError(
"Series saving is not implemented yet.");
368 template <
class Archive>
369 inline void save_basic(Archive &ar,
const MultiArgFunction &b)
373 template <
class Archive>
374 inline void save_basic(Archive &ar,
const FunctionSymbol &b)
376 ar(b.get_name(), b.get_args());
378 template <
class Archive>
379 inline void save_basic(Archive &ar,
const Derivative &b)
381 ar(b.get_arg(), b.get_symbols());
383 template <
class Archive>
384 inline void save_basic(Archive &ar,
const Subs &b)
386 ar(b.get_arg(), b.get_dict());
388 template <
class Archive>
389 inline void save_basic(Archive &ar,
const NumberWrapper &b)
391 throw NotImplementedError(
"NumberWrapper saving is not implemented yet.");
393 template <
class Archive>
394 inline void save_basic(Archive &ar,
const FunctionWrapper &b)
396 throw NotImplementedError(
"FunctionWrapper saving is not implemented yet.");
400 template <
class Archive,
class T>
406 throw SerializationError(
"Need a RCPBasicAwareOutputArchive");
408 ar_ptr->save_rcp_basic(rcp_static_cast<const Basic>(ptr));
410 template <
class Archive>
411 RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
415 return real_double(val);
417 template <
class Archive>
418 RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
420 RCP<const Number> direction;
422 return Infty::from_direction(direction);
424 template <
class Archive>
425 RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
427 return rcp_static_cast<const Basic>(Nan);
429 template <
class Archive>
430 RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
436 template <
class Archive>
437 RCP<const Basic> load_basic(Archive &ar, RCP<const Dummy> &)
442 return dummy(name, index);
444 template <
class Archive>
445 RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
447 RCP<const Number> coeff;
448 map_basic_basic dict;
451 return make_rcp<const Mul>(coeff, std::move(dict));
453 template <
class Archive>
454 RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
456 RCP<const Number> coeff;
460 return make_rcp<const Add>(coeff, std::move(dict));
462 template <
class Archive>
463 RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
465 RCP<const Basic> base,
exp;
468 return make_rcp<const Pow>(base,
exp);
470 template <
typename Archive>
471 void load_helper(Archive &ar, integer_class &intgr)
475 if (int_str.size() == 0) {
476 throw SerializationError(
"invalid integer");
478 if (not(int_str[0] ==
'-' or std::isdigit(int_str[0]))) {
479 throw SerializationError(
"invalid integer");
481 for (
auto it = ++int_str.begin(); it < int_str.end(); it++) {
482 if (not std::isdigit(*it)) {
483 throw SerializationError(
"invalid integer");
486 intgr = integer_class(std::move(int_str));
488 template <
typename Archive>
489 void load_helper(Archive &ar,
const rational_class &rat)
491 integer_class num, den;
492 load_helper(ar, num);
493 load_helper(ar, den);
497 template <
typename Archive>
498 RCP<const Basic> load_basic(Archive &ar,
const URatPoly &b)
500 RCP<const Basic> var;
504 std::map<unsigned, rational_class> d;
505 auto hint = d.begin();
506 for (
size_t i = 0; i < l; i++) {
508 rational_class second;
510 load_helper(ar, second);
511 #if !defined(__clang__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
512 d.insert(hint, std::make_pair(std::move(first), std::move(second)));
514 d.emplace_hint(hint, std::move(first), std::move(second));
517 return make_rcp<const URatPoly>(var, URatDict(std::move(d)));
519 template <
class Archive>
520 RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
526 template <
class Archive>
527 RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
533 template <
class Archive>
534 RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
536 RCP<const Integer> num, den;
540 template <
class Archive>
541 RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
543 RCP<const Number> num, den;
547 template <
class Archive,
class T>
549 load_basic(Archive &ar, RCP<const T> &,
550 typename std::enable_if<std::is_base_of<ComplexBase, T>::value,
551 int>::type * =
nullptr)
553 RCP<const Number> num, den;
557 template <
class Archive>
558 RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
560 RCP<const Number> start, end;
561 bool left_open, right_open;
562 ar(left_open, start, right_open, end);
563 return make_rcp<const Interval>(start, end, left_open, right_open);
565 template <
class Archive>
566 RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
572 template <
class Archive>
573 RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
575 set_boolean container;
577 return make_rcp<const And>(std::move(container));
579 template <
class Archive>
580 RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
582 set_boolean container;
584 return make_rcp<const Or>(std::move(container));
586 template <
class Archive>
587 RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
589 vec_boolean container;
591 return make_rcp<const Xor>(std::move(container));
593 template <
class Archive>
594 RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
596 RCP<const Boolean> arg;
598 return make_rcp<const Not>(arg);
600 template <
class Archive>
601 RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
605 return make_rcp<const Piecewise>(std::move(vec));
607 template <
class Archive>
608 RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
610 RCP<const Basic> expr;
611 RCP<const Set> contains_set;
612 ar(expr, contains_set);
613 return make_rcp<const Contains>(expr, contains_set);
615 template <
class Archive>
616 RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
620 template <
class Archive>
621 RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
625 template <
class Archive>
626 RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
630 template <
class Archive>
631 RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
635 template <
class Archive>
636 RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
640 template <
class Archive>
641 RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
645 return make_rcp<const Union>(std::move(union_set));
647 template <
class Archive>
648 RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
650 RCP<const Set> universe, container;
651 ar(universe, container);
652 return make_rcp<const Complement>(universe, container);
654 template <
class Archive>
655 RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
657 RCP<const Basic> sym, expr;
660 return make_rcp<const ImageSet>(sym, expr, base);
662 template <
class Archive>
663 RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
667 return make_rcp<const FiniteSet>(set);
669 template <
class Archive>
670 RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
672 RCP<const Basic> sym;
673 RCP<const Boolean> condition;
675 return make_rcp<const ConditionSet>(sym, condition);
677 #ifdef HAVE_SYMENGINE_MPFR
678 template <
class Archive>
679 RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
684 return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
687 template <
class Archive>
688 RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
690 RCP<const Basic> arg;
693 return make_rcp<const Derivative>(arg, std::move(set));
695 template <
class Archive>
696 RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
698 RCP<const Basic> arg;
699 map_basic_basic dict;
701 return make_rcp<const Subs>(arg, std::move(dict));
704 template <
class Archive,
class T>
706 load_basic(Archive &ar, RCP<const T> &,
707 typename std::enable_if<std::is_base_of<OneArgFunction, T>::value,
708 int>::type * =
nullptr)
710 RCP<const Basic> arg;
712 return make_rcp<const T>(arg);
714 template <
class Archive,
class T>
716 load_basic(Archive &ar, RCP<const T> &,
717 typename std::enable_if<std::is_base_of<TwoArgFunction, T>::value,
718 int>::type * =
nullptr)
720 RCP<const Basic> arg1, arg2;
722 return make_rcp<const T>(arg1, arg2);
724 template <
class Archive>
725 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
730 return make_rcp<const FunctionSymbol>(name, std::move(vec));
732 template <
class Archive>
733 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
735 throw SerializationError(StreamFmt()
736 << __FILE__ <<
":" << __LINE__
738 <<
": " << __PRETTY_FUNCTION__
740 <<
"Loading of this type is not implemented.");
742 template <
class Archive,
class T>
744 load_basic(Archive &ar, RCP<const T> &,
745 typename std::enable_if<std::is_base_of<MultiArgFunction, T>::value,
746 int>::type * =
nullptr)
750 return make_rcp<const T>(std::move(args));
752 template <
class Archive,
class T>
754 load_basic(Archive &ar, RCP<const T> &,
755 typename std::enable_if<std::is_base_of<Relational, T>::value,
756 int>::type * =
nullptr)
758 RCP<const Basic> arg1, arg2;
760 return make_rcp<const T>(arg1, arg2);
762 template <
class Archive,
class T>
763 RCP<const Basic> load_basic(
764 Archive &ar, RCP<const T> &,
765 typename std::enable_if<not(std::is_base_of<Relational, T>::value
766 or std::is_base_of<ComplexBase, T>::value
767 or std::is_base_of<OneArgFunction, T>::value
768 or std::is_base_of<MultiArgFunction, T>::value
769 or std::is_base_of<TwoArgFunction, T>::value),
770 int>::type * =
nullptr)
772 throw SerializationError(StreamFmt()
773 << __FILE__ <<
":" << __LINE__
775 <<
": " << __PRETTY_FUNCTION__
777 <<
"Loading of this type is not implemented.");
780 template <
class Archive>
781 inline void save_typeid(Archive &ar, TypeID &t)
785 "TypeID cannot be saved to a 8 bit int.");
789 template <
class Archive>
790 inline void load_typeid(Archive &ar, TypeID &t)
795 throw SerializationError(
"TypeID out of range");
797 t =
static_cast<TypeID
>(i);
801 template <
class Archive,
class T>
807 throw SerializationError(
"Need a RCPBasicAwareInputArchive");
809 ptr = ar_ptr->template load_rcp_basic<T>();
The base class for SymEngine.
static RCP< const Number > from_two_nums(const Number &re, const Number &im)
void rtti()
Overload the rtti function to enable dynamic_cast.
static RCP< const Number > from_two_ints(const Integer &n, const Integer &d)
Main namespace for SymEngine package.
RCP< const Dummy > dummy()
inline version to return Dummy
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
RCP< const Reals > reals()
RCP< const EmptySet > emptyset()
RCP< const Integers > integers()
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
RCP< const UniversalSet > universalset()
RCP< const Constant > constant(const std::string &name)
inline version to return Constant
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.
RCP< const Rationals > rationals()
RCP< const Number > addnum(const RCP< const Number > &self, const RCP< const Number > &other)
Add self and other