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());
51 _keep_alive.push_back(ptr);
52 TypeID type_code = ptr->get_type_code();
53 save_typeid(*
this, type_code);
55 #define SYMENGINE_ENUM(type, Class) \
57 save_basic(*this, static_cast<const Class &>(*ptr)); \
59 #include "symengine/type_codes.inc"
62 save_basic(*
this, *ptr);
64 _addresses.insert(addr);
68 std::set<uintptr_t> _addresses;
69 std::vector<RCP<const Basic>> _keep_alive;
74 template <
class Archive>
77 using Archive::Archive;
81 RCP<const T> load_rcp_basic()
90 if (first_seen >= 2) {
91 throw SerializationError(
"Invalid input");
95 auto it = _rcp_map.find(addr);
96 if (it == _rcp_map.end()) {
97 throw SerializationError(
"Invalid shared pointer");
99 RCP<const Basic> b = it->second;
100 switch (b->get_type_code()) {
101 #define SYMENGINE_ENUM(type_enum, Class) \
103 if (not std::is_base_of<T, Class>::value) { \
104 throw SerializationError("Cannot convert to given type"); \
106 return rcp_static_cast<const T>(b); \
109 #include "symengine/type_codes.inc"
110 #undef SYMENGINE_ENUM
112 throw SerializationError(
"Unknown typeID");
117 load_typeid(*
this, type_code);
119 #define SYMENGINE_ENUM(type_enum, Class) \
121 RCP<const Class> dummy_ptr; \
122 RCP<const Basic> basic_ptr = load_basic(*this, dummy_ptr); \
123 _rcp_map[addr] = basic_ptr; \
124 if (not std::is_base_of<T, Class>::value) { \
125 throw SerializationError("Cannot convert to given type"); \
127 return rcp_static_cast<const T>(basic_ptr); \
130 #include "symengine/type_codes.inc"
131 #undef SYMENGINE_ENUM
133 throw SerializationError(
"Unknown typeID");
135 }
catch (cereal::Exception &e) {
136 throw SerializationError(e.what());
141 std::unordered_map<uintptr_t, RCP<const Basic>> _rcp_map;
146 template <
class Archive>
147 inline void save_basic(Archive &ar,
const Basic &b)
149 const auto t_code = b.get_type_code();
150 throw SerializationError(StreamFmt()
151 << __FILE__ <<
":" << __LINE__
153 <<
": " << __PRETTY_FUNCTION__
155 <<
" not supported: " << type_code_name(t_code)
156 <<
" (" << t_code <<
")"
158 <<
", " << b.__str__()
162 template <
class Archive>
163 inline void save_basic(Archive &ar,
const Symbol &b)
167 template <
class Archive>
168 inline void save_basic(Archive &ar,
const Dummy &b)
170 ar(b.get_name(), b.get_index());
172 template <
class Archive>
173 inline void save_basic(Archive &ar,
const Mul &b)
178 template <
class Archive>
179 inline void save_basic(Archive &ar,
const Add &b)
184 template <
class Archive>
185 inline void save_basic(Archive &ar,
const Pow &b)
190 template <
typename Archive>
191 void save_helper(Archive &ar,
const integer_class &intgr)
193 std::ostringstream s;
197 template <
typename Archive>
198 void save_helper(Archive &ar,
const rational_class &rat)
200 integer_class num = get_num(rat);
201 integer_class den = get_den(rat);
202 save_helper(ar, num);
203 save_helper(ar, den);
207 template <
typename Archive>
208 void save_basic(Archive &ar,
const URatPoly &b)
211 const URatDict &urd = b.get_poly();
212 size_t l = urd.size();
214 for (
auto &p : urd.dict_) {
215 unsigned int first = p.first;
216 const rational_class &second = p.second;
218 save_helper(ar, second);
221 template <
class Archive>
222 inline void save_basic(Archive &ar,
const Integer &b)
226 template <
class Archive>
227 inline void save_basic(Archive &ar,
const RealDouble &b)
231 template <
class Archive>
232 inline void save_basic(Archive &ar,
const Rational &b)
234 ar(b.get_num(), b.get_den());
236 template <
class Archive>
237 inline void save_basic(Archive &ar,
const ComplexBase &b)
239 ar(b.real_part(), b.imaginary_part());
241 template <
class Archive>
242 inline void save_basic(Archive &ar,
const Interval &b)
244 ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
246 template <
class Archive>
247 inline void save_basic(Archive &ar,
const BooleanAtom &b)
251 template <
class Archive>
252 inline void save_basic(Archive &ar,
const Infty &b)
254 ar(b.get_direction());
257 template <
class Archive>
258 inline void save_basic(Archive &ar,
const NaN &b)
262 template <
class Archive>
263 inline void save_basic(Archive &ar,
const Constant &b)
267 template <
class Archive>
268 inline void save_basic(Archive &ar,
const OneArgFunction &b)
272 template <
class Archive>
273 inline void save_basic(Archive &ar,
const TwoArgFunction &b)
275 ar(b.get_arg1(), b.get_arg2());
278 template <
class Archive>
279 inline void save_basic(Archive &ar,
const Relational &b)
281 ar(b.get_arg1(), b.get_arg2());
283 template <
class Archive>
284 inline void save_basic(Archive &ar,
const And &b)
286 ar(b.get_container());
288 template <
class Archive>
289 inline void save_basic(Archive &ar,
const Or &b)
291 ar(b.get_container());
293 template <
class Archive>
294 inline void save_basic(Archive &ar,
const Xor &b)
296 ar(b.get_container());
298 template <
class Archive>
299 inline void save_basic(Archive &ar,
const Not &b)
303 template <
class Archive>
304 inline void save_basic(Archive &ar,
const Contains &b)
306 ar(b.get_expr(), b.get_set());
308 template <
class Archive>
309 inline void save_basic(Archive &ar,
const Piecewise &b)
313 template <
class Archive>
314 inline void save_basic(Archive &ar,
const Reals &b)
317 template <
class Archive>
318 inline void save_basic(Archive &ar,
const Rationals &b)
321 template <
class Archive>
322 inline void save_basic(Archive &ar,
const EmptySet &b)
325 template <
class Archive>
326 inline void save_basic(Archive &ar,
const Integers &b)
329 template <
class Archive>
330 inline void save_basic(Archive &ar,
const UniversalSet &b)
333 template <
class Archive>
334 inline void save_basic(Archive &ar,
const Union &b)
336 ar(b.get_container());
338 template <
class Archive>
339 inline void save_basic(Archive &ar,
const Complement &b)
341 ar(b.get_universe(), b.get_container());
343 template <
class Archive>
344 inline void save_basic(Archive &ar,
const ImageSet &b)
346 ar(b.get_symbol(), b.get_expr(), b.get_baseset());
348 template <
class Archive>
349 inline void save_basic(Archive &ar,
const FiniteSet &b)
351 ar(b.get_container());
353 template <
class Archive>
354 inline void save_basic(Archive &ar,
const ConditionSet &b)
356 ar(b.get_symbol(), b.get_condition());
358 #ifdef HAVE_SYMENGINE_MPFR
359 template <
class Archive>
360 inline void save_basic(Archive &ar,
const RealMPFR &b)
362 ar(b.__str__(), b.get_prec());
365 template <
class Archive>
366 inline void save_basic(Archive &ar,
const GaloisField &b)
368 throw NotImplementedError(
"GaloisField saving is not implemented yet.");
370 template <
class Archive>
371 inline void save_basic(Archive &ar,
const SeriesCoeffInterface &)
373 throw NotImplementedError(
"Series saving is not implemented yet.");
375 template <
class Archive>
376 inline void save_basic(Archive &ar,
const MultiArgFunction &b)
380 template <
class Archive>
381 inline void save_basic(Archive &ar,
const FunctionSymbol &b)
383 ar(b.get_name(), b.get_args());
385 template <
class Archive>
386 inline void save_basic(Archive &ar,
const Derivative &b)
388 ar(b.get_arg(), b.get_symbols());
390 template <
class Archive>
391 inline void save_basic(Archive &ar,
const Subs &b)
393 ar(b.get_arg(), b.get_dict());
395 template <
class Archive>
396 inline void save_basic(Archive &ar,
const NumberWrapper &b)
398 throw NotImplementedError(
"NumberWrapper saving is not implemented yet.");
400 template <
class Archive>
401 inline void save_basic(Archive &ar,
const FunctionWrapper &b)
403 throw NotImplementedError(
"FunctionWrapper saving is not implemented yet.");
407 template <
class Archive,
class T>
413 throw SerializationError(
"Need a RCPBasicAwareOutputArchive");
415 ar_ptr->save_rcp_basic(rcp_static_cast<const Basic>(ptr));
417 template <
class Archive>
418 RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
422 return real_double(val);
424 template <
class Archive>
425 RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
427 RCP<const Number> direction;
429 return Infty::from_direction(direction);
431 template <
class Archive>
432 RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
434 return rcp_static_cast<const Basic>(Nan);
436 template <
class Archive>
437 RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
443 template <
class Archive>
444 RCP<const Basic> load_basic(Archive &ar, RCP<const Dummy> &)
449 return dummy(name, index);
451 template <
class Archive>
452 RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
454 RCP<const Number> coeff;
455 map_basic_basic dict;
458 return make_rcp<const Mul>(coeff, std::move(dict));
460 template <
class Archive>
461 RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
463 RCP<const Number> coeff;
467 return make_rcp<const Add>(coeff, std::move(dict));
469 template <
class Archive>
470 RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
472 RCP<const Basic> base,
exp;
475 return make_rcp<const Pow>(base,
exp);
477 template <
typename Archive>
478 void load_helper(Archive &ar, integer_class &intgr)
482 if (int_str.size() == 0) {
483 throw SerializationError(
"invalid integer");
485 if (not(int_str[0] ==
'-' or std::isdigit(int_str[0]))) {
486 throw SerializationError(
"invalid integer");
488 for (
auto it = ++int_str.begin(); it < int_str.end(); it++) {
489 if (not std::isdigit(*it)) {
490 throw SerializationError(
"invalid integer");
493 intgr = integer_class(std::move(int_str));
495 template <
typename Archive>
496 void load_helper(Archive &ar,
const rational_class &rat)
498 integer_class num, den;
499 load_helper(ar, num);
500 load_helper(ar, den);
504 template <
typename Archive>
505 RCP<const Basic> load_basic(Archive &ar,
const URatPoly &b)
507 RCP<const Basic> var;
511 std::map<unsigned, rational_class> d;
512 auto hint = d.begin();
513 for (
size_t i = 0; i < l; i++) {
515 rational_class second;
517 load_helper(ar, second);
518 #if !defined(__clang__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
519 d.insert(hint, std::make_pair(std::move(first), std::move(second)));
521 d.emplace_hint(hint, std::move(first), std::move(second));
524 return make_rcp<const URatPoly>(var, URatDict(std::move(d)));
526 template <
class Archive>
527 RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
533 template <
class Archive>
534 RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
540 template <
class Archive>
541 RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
543 RCP<const Integer> num, den;
547 template <
class Archive>
548 RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
550 RCP<const Number> num, den;
554 template <
class Archive,
class T>
556 load_basic(Archive &ar, RCP<const T> &,
557 typename std::enable_if<std::is_base_of<ComplexBase, T>::value,
558 int>::type * =
nullptr)
560 RCP<const Number> num, den;
564 template <
class Archive>
565 RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
567 RCP<const Number> start, end;
568 bool left_open, right_open;
569 ar(left_open, start, right_open, end);
570 return make_rcp<const Interval>(start, end, left_open, right_open);
572 template <
class Archive>
573 RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
579 template <
class Archive>
580 RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
582 set_boolean container;
584 return make_rcp<const And>(std::move(container));
586 template <
class Archive>
587 RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
589 set_boolean container;
591 return make_rcp<const Or>(std::move(container));
593 template <
class Archive>
594 RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
596 vec_boolean container;
598 return make_rcp<const Xor>(std::move(container));
600 template <
class Archive>
601 RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
603 RCP<const Boolean> arg;
605 return make_rcp<const Not>(arg);
607 template <
class Archive>
608 RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
612 return make_rcp<const Piecewise>(std::move(vec));
614 template <
class Archive>
615 RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
617 RCP<const Basic> expr;
618 RCP<const Set> contains_set;
619 ar(expr, contains_set);
620 return make_rcp<const Contains>(expr, contains_set);
622 template <
class Archive>
623 RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
627 template <
class Archive>
628 RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
632 template <
class Archive>
633 RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
637 template <
class Archive>
638 RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
642 template <
class Archive>
643 RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
647 template <
class Archive>
648 RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
652 return make_rcp<const Union>(std::move(union_set));
654 template <
class Archive>
655 RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
657 RCP<const Set> universe, container;
658 ar(universe, container);
659 return make_rcp<const Complement>(universe, container);
661 template <
class Archive>
662 RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
664 RCP<const Basic> sym, expr;
667 return make_rcp<const ImageSet>(sym, expr, base);
669 template <
class Archive>
670 RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
674 return make_rcp<const FiniteSet>(set);
676 template <
class Archive>
677 RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
679 RCP<const Basic> sym;
680 RCP<const Boolean> condition;
682 return make_rcp<const ConditionSet>(sym, condition);
684 #ifdef HAVE_SYMENGINE_MPFR
685 template <
class Archive>
686 RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
691 return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
694 template <
class Archive>
695 RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
697 RCP<const Basic> arg;
700 return make_rcp<const Derivative>(arg, std::move(set));
702 template <
class Archive>
703 RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
705 RCP<const Basic> arg;
706 map_basic_basic dict;
708 return make_rcp<const Subs>(arg, std::move(dict));
711 template <
class Archive,
class T>
713 load_basic(Archive &ar, RCP<const T> &,
714 typename std::enable_if<std::is_base_of<OneArgFunction, T>::value,
715 int>::type * =
nullptr)
717 RCP<const Basic> arg;
719 return make_rcp<const T>(arg);
721 template <
class Archive,
class T>
723 load_basic(Archive &ar, RCP<const T> &,
724 typename std::enable_if<std::is_base_of<TwoArgFunction, T>::value,
725 int>::type * =
nullptr)
727 RCP<const Basic> arg1, arg2;
729 return make_rcp<const T>(arg1, arg2);
731 template <
class Archive>
732 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
737 return make_rcp<const FunctionSymbol>(name, std::move(vec));
739 template <
class Archive>
740 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
742 throw SerializationError(StreamFmt()
743 << __FILE__ <<
":" << __LINE__
745 <<
": " << __PRETTY_FUNCTION__
747 <<
"Loading of this type is not implemented.");
749 template <
class Archive,
class T>
751 load_basic(Archive &ar, RCP<const T> &,
752 typename std::enable_if<std::is_base_of<MultiArgFunction, T>::value,
753 int>::type * =
nullptr)
757 return make_rcp<const T>(std::move(args));
759 template <
class Archive,
class T>
761 load_basic(Archive &ar, RCP<const T> &,
762 typename std::enable_if<std::is_base_of<Relational, T>::value,
763 int>::type * =
nullptr)
765 RCP<const Basic> arg1, arg2;
767 return make_rcp<const T>(arg1, arg2);
769 template <
class Archive,
class T>
770 RCP<const Basic> load_basic(
771 Archive &ar, RCP<const T> &,
772 typename std::enable_if<not(std::is_base_of<Relational, T>::value
773 or std::is_base_of<ComplexBase, T>::value
774 or std::is_base_of<OneArgFunction, T>::value
775 or std::is_base_of<MultiArgFunction, T>::value
776 or std::is_base_of<TwoArgFunction, T>::value),
777 int>::type * =
nullptr)
779 throw SerializationError(StreamFmt()
780 << __FILE__ <<
":" << __LINE__
782 <<
": " << __PRETTY_FUNCTION__
784 <<
"Loading of this type is not implemented.");
787 template <
class Archive>
788 inline void save_typeid(Archive &ar, TypeID &t)
792 "TypeID cannot be saved to a 8 bit int.");
796 template <
class Archive>
797 inline void load_typeid(Archive &ar, TypeID &t)
802 throw SerializationError(
"TypeID out of range");
804 t =
static_cast<TypeID
>(i);
808 template <
class Archive,
class T>
814 throw SerializationError(
"Need a RCPBasicAwareInputArchive");
816 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