serialize-cereal.h
1 #ifndef SYMENGINE_SERIALIZE_CEREAL_H
2 #define SYMENGINE_SERIALIZE_CEREAL_H
3 
4 #include <cctype>
5 
6 #include <symengine/basic.h>
7 #include <symengine/number.h>
8 #include <symengine/integer.h>
9 #include <symengine/symbol.h>
10 #include <symengine/visitor.h>
11 #include <symengine/utilities/stream_fmt.h>
12 
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>
24 
25 namespace SymEngine
26 {
27 
28 template <class Archive>
29 class RCPBasicAwareOutputArchive : public Archive
30 {
31  using Archive::Archive;
32 
33 public:
34  void save_rcp_basic(const RCP<const Basic> &ptr)
35  {
36  uintptr_t addr = (uintptr_t)(void *)ptr.get();
37  (*this)(addr);
38 
39  auto id = _addresses.find(addr);
40  uint8_t first_seen = (id == _addresses.end());
41  (*this)(first_seen);
42 
43  if (not first_seen) {
44  return;
45  }
46  // Keep a reference to every serialized object for the lifetime of the
47  // archive, as some are temporary objects (e.g. Rational::get_num).
48  // Without this a temp object can be freed and its address
49  // then re-used by another temp object, which is then incorrectly
50  // serialized as the previous object seen at this address.
51  _keep_alive.push_back(ptr);
52  TypeID type_code = ptr->get_type_code();
53  save_typeid(*this, type_code);
54  switch (type_code) {
55 #define SYMENGINE_ENUM(type, Class) \
56  case type: \
57  save_basic(*this, static_cast<const Class &>(*ptr)); \
58  break;
59 #include "symengine/type_codes.inc"
60 #undef SYMENGINE_ENUM
61  default:
62  save_basic(*this, *ptr);
63  }
64  _addresses.insert(addr);
65  }
66 
67 private:
68  std::set<uintptr_t> _addresses;
69  std::vector<RCP<const Basic>> _keep_alive;
71  void rtti(){};
72 };
73 
74 template <class Archive>
75 class RCPBasicAwareInputArchive : public Archive
76 {
77  using Archive::Archive;
78 
79 public:
80  template <class T>
81  RCP<const T> load_rcp_basic()
82  {
83  try {
84  uintptr_t addr;
85  (*this)(addr);
86 
87  uint8_t first_seen;
88  (*this)(first_seen);
89 
90  if (first_seen >= 2) {
91  throw SerializationError("Invalid input");
92  }
93 
94  if (not first_seen) {
95  auto it = _rcp_map.find(addr);
96  if (it == _rcp_map.end()) {
97  throw SerializationError("Invalid shared pointer");
98  }
99  RCP<const Basic> b = it->second;
100  switch (b->get_type_code()) {
101 #define SYMENGINE_ENUM(type_enum, Class) \
102  case type_enum: { \
103  if (not std::is_base_of<T, Class>::value) { \
104  throw SerializationError("Cannot convert to given type"); \
105  } else { \
106  return rcp_static_cast<const T>(b); \
107  } \
108  }
109 #include "symengine/type_codes.inc"
110 #undef SYMENGINE_ENUM
111  default:
112  throw SerializationError("Unknown typeID");
113  }
114  }
115 
116  TypeID type_code;
117  load_typeid(*this, type_code);
118  switch (type_code) {
119 #define SYMENGINE_ENUM(type_enum, Class) \
120  case type_enum: { \
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"); \
126  } else { \
127  return rcp_static_cast<const T>(basic_ptr); \
128  } \
129  }
130 #include "symengine/type_codes.inc"
131 #undef SYMENGINE_ENUM
132  default:
133  throw SerializationError("Unknown typeID");
134  }
135  } catch (cereal::Exception &e) {
136  throw SerializationError(e.what());
137  }
138  }
139 
140 private:
141  std::unordered_map<uintptr_t, RCP<const Basic>> _rcp_map;
143  void rtti(){};
144 };
145 
146 template <class Archive>
147 inline void save_basic(Archive &ar, const Basic &b)
148 {
149  const auto t_code = b.get_type_code();
150  throw SerializationError(StreamFmt()
151  << __FILE__ << ":" << __LINE__
152 #ifndef _MSC_VER
153  << ": " << __PRETTY_FUNCTION__
154 #endif
155  << " not supported: " << type_code_name(t_code)
156  << " (" << t_code << ")"
157 #if !defined(NDEBUG)
158  << ", " << b.__str__()
159 #endif
160  );
161 }
162 template <class Archive>
163 inline void save_basic(Archive &ar, const Symbol &b)
164 {
165  ar(b.__str__());
166 }
167 template <class Archive>
168 inline void save_basic(Archive &ar, const Dummy &b)
169 {
170  ar(b.get_name(), b.get_index());
171 }
172 template <class Archive>
173 inline void save_basic(Archive &ar, const Mul &b)
174 {
175  ar(b.get_coef());
176  ar(b.get_dict());
177 }
178 template <class Archive>
179 inline void save_basic(Archive &ar, const Add &b)
180 {
181  ar(b.get_coef());
182  ar(b.get_dict());
183 }
184 template <class Archive>
185 inline void save_basic(Archive &ar, const Pow &b)
186 {
187  ar(b.get_base());
188  ar(b.get_exp());
189 }
190 template <typename Archive>
191 void save_helper(Archive &ar, const integer_class &intgr)
192 {
193  std::ostringstream s;
194  s << intgr; // stream to string
195  ar(s.str());
196 }
197 template <typename Archive>
198 void save_helper(Archive &ar, const rational_class &rat)
199 {
200  integer_class num = get_num(rat);
201  integer_class den = get_den(rat);
202  save_helper(ar, num);
203  save_helper(ar, den);
204 }
205 template <typename Archive>
206 void save_helper(Archive &ar, const Expression &c)
207 {
208  ar(c.get_basic());
209 }
210 template <typename Archive, typename Container>
211 void save_poly_dict(Archive &ar, const Container &c)
212 {
213  ar(c.dict_.size());
214  for (const auto &term : c.dict_) {
215  ar(term.first);
216  save_helper(ar, term.second);
217  }
218 }
219 template <typename Archive>
220 void save_basic(Archive &ar, const UIntPoly &b)
221 {
222  ar(b.get_var());
223  save_poly_dict(ar, b.get_poly());
224 }
225 template <typename Archive>
226 void save_basic(Archive &ar, const URatPoly &b)
227 {
228  ar(b.get_var());
229  save_poly_dict(ar, b.get_poly());
230 }
231 template <typename Archive>
232 void save_basic(Archive &ar, const UExprPoly &b)
233 {
234  ar(b.get_var());
235  save_poly_dict(ar, b.get_poly());
236 }
237 template <typename Archive>
238 void save_basic(Archive &ar, const MIntPoly &b)
239 {
240  ar(b.get_vars());
241  save_poly_dict(ar, b.get_poly());
242 }
243 template <typename Archive>
244 void save_basic(Archive &ar, const MExprPoly &b)
245 {
246  ar(b.get_vars());
247  save_poly_dict(ar, b.get_poly());
248 }
249 #if defined(HAVE_SYMENGINE_FLINT) || defined(HAVE_SYMENGINE_PIRANHA)
250 template <typename Archive, typename Poly>
251 void save_dense_poly(Archive &ar, const Poly &b)
252 {
253  ar(b.get_var());
254  unsigned int size = static_cast<unsigned int>(b.size());
255  ar(size);
256  for (unsigned int i = 0; i < size; ++i) {
257  save_helper(ar, b.get_coeff(i));
258  }
259 }
260 #endif
261 #ifdef HAVE_SYMENGINE_FLINT
262 template <typename Archive>
263 void save_basic(Archive &ar, const UIntPolyFlint &b)
264 {
265  save_dense_poly(ar, b);
266 }
267 template <typename Archive>
268 void save_basic(Archive &ar, const URatPolyFlint &b)
269 {
270  save_dense_poly(ar, b);
271 }
272 #endif
273 #ifdef HAVE_SYMENGINE_PIRANHA
274 template <typename Archive>
275 void save_basic(Archive &ar, const UIntPolyPiranha &b)
276 {
277  save_dense_poly(ar, b);
278 }
279 template <typename Archive>
280 void save_basic(Archive &ar, const URatPolyPiranha &b)
281 {
282  save_dense_poly(ar, b);
283 }
284 #endif
285 template <class Archive>
286 inline void save_basic(Archive &ar, const Integer &b)
287 {
288  ar(b.__str__());
289 }
290 template <class Archive>
291 inline void save_basic(Archive &ar, const RealDouble &b)
292 {
293  ar(b.i);
294 }
295 template <class Archive>
296 inline void save_basic(Archive &ar, const Rational &b)
297 {
298  ar(b.get_num(), b.get_den());
299 }
300 template <class Archive>
301 inline void save_basic(Archive &ar, const ComplexBase &b)
302 {
303  ar(b.real_part(), b.imaginary_part());
304 }
305 template <class Archive>
306 inline void save_basic(Archive &ar, const Interval &b)
307 {
308  ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
309 }
310 template <class Archive>
311 inline void save_basic(Archive &ar, const BooleanAtom &b)
312 {
313  ar(b.get_val());
314 }
315 template <class Archive>
316 inline void save_basic(Archive &ar, const Infty &b)
317 {
318  ar(b.get_direction());
319 }
320 
321 template <class Archive>
322 inline void save_basic(Archive &ar, const NaN &b)
323 {
324 }
325 
326 template <class Archive>
327 inline void save_basic(Archive &ar, const Constant &b)
328 {
329  ar(b.get_name());
330 }
331 template <class Archive>
332 inline void save_basic(Archive &ar, const OneArgFunction &b)
333 {
334  ar(b.get_arg());
335 }
336 template <class Archive>
337 inline void save_basic(Archive &ar, const TwoArgFunction &b)
338 {
339  ar(b.get_arg1(), b.get_arg2());
340 }
341 
342 template <class Archive>
343 inline void save_basic(Archive &ar, const Relational &b)
344 {
345  ar(b.get_arg1(), b.get_arg2());
346 }
347 template <class Archive>
348 inline void save_basic(Archive &ar, const And &b)
349 {
350  ar(b.get_container());
351 }
352 template <class Archive>
353 inline void save_basic(Archive &ar, const Or &b)
354 {
355  ar(b.get_container());
356 }
357 template <class Archive>
358 inline void save_basic(Archive &ar, const Xor &b)
359 {
360  ar(b.get_container());
361 }
362 template <class Archive>
363 inline void save_basic(Archive &ar, const Not &b)
364 {
365  ar(b.get_arg());
366 }
367 template <class Archive>
368 inline void save_basic(Archive &ar, const Contains &b)
369 {
370  ar(b.get_expr(), b.get_set());
371 }
372 template <class Archive>
373 inline void save_basic(Archive &ar, const Piecewise &b)
374 {
375  ar(b.get_vec());
376 }
377 template <class Archive>
378 inline void save_basic(Archive &ar, const Reals &b)
379 {
380 }
381 template <class Archive>
382 inline void save_basic(Archive &ar, const Rationals &b)
383 {
384 }
385 template <class Archive>
386 inline void save_basic(Archive &ar, const EmptySet &b)
387 {
388 }
389 template <class Archive>
390 inline void save_basic(Archive &ar, const Integers &b)
391 {
392 }
393 template <class Archive>
394 inline void save_basic(Archive &ar, const UniversalSet &b)
395 {
396 }
397 template <class Archive>
398 inline void save_basic(Archive &ar, const Union &b)
399 {
400  ar(b.get_container());
401 }
402 template <class Archive>
403 inline void save_basic(Archive &ar, const Complement &b)
404 {
405  ar(b.get_universe(), b.get_container());
406 }
407 template <class Archive>
408 inline void save_basic(Archive &ar, const ImageSet &b)
409 {
410  ar(b.get_symbol(), b.get_expr(), b.get_baseset());
411 }
412 template <class Archive>
413 inline void save_basic(Archive &ar, const FiniteSet &b)
414 {
415  ar(b.get_container());
416 }
417 template <class Archive>
418 inline void save_basic(Archive &ar, const ConditionSet &b)
419 {
420  ar(b.get_symbol(), b.get_condition());
421 }
422 #ifdef HAVE_SYMENGINE_MPFR
423 template <class Archive>
424 inline void save_basic(Archive &ar, const RealMPFR &b)
425 {
426  ar(b.__str__(), b.get_prec());
427 }
428 #endif
429 template <class Archive>
430 inline void save_basic(Archive &ar, const GaloisField &b)
431 {
432  throw NotImplementedError("GaloisField saving is not implemented yet.");
433 }
434 template <class Archive>
435 inline void save_basic(Archive &ar, const SeriesCoeffInterface &)
436 {
437  throw NotImplementedError("Series saving is not implemented yet.");
438 }
439 template <class Archive>
440 inline void save_basic(Archive &ar, const MultiArgFunction &b)
441 {
442  ar(b.get_args());
443 }
444 template <class Archive>
445 inline void save_basic(Archive &ar, const FunctionSymbol &b)
446 {
447  ar(b.get_name(), b.get_args());
448 }
449 template <class Archive>
450 inline void save_basic(Archive &ar, const Derivative &b)
451 {
452  ar(b.get_arg(), b.get_symbols());
453 }
454 template <class Archive>
455 inline void save_basic(Archive &ar, const Subs &b)
456 {
457  ar(b.get_arg(), b.get_dict());
458 }
459 template <class Archive>
460 inline void save_basic(Archive &ar, const NumberWrapper &b)
461 {
462  throw NotImplementedError("NumberWrapper saving is not implemented yet.");
463 }
464 template <class Archive>
465 inline void save_basic(Archive &ar, const FunctionWrapper &b)
466 {
467  throw NotImplementedError("FunctionWrapper saving is not implemented yet.");
468 }
469 
471 template <class Archive, class T>
472 inline void CEREAL_SAVE_FUNCTION_NAME(Archive &ar, RCP<const T> const &ptr)
473 {
475  = dynamic_cast<RCPBasicAwareOutputArchive<Archive> *>(&ar);
476  if (not ar_ptr) {
477  throw SerializationError("Need a RCPBasicAwareOutputArchive");
478  }
479  ar_ptr->save_rcp_basic(rcp_static_cast<const Basic>(ptr));
480 }
481 template <class Archive>
482 RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
483 {
484  double val;
485  ar(val);
486  return real_double(val);
487 }
488 template <class Archive>
489 RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
490 {
491  RCP<const Number> direction;
492  ar(direction);
493  return Infty::from_direction(direction);
494 }
495 template <class Archive>
496 RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
497 {
498  return rcp_static_cast<const Basic>(Nan);
499 }
500 template <class Archive>
501 RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
502 {
503  std::string name;
504  ar(name);
505  return symbol(name);
506 }
507 template <class Archive>
508 RCP<const Basic> load_basic(Archive &ar, RCP<const Dummy> &)
509 {
510  std::string name;
511  size_t index;
512  ar(name, index);
513  return dummy(name, index);
514 }
515 template <class Archive>
516 RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
517 {
518  RCP<const Number> coeff;
519  map_basic_basic dict;
520  ar(coeff);
521  ar(dict);
522  return make_rcp<const Mul>(coeff, std::move(dict));
523 }
524 template <class Archive>
525 RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
526 {
527  RCP<const Number> coeff;
528  umap_basic_num dict;
529  ar(coeff);
530  ar(dict);
531  return make_rcp<const Add>(coeff, std::move(dict));
532 }
533 template <class Archive>
534 RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
535 {
536  RCP<const Basic> base, exp;
537  ar(base);
538  ar(exp);
539  return make_rcp<const Pow>(base, exp);
540 }
541 template <typename Archive>
542 void load_helper(Archive &ar, integer_class &intgr)
543 {
544  std::string int_str;
545  ar(int_str);
546  if (int_str.size() == 0) {
547  throw SerializationError("invalid integer");
548  }
549  if (not(int_str[0] == '-' or std::isdigit(int_str[0]))) {
550  throw SerializationError("invalid integer");
551  }
552  for (auto it = ++int_str.begin(); it < int_str.end(); it++) {
553  if (not std::isdigit(*it)) {
554  throw SerializationError("invalid integer");
555  }
556  }
557  intgr = integer_class(std::move(int_str));
558 }
559 template <typename Archive>
560 void load_helper(Archive &ar, rational_class &rat)
561 {
562  integer_class num, den;
563  load_helper(ar, num);
564  load_helper(ar, den);
565  rat = rational_class(num, den);
566 }
567 template <typename Archive>
568 void load_helper(Archive &ar, Expression &c)
569 {
570  RCP<const Basic> b;
571  ar(b);
572  c = Expression(std::move(b));
573 }
574 template <typename RawDict, typename Archive>
575 RawDict load_poly_dict(Archive &ar)
576 {
577  size_t size;
578  ar(size);
579  RawDict dict;
580  for (size_t i = 0; i < size; ++i) {
581  typename RawDict::key_type exponent;
582  typename RawDict::mapped_type coeff;
583  ar(exponent);
584  load_helper(ar, coeff);
585  dict.emplace(std::move(exponent), std::move(coeff));
586  }
587  return dict;
588 }
589 template <typename Archive>
590 RCP<const Basic> load_basic(Archive &ar, RCP<const UIntPoly> &)
591 {
592  RCP<const Basic> var;
593  ar(var);
594  return make_rcp<const UIntPoly>(var,
595  UIntDict(load_poly_dict<map_uint_mpz>(ar)));
596 }
597 template <typename Archive>
598 RCP<const Basic> load_basic(Archive &ar, RCP<const URatPoly> &)
599 {
600  RCP<const Basic> var;
601  ar(var);
602  return make_rcp<const URatPoly>(var,
603  URatDict(load_poly_dict<map_uint_mpq>(ar)));
604 }
605 template <typename Archive>
606 RCP<const Basic> load_basic(Archive &ar, RCP<const UExprPoly> &)
607 {
608  RCP<const Basic> var;
609  ar(var);
610  return make_rcp<const UExprPoly>(
611  var, UExprDict(load_poly_dict<map_int_Expr>(ar)));
612 }
613 template <typename Archive>
614 RCP<const Basic> load_basic(Archive &ar, RCP<const MIntPoly> &)
615 {
616  set_basic vars;
617  ar(vars);
618  auto dict = load_poly_dict<umap_uvec_mpz>(ar);
619  return MIntPoly::from_container(
620  vars, MIntDict(std::move(dict), static_cast<unsigned>(vars.size())));
621 }
622 template <typename Archive>
623 RCP<const Basic> load_basic(Archive &ar, RCP<const MExprPoly> &)
624 {
625  set_basic vars;
626  ar(vars);
627  auto dict = load_poly_dict<umap_vec_expr>(ar);
628  return MExprPoly::from_container(
629  vars, MExprDict(std::move(dict), static_cast<unsigned>(vars.size())));
630 }
631 #if defined(HAVE_SYMENGINE_FLINT) || defined(HAVE_SYMENGINE_PIRANHA)
632 template <typename Poly, typename Cf, typename Archive>
633 RCP<const Basic> load_dense_poly(Archive &ar)
634 {
635  RCP<const Basic> var;
636  unsigned int size;
637  ar(var, size);
638  std::map<unsigned, Cf> dict;
639  for (unsigned int i = 0; i < size; ++i) {
640  Cf coeff;
641  load_helper(ar, coeff);
642  dict.emplace(i, std::move(coeff));
643  }
644  return Poly::from_dict(var, std::move(dict));
645 }
646 #endif
647 #ifdef HAVE_SYMENGINE_FLINT
648 template <typename Archive>
649 RCP<const Basic> load_basic(Archive &ar, RCP<const UIntPolyFlint> &)
650 {
651  return load_dense_poly<UIntPolyFlint, integer_class>(ar);
652 }
653 template <typename Archive>
654 RCP<const Basic> load_basic(Archive &ar, RCP<const URatPolyFlint> &)
655 {
656  return load_dense_poly<URatPolyFlint, rational_class>(ar);
657 }
658 #endif
659 #ifdef HAVE_SYMENGINE_PIRANHA
660 template <typename Archive>
661 RCP<const Basic> load_basic(Archive &ar, RCP<const UIntPolyPiranha> &)
662 {
663  return load_dense_poly<UIntPolyPiranha, integer_class>(ar);
664 }
665 template <typename Archive>
666 RCP<const Basic> load_basic(Archive &ar, RCP<const URatPolyPiranha> &)
667 {
668  return load_dense_poly<URatPolyPiranha, rational_class>(ar);
669 }
670 #endif
671 template <class Archive>
672 RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
673 {
674  integer_class c;
675  load_helper(ar, c);
676  return integer(std::move(c));
677 }
678 template <class Archive>
679 RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
680 {
681  std::string name;
682  ar(name);
683  return constant(name);
684 }
685 template <class Archive>
686 RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
687 {
688  RCP<const Integer> num, den;
689  ar(num, den);
690  return Rational::from_two_ints(*num, *den);
691 }
692 template <class Archive>
693 RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
694 {
695  RCP<const Number> num, den;
696  ar(num, den);
697  return Complex::from_two_nums(*num, *den);
698 }
699 template <class Archive, class T>
700 RCP<const Basic>
701 load_basic(Archive &ar, RCP<const T> &,
702  typename std::enable_if<std::is_base_of<ComplexBase, T>::value,
703  int>::type * = nullptr)
704 {
705  RCP<const Number> num, den;
706  ar(num, den);
707  return addnum(num, mulnum(I, den));
708 }
709 template <class Archive>
710 RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
711 {
712  RCP<const Number> start, end;
713  bool left_open, right_open;
714  ar(left_open, start, right_open, end);
715  return make_rcp<const Interval>(start, end, left_open, right_open);
716 }
717 template <class Archive>
718 RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
719 {
720  bool val;
721  ar(val);
722  return boolean(val);
723 }
724 template <class Archive>
725 RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
726 {
727  set_boolean container;
728  ar(container);
729  return make_rcp<const And>(std::move(container));
730 }
731 template <class Archive>
732 RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
733 {
734  set_boolean container;
735  ar(container);
736  return make_rcp<const Or>(std::move(container));
737 }
738 template <class Archive>
739 RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
740 {
741  vec_boolean container;
742  ar(container);
743  return make_rcp<const Xor>(std::move(container));
744 }
745 template <class Archive>
746 RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
747 {
748  RCP<const Boolean> arg;
749  ar(arg);
750  return make_rcp<const Not>(arg);
751 }
752 template <class Archive>
753 RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
754 {
755  PiecewiseVec vec;
756  ar(vec);
757  return make_rcp<const Piecewise>(std::move(vec));
758 }
759 template <class Archive>
760 RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
761 {
762  RCP<const Basic> expr;
763  RCP<const Set> contains_set;
764  ar(expr, contains_set);
765  return make_rcp<const Contains>(expr, contains_set);
766 }
767 template <class Archive>
768 RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
769 {
770  return reals();
771 }
772 template <class Archive>
773 RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
774 {
775  return rationals();
776 }
777 template <class Archive>
778 RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
779 {
780  return emptyset();
781 }
782 template <class Archive>
783 RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
784 {
785  return integers();
786 }
787 template <class Archive>
788 RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
789 {
790  return universalset();
791 }
792 template <class Archive>
793 RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
794 {
795  set_set union_set;
796  ar(union_set);
797  return make_rcp<const Union>(std::move(union_set));
798 }
799 template <class Archive>
800 RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
801 {
802  RCP<const Set> universe, container;
803  ar(universe, container);
804  return make_rcp<const Complement>(universe, container);
805 }
806 template <class Archive>
807 RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
808 {
809  RCP<const Basic> sym, expr;
810  RCP<const Set> base;
811  ar(sym, expr, base);
812  return make_rcp<const ImageSet>(sym, expr, base);
813 }
814 template <class Archive>
815 RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
816 {
817  set_basic set;
818  ar(set);
819  return make_rcp<const FiniteSet>(set);
820 }
821 template <class Archive>
822 RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
823 {
824  RCP<const Basic> sym;
825  RCP<const Boolean> condition;
826  ar(sym, condition);
827  return make_rcp<const ConditionSet>(sym, condition);
828 }
829 #ifdef HAVE_SYMENGINE_MPFR
830 template <class Archive>
831 RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
832 {
833  std::string num;
834  mpfr_prec_t prec;
835  ar(num, prec);
836  return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
837 }
838 #endif
839 template <class Archive>
840 RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
841 {
842  RCP<const Basic> arg;
843  multiset_basic set;
844  ar(arg, set);
845  return make_rcp<const Derivative>(arg, std::move(set));
846 }
847 template <class Archive>
848 RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
849 {
850  RCP<const Basic> arg;
851  map_basic_basic dict;
852  ar(arg, dict);
853  return make_rcp<const Subs>(arg, std::move(dict));
854 }
855 
856 template <class Archive, class T>
857 RCP<const Basic>
858 load_basic(Archive &ar, RCP<const T> &,
859  typename std::enable_if<std::is_base_of<OneArgFunction, T>::value,
860  int>::type * = nullptr)
861 {
862  RCP<const Basic> arg;
863  ar(arg);
864  return make_rcp<const T>(arg);
865 }
866 template <class Archive, class T>
867 RCP<const Basic>
868 load_basic(Archive &ar, RCP<const T> &,
869  typename std::enable_if<std::is_base_of<TwoArgFunction, T>::value,
870  int>::type * = nullptr)
871 {
872  RCP<const Basic> arg1, arg2;
873  ar(arg1, arg2);
874  return make_rcp<const T>(arg1, arg2);
875 }
876 template <class Archive>
877 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
878 {
879  std::string name;
880  vec_basic vec;
881  ar(name, vec);
882  return make_rcp<const FunctionSymbol>(name, std::move(vec));
883 }
884 template <class Archive>
885 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
886 {
887  throw SerializationError(StreamFmt()
888  << __FILE__ << ":" << __LINE__
889 #ifndef _MSC_VER
890  << ": " << __PRETTY_FUNCTION__
891 #endif
892  << "Loading of this type is not implemented.");
893 }
894 template <class Archive, class T>
895 RCP<const Basic>
896 load_basic(Archive &ar, RCP<const T> &,
897  typename std::enable_if<std::is_base_of<MultiArgFunction, T>::value,
898  int>::type * = nullptr)
899 {
900  vec_basic args;
901  ar(args);
902  return make_rcp<const T>(std::move(args));
903 }
904 template <class Archive, class T>
905 RCP<const Basic>
906 load_basic(Archive &ar, RCP<const T> &,
907  typename std::enable_if<std::is_base_of<Relational, T>::value,
908  int>::type * = nullptr)
909 {
910  RCP<const Basic> arg1, arg2;
911  ar(arg1, arg2);
912  return make_rcp<const T>(arg1, arg2);
913 }
914 template <class Archive, class T>
915 RCP<const Basic> load_basic(
916  Archive &ar, RCP<const T> &,
917  typename std::enable_if<not(std::is_base_of<Relational, T>::value
918  or std::is_base_of<ComplexBase, T>::value
919  or std::is_base_of<OneArgFunction, T>::value
920  or std::is_base_of<MultiArgFunction, T>::value
921  or std::is_base_of<TwoArgFunction, T>::value),
922  int>::type * = nullptr)
923 {
924  throw SerializationError(StreamFmt()
925  << __FILE__ << ":" << __LINE__
926 #ifndef _MSC_VER
927  << ": " << __PRETTY_FUNCTION__
928 #endif
929  << "Loading of this type is not implemented.");
930 }
931 
932 template <class Archive>
933 inline void save_typeid(Archive &ar, TypeID &t)
934 {
935  uint8_t i = t;
936  static_assert(TypeID::TypeID_Count < (1 << 8),
937  "TypeID cannot be saved to a 8 bit int.");
938  ar(i);
939 }
940 
941 template <class Archive>
942 inline void load_typeid(Archive &ar, TypeID &t)
943 {
944  uint8_t i;
945  ar(i);
946  if (i >= TypeID::TypeID_Count) {
947  throw SerializationError("TypeID out of range");
948  }
949  t = static_cast<TypeID>(i);
950 }
951 
953 template <class Archive, class T>
954 inline void CEREAL_LOAD_FUNCTION_NAME(Archive &ar, RCP<const T> &ptr)
955 {
957  = dynamic_cast<RCPBasicAwareInputArchive<Archive> *>(&ar);
958  if (not ar_ptr) {
959  throw SerializationError("Need a RCPBasicAwareInputArchive");
960  }
961  ptr = ar_ptr->template load_rcp_basic<T>();
962 }
963 } // namespace SymEngine
964 #endif // SYMENGINE_SERIALIZE_CEREAL_H
The base class for SymEngine.
static RCP< const Number > from_two_nums(const Number &re, const Number &im)
Definition: complex.cpp:109
void rtti()
Overload the rtti function to enable dynamic_cast.
void rtti()
Overload the rtti function to enable dynamic_cast.
static RCP< const Number > from_two_ints(const Integer &n, const Integer &d)
Definition: rational.cpp:44
Main namespace for SymEngine package.
Definition: add.cpp:19
RCP< const Dummy > dummy()
inline version to return Dummy
Definition: symbol.h:93
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:197
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
Definition: symbol.h:87
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
Definition: number.h:93
RCP< const Reals > reals()
Definition: sets.h:560
RCP< const EmptySet > emptyset()
Definition: sets.h:590
RCP< const Integers > integers()
Definition: sets.h:572
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 UniversalSet > universalset()
Definition: sets.h:596
TypeID
Definition: basic.h:43
@ TypeID_Count
Definition: basic.h:52
RCP< const Constant > constant(const std::string &name)
inline version to return Constant
Definition: constants.h:53
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()
Definition: sets.h:566
RCP< const Number > addnum(const RCP< const Number > &self, const RCP< const Number > &other)
Add self and other
Definition: number.h:81