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);
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());
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 Mul &b)
166 template <
class Archive>
167 inline void save_basic(Archive &ar,
const Add &b)
172 template <
class Archive>
173 inline void save_basic(Archive &ar,
const Pow &b)
178 template <
typename Archive>
179 void save_helper(Archive &ar,
const integer_class &intgr)
185 template <
typename Archive>
186 void save_helper(Archive &ar,
const rational_class &rat)
188 integer_class num = get_num(rat);
189 integer_class den = get_den(rat);
190 save_helper(ar, num);
191 save_helper(ar, den);
195 template <
typename Archive>
196 void save_basic(Archive &ar,
const URatPoly &b)
199 const URatDict &urd = b.get_poly();
200 size_t l = urd.size();
202 for (
auto &p : urd.dict_) {
203 unsigned int first = p.first;
204 const rational_class &second = p.second;
206 save_helper(ar, second);
209 template <
class Archive>
210 inline void save_basic(Archive &ar,
const Integer &b)
214 template <
class Archive>
215 inline void save_basic(Archive &ar,
const RealDouble &b)
219 template <
class Archive>
220 inline void save_basic(Archive &ar,
const Rational &b)
222 ar(b.get_num(), b.get_den());
224 template <
class Archive>
225 inline void save_basic(Archive &ar,
const ComplexBase &b)
227 ar(b.real_part(), b.imaginary_part());
229 template <
class Archive>
230 inline void save_basic(Archive &ar,
const Interval &b)
232 ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
234 template <
class Archive>
235 inline void save_basic(Archive &ar,
const BooleanAtom &b)
239 template <
class Archive>
240 inline void save_basic(Archive &ar,
const Infty &b)
242 ar(b.get_direction());
245 template <
class Archive>
246 inline void save_basic(Archive &ar,
const NaN &b)
250 template <
class Archive>
251 inline void save_basic(Archive &ar,
const Constant &b)
255 template <
class Archive>
256 inline void save_basic(Archive &ar,
const OneArgFunction &b)
260 template <
class Archive>
261 inline void save_basic(Archive &ar,
const TwoArgFunction &b)
263 ar(b.get_arg1(), b.get_arg2());
266 template <
class Archive>
267 inline void save_basic(Archive &ar,
const Relational &b)
269 ar(b.get_arg1(), b.get_arg2());
271 template <
class Archive>
272 inline void save_basic(Archive &ar,
const And &b)
274 ar(b.get_container());
276 template <
class Archive>
277 inline void save_basic(Archive &ar,
const Or &b)
279 ar(b.get_container());
281 template <
class Archive>
282 inline void save_basic(Archive &ar,
const Xor &b)
284 ar(b.get_container());
286 template <
class Archive>
287 inline void save_basic(Archive &ar,
const Not &b)
291 template <
class Archive>
292 inline void save_basic(Archive &ar,
const Contains &b)
294 ar(b.get_expr(), b.get_set());
296 template <
class Archive>
297 inline void save_basic(Archive &ar,
const Piecewise &b)
301 template <
class Archive>
302 inline void save_basic(Archive &ar,
const Reals &b)
305 template <
class Archive>
306 inline void save_basic(Archive &ar,
const Rationals &b)
309 template <
class Archive>
310 inline void save_basic(Archive &ar,
const EmptySet &b)
313 template <
class Archive>
314 inline void save_basic(Archive &ar,
const Integers &b)
317 template <
class Archive>
318 inline void save_basic(Archive &ar,
const UniversalSet &b)
321 template <
class Archive>
322 inline void save_basic(Archive &ar,
const Union &b)
324 ar(b.get_container());
326 template <
class Archive>
327 inline void save_basic(Archive &ar,
const Complement &b)
329 ar(b.get_universe(), b.get_container());
331 template <
class Archive>
332 inline void save_basic(Archive &ar,
const ImageSet &b)
334 ar(b.get_symbol(), b.get_expr(), b.get_baseset());
336 template <
class Archive>
337 inline void save_basic(Archive &ar,
const FiniteSet &b)
339 ar(b.get_container());
341 template <
class Archive>
342 inline void save_basic(Archive &ar,
const ConditionSet &b)
344 ar(b.get_symbol(), b.get_condition());
346 #ifdef HAVE_SYMENGINE_MPFR
347 template <
class Archive>
348 inline void save_basic(Archive &ar,
const RealMPFR &b)
350 ar(b.__str__(), b.get_prec());
353 template <
class Archive>
354 inline void save_basic(Archive &ar,
const GaloisField &b)
356 throw NotImplementedError(
"GaloisField saving is not implemented yet.");
358 template <
class Archive>
359 inline void save_basic(Archive &ar,
const SeriesCoeffInterface &)
361 throw NotImplementedError(
"Series saving is not implemented yet.");
363 template <
class Archive>
364 inline void save_basic(Archive &ar,
const MultiArgFunction &b)
368 template <
class Archive>
369 inline void save_basic(Archive &ar,
const FunctionSymbol &b)
371 ar(b.get_name(), b.get_args());
373 template <
class Archive>
374 inline void save_basic(Archive &ar,
const Derivative &b)
376 ar(b.get_arg(), b.get_symbols());
378 template <
class Archive>
379 inline void save_basic(Archive &ar,
const Subs &b)
381 ar(b.get_arg(), b.get_dict());
383 template <
class Archive>
384 inline void save_basic(Archive &ar,
const NumberWrapper &b)
386 throw NotImplementedError(
"NumberWrapper saving is not implemented yet.");
388 template <
class Archive>
389 inline void save_basic(Archive &ar,
const FunctionWrapper &b)
391 throw NotImplementedError(
"FunctionWrapper saving is not implemented yet.");
395 template <
class Archive,
class T>
401 throw SerializationError(
"Need a RCPBasicAwareOutputArchive");
403 ar_ptr->save_rcp_basic(rcp_static_cast<const Basic>(ptr));
405 template <
class Archive>
406 RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
410 return real_double(val);
412 template <
class Archive>
413 RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
415 RCP<const Number> direction;
417 return Infty::from_direction(direction);
419 template <
class Archive>
420 RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
422 return rcp_static_cast<const Basic>(Nan);
424 template <
class Archive>
425 RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
431 template <
class Archive>
432 RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
434 RCP<const Number> coeff;
435 map_basic_basic dict;
438 return make_rcp<const Mul>(coeff,
std::move(dict));
440 template <
class Archive>
441 RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
443 RCP<const Number> coeff;
447 return make_rcp<const Add>(coeff,
std::move(dict));
449 template <
class Archive>
450 RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
452 RCP<const Basic> base,
exp;
455 return make_rcp<const Pow>(base,
exp);
457 template <
typename Archive>
458 void load_helper(Archive &ar, integer_class &intgr)
462 if (int_str.
size() == 0) {
463 throw SerializationError(
"invalid integer");
465 if (not(int_str[0] ==
'-' or
std::isdigit(int_str[0]))) {
466 throw SerializationError(
"invalid integer");
468 for (
auto it = ++int_str.
begin(); it < int_str.
end(); it++) {
470 throw SerializationError(
"invalid integer");
473 intgr = integer_class(
std::move(int_str));
475 template <
typename Archive>
476 void load_helper(Archive &ar,
const rational_class &rat)
478 integer_class num, den;
479 load_helper(ar, num);
480 load_helper(ar, den);
484 template <
typename Archive>
485 RCP<const Basic> load_basic(Archive &ar,
const URatPoly &b)
487 RCP<const Basic> var;
492 auto hint = d.
begin();
493 for (
size_t i = 0; i < l; i++) {
495 rational_class second;
497 load_helper(ar, second);
498 #if !defined(__clang__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
504 return make_rcp<const URatPoly>(var, URatDict(
std::move(d)));
506 template <
class Archive>
507 RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
513 template <
class Archive>
514 RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
520 template <
class Archive>
521 RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
523 RCP<const Integer> num, den;
527 template <
class Archive>
528 RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
530 RCP<const Number> num, den;
534 template <
class Archive,
class T>
536 load_basic(Archive &ar, RCP<const T> &,
538 int>::type * =
nullptr)
540 RCP<const Number> num, den;
544 template <
class Archive>
545 RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
547 RCP<const Number> start,
end;
548 bool left_open, right_open;
549 ar(left_open, start, right_open, end);
550 return make_rcp<const Interval>(start, end, left_open, right_open);
552 template <
class Archive>
553 RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
559 template <
class Archive>
560 RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
562 set_boolean container;
564 return make_rcp<const And>(
std::move(container));
566 template <
class Archive>
567 RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
569 set_boolean container;
571 return make_rcp<const Or>(
std::move(container));
573 template <
class Archive>
574 RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
576 vec_boolean container;
578 return make_rcp<const Xor>(
std::move(container));
580 template <
class Archive>
581 RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
583 RCP<const Boolean> arg;
585 return make_rcp<const Not>(arg);
587 template <
class Archive>
588 RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
592 return make_rcp<const Piecewise>(
std::move(vec));
594 template <
class Archive>
595 RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
597 RCP<const Basic> expr;
598 RCP<const Set> contains_set;
599 ar(expr, contains_set);
600 return make_rcp<const Contains>(expr, contains_set);
602 template <
class Archive>
603 RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
607 template <
class Archive>
608 RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
612 template <
class Archive>
613 RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
617 template <
class Archive>
618 RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
622 template <
class Archive>
623 RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
627 template <
class Archive>
628 RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
632 return make_rcp<const Union>(
std::move(union_set));
634 template <
class Archive>
635 RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
637 RCP<const Set> universe, container;
638 ar(universe, container);
639 return make_rcp<const Complement>(universe, container);
641 template <
class Archive>
642 RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
644 RCP<const Basic> sym, expr;
647 return make_rcp<const ImageSet>(sym, expr, base);
649 template <
class Archive>
650 RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
654 return make_rcp<const FiniteSet>(set);
656 template <
class Archive>
657 RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
659 RCP<const Basic> sym;
660 RCP<const Boolean> condition;
662 return make_rcp<const ConditionSet>(sym, condition);
664 #ifdef HAVE_SYMENGINE_MPFR
665 template <
class Archive>
666 RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
671 return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
674 template <
class Archive>
675 RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
677 RCP<const Basic> arg;
680 return make_rcp<const Derivative>(arg,
std::move(set));
682 template <
class Archive>
683 RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
685 RCP<const Basic> arg;
686 map_basic_basic dict;
688 return make_rcp<const Subs>(arg,
std::move(dict));
691 template <
class Archive,
class T>
693 load_basic(Archive &ar, RCP<const T> &,
695 int>::type * =
nullptr)
697 RCP<const Basic> arg;
699 return make_rcp<const T>(arg);
701 template <
class Archive,
class T>
703 load_basic(Archive &ar, RCP<const T> &,
705 int>::type * =
nullptr)
707 RCP<const Basic> arg1, arg2;
709 return make_rcp<const T>(arg1, arg2);
711 template <
class Archive>
712 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
717 return make_rcp<const FunctionSymbol>(name,
std::move(vec));
719 template <
class Archive>
720 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
722 throw SerializationError(StreamFmt()
723 << __FILE__ <<
":" << __LINE__
725 <<
": " << __PRETTY_FUNCTION__
727 <<
"Loading of this type is not implemented.");
729 template <
class Archive,
class T>
731 load_basic(Archive &ar, RCP<const T> &,
733 int>::type * =
nullptr)
737 return make_rcp<const T>(
std::move(args));
739 template <
class Archive,
class T>
741 load_basic(Archive &ar, RCP<const T> &,
743 int>::type * =
nullptr)
745 RCP<const Basic> arg1, arg2;
747 return make_rcp<const T>(arg1, arg2);
749 template <
class Archive,
class T>
750 RCP<const Basic> load_basic(
751 Archive &ar, RCP<const T> &,
757 int>::type * =
nullptr)
759 throw SerializationError(StreamFmt()
760 << __FILE__ <<
":" << __LINE__
762 <<
": " << __PRETTY_FUNCTION__
764 <<
"Loading of this type is not implemented.");
767 template <
class Archive>
768 inline void save_typeid(Archive &ar, TypeID &t)
772 "TypeID cannot be saved to a 8 bit int.");
776 template <
class Archive>
777 inline void load_typeid(Archive &ar, TypeID &t)
782 throw SerializationError(
"TypeID out of range");
784 t =
static_cast<TypeID
>(i);
788 template <
class Archive,
class T>
794 throw SerializationError(
"Need a RCPBasicAwareInputArchive");
796 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)
T emplace_hint(T... args)
Main namespace for SymEngine package.
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