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 // Following is an ugly hack for templated integer classes
206 // Not sure why a direct version doesn't work
207 template <typename Archive>
208 void save_basic(Archive &ar, const URatPoly &b)
209 {
210  ar(b.get_var());
211  const URatDict &urd = b.get_poly();
212  size_t l = urd.size();
213  ar(l);
214  for (auto &p : urd.dict_) {
215  unsigned int first = p.first;
216  const rational_class &second = p.second;
217  ar(first);
218  save_helper(ar, second);
219  }
220 }
221 template <class Archive>
222 inline void save_basic(Archive &ar, const Integer &b)
223 {
224  ar(b.__str__());
225 }
226 template <class Archive>
227 inline void save_basic(Archive &ar, const RealDouble &b)
228 {
229  ar(b.i);
230 }
231 template <class Archive>
232 inline void save_basic(Archive &ar, const Rational &b)
233 {
234  ar(b.get_num(), b.get_den());
235 }
236 template <class Archive>
237 inline void save_basic(Archive &ar, const ComplexBase &b)
238 {
239  ar(b.real_part(), b.imaginary_part());
240 }
241 template <class Archive>
242 inline void save_basic(Archive &ar, const Interval &b)
243 {
244  ar(b.get_left_open(), b.get_start(), b.get_right_open(), b.get_end());
245 }
246 template <class Archive>
247 inline void save_basic(Archive &ar, const BooleanAtom &b)
248 {
249  ar(b.get_val());
250 }
251 template <class Archive>
252 inline void save_basic(Archive &ar, const Infty &b)
253 {
254  ar(b.get_direction());
255 }
256 
257 template <class Archive>
258 inline void save_basic(Archive &ar, const NaN &b)
259 {
260 }
261 
262 template <class Archive>
263 inline void save_basic(Archive &ar, const Constant &b)
264 {
265  ar(b.get_name());
266 }
267 template <class Archive>
268 inline void save_basic(Archive &ar, const OneArgFunction &b)
269 {
270  ar(b.get_arg());
271 }
272 template <class Archive>
273 inline void save_basic(Archive &ar, const TwoArgFunction &b)
274 {
275  ar(b.get_arg1(), b.get_arg2());
276 }
277 
278 template <class Archive>
279 inline void save_basic(Archive &ar, const Relational &b)
280 {
281  ar(b.get_arg1(), b.get_arg2());
282 }
283 template <class Archive>
284 inline void save_basic(Archive &ar, const And &b)
285 {
286  ar(b.get_container());
287 }
288 template <class Archive>
289 inline void save_basic(Archive &ar, const Or &b)
290 {
291  ar(b.get_container());
292 }
293 template <class Archive>
294 inline void save_basic(Archive &ar, const Xor &b)
295 {
296  ar(b.get_container());
297 }
298 template <class Archive>
299 inline void save_basic(Archive &ar, const Not &b)
300 {
301  ar(b.get_arg());
302 }
303 template <class Archive>
304 inline void save_basic(Archive &ar, const Contains &b)
305 {
306  ar(b.get_expr(), b.get_set());
307 }
308 template <class Archive>
309 inline void save_basic(Archive &ar, const Piecewise &b)
310 {
311  ar(b.get_vec());
312 }
313 template <class Archive>
314 inline void save_basic(Archive &ar, const Reals &b)
315 {
316 }
317 template <class Archive>
318 inline void save_basic(Archive &ar, const Rationals &b)
319 {
320 }
321 template <class Archive>
322 inline void save_basic(Archive &ar, const EmptySet &b)
323 {
324 }
325 template <class Archive>
326 inline void save_basic(Archive &ar, const Integers &b)
327 {
328 }
329 template <class Archive>
330 inline void save_basic(Archive &ar, const UniversalSet &b)
331 {
332 }
333 template <class Archive>
334 inline void save_basic(Archive &ar, const Union &b)
335 {
336  ar(b.get_container());
337 }
338 template <class Archive>
339 inline void save_basic(Archive &ar, const Complement &b)
340 {
341  ar(b.get_universe(), b.get_container());
342 }
343 template <class Archive>
344 inline void save_basic(Archive &ar, const ImageSet &b)
345 {
346  ar(b.get_symbol(), b.get_expr(), b.get_baseset());
347 }
348 template <class Archive>
349 inline void save_basic(Archive &ar, const FiniteSet &b)
350 {
351  ar(b.get_container());
352 }
353 template <class Archive>
354 inline void save_basic(Archive &ar, const ConditionSet &b)
355 {
356  ar(b.get_symbol(), b.get_condition());
357 }
358 #ifdef HAVE_SYMENGINE_MPFR
359 template <class Archive>
360 inline void save_basic(Archive &ar, const RealMPFR &b)
361 {
362  ar(b.__str__(), b.get_prec());
363 }
364 #endif
365 template <class Archive>
366 inline void save_basic(Archive &ar, const GaloisField &b)
367 {
368  throw NotImplementedError("GaloisField saving is not implemented yet.");
369 }
370 template <class Archive>
371 inline void save_basic(Archive &ar, const SeriesCoeffInterface &)
372 {
373  throw NotImplementedError("Series saving is not implemented yet.");
374 }
375 template <class Archive>
376 inline void save_basic(Archive &ar, const MultiArgFunction &b)
377 {
378  ar(b.get_args());
379 }
380 template <class Archive>
381 inline void save_basic(Archive &ar, const FunctionSymbol &b)
382 {
383  ar(b.get_name(), b.get_args());
384 }
385 template <class Archive>
386 inline void save_basic(Archive &ar, const Derivative &b)
387 {
388  ar(b.get_arg(), b.get_symbols());
389 }
390 template <class Archive>
391 inline void save_basic(Archive &ar, const Subs &b)
392 {
393  ar(b.get_arg(), b.get_dict());
394 }
395 template <class Archive>
396 inline void save_basic(Archive &ar, const NumberWrapper &b)
397 {
398  throw NotImplementedError("NumberWrapper saving is not implemented yet.");
399 }
400 template <class Archive>
401 inline void save_basic(Archive &ar, const FunctionWrapper &b)
402 {
403  throw NotImplementedError("FunctionWrapper saving is not implemented yet.");
404 }
405 
407 template <class Archive, class T>
408 inline void CEREAL_SAVE_FUNCTION_NAME(Archive &ar, RCP<const T> const &ptr)
409 {
411  = dynamic_cast<RCPBasicAwareOutputArchive<Archive> *>(&ar);
412  if (not ar_ptr) {
413  throw SerializationError("Need a RCPBasicAwareOutputArchive");
414  }
415  ar_ptr->save_rcp_basic(rcp_static_cast<const Basic>(ptr));
416 }
417 template <class Archive>
418 RCP<const Basic> load_basic(Archive &ar, RCP<const RealDouble> &)
419 {
420  double val;
421  ar(val);
422  return real_double(val);
423 }
424 template <class Archive>
425 RCP<const Basic> load_basic(Archive &ar, RCP<const Infty> &)
426 {
427  RCP<const Number> direction;
428  ar(direction);
429  return Infty::from_direction(direction);
430 }
431 template <class Archive>
432 RCP<const Basic> load_basic(Archive &ar, RCP<const NaN> &)
433 {
434  return rcp_static_cast<const Basic>(Nan);
435 }
436 template <class Archive>
437 RCP<const Basic> load_basic(Archive &ar, RCP<const Symbol> &)
438 {
439  std::string name;
440  ar(name);
441  return symbol(name);
442 }
443 template <class Archive>
444 RCP<const Basic> load_basic(Archive &ar, RCP<const Dummy> &)
445 {
446  std::string name;
447  size_t index;
448  ar(name, index);
449  return dummy(name, index);
450 }
451 template <class Archive>
452 RCP<const Basic> load_basic(Archive &ar, RCP<const Mul> &)
453 {
454  RCP<const Number> coeff;
455  map_basic_basic dict;
456  ar(coeff);
457  ar(dict);
458  return make_rcp<const Mul>(coeff, std::move(dict));
459 }
460 template <class Archive>
461 RCP<const Basic> load_basic(Archive &ar, RCP<const Add> &)
462 {
463  RCP<const Number> coeff;
464  umap_basic_num dict;
465  ar(coeff);
466  ar(dict);
467  return make_rcp<const Add>(coeff, std::move(dict));
468 }
469 template <class Archive>
470 RCP<const Basic> load_basic(Archive &ar, RCP<const Pow> &)
471 {
472  RCP<const Basic> base, exp;
473  ar(base);
474  ar(exp);
475  return make_rcp<const Pow>(base, exp);
476 }
477 template <typename Archive>
478 void load_helper(Archive &ar, integer_class &intgr)
479 {
480  std::string int_str;
481  ar(int_str);
482  if (int_str.size() == 0) {
483  throw SerializationError("invalid integer");
484  }
485  if (not(int_str[0] == '-' or std::isdigit(int_str[0]))) {
486  throw SerializationError("invalid integer");
487  }
488  for (auto it = ++int_str.begin(); it < int_str.end(); it++) {
489  if (not std::isdigit(*it)) {
490  throw SerializationError("invalid integer");
491  }
492  }
493  intgr = integer_class(std::move(int_str));
494 }
495 template <typename Archive>
496 void load_helper(Archive &ar, const rational_class &rat)
497 {
498  integer_class num, den;
499  load_helper(ar, num);
500  load_helper(ar, den);
501 }
502 // Following is an ugly hack for templated integer classes
503 // Not sure why the other clean version doesn't work
504 template <typename Archive>
505 RCP<const Basic> load_basic(Archive &ar, const URatPoly &b)
506 {
507  RCP<const Basic> var;
508  size_t l;
509  ar(var);
510  ar(l);
511  std::map<unsigned, rational_class> d;
512  auto hint = d.begin();
513  for (size_t i = 0; i < l; i++) {
514  unsigned int first;
515  rational_class second;
516  ar(first);
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)));
520 #else
521  d.emplace_hint(hint, std::move(first), std::move(second));
522 #endif
523  }
524  return make_rcp<const URatPoly>(var, URatDict(std::move(d)));
525 }
526 template <class Archive>
527 RCP<const Basic> load_basic(Archive &ar, RCP<const Integer> &)
528 {
529  integer_class c;
530  load_helper(ar, c);
531  return integer(std::move(c));
532 }
533 template <class Archive>
534 RCP<const Basic> load_basic(Archive &ar, RCP<const Constant> &)
535 {
536  std::string name;
537  ar(name);
538  return constant(name);
539 }
540 template <class Archive>
541 RCP<const Basic> load_basic(Archive &ar, RCP<const Rational> &)
542 {
543  RCP<const Integer> num, den;
544  ar(num, den);
545  return Rational::from_two_ints(*num, *den);
546 }
547 template <class Archive>
548 RCP<const Basic> load_basic(Archive &ar, RCP<const Complex> &)
549 {
550  RCP<const Number> num, den;
551  ar(num, den);
552  return Complex::from_two_nums(*num, *den);
553 }
554 template <class Archive, class T>
555 RCP<const Basic>
556 load_basic(Archive &ar, RCP<const T> &,
557  typename std::enable_if<std::is_base_of<ComplexBase, T>::value,
558  int>::type * = nullptr)
559 {
560  RCP<const Number> num, den;
561  ar(num, den);
562  return addnum(num, mulnum(I, den));
563 }
564 template <class Archive>
565 RCP<const Basic> load_basic(Archive &ar, RCP<const Interval> &)
566 {
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);
571 }
572 template <class Archive>
573 RCP<const Basic> load_basic(Archive &ar, RCP<const BooleanAtom> &)
574 {
575  bool val;
576  ar(val);
577  return boolean(val);
578 }
579 template <class Archive>
580 RCP<const Basic> load_basic(Archive &ar, RCP<const And> &)
581 {
582  set_boolean container;
583  ar(container);
584  return make_rcp<const And>(std::move(container));
585 }
586 template <class Archive>
587 RCP<const Basic> load_basic(Archive &ar, RCP<const Or> &)
588 {
589  set_boolean container;
590  ar(container);
591  return make_rcp<const Or>(std::move(container));
592 }
593 template <class Archive>
594 RCP<const Basic> load_basic(Archive &ar, RCP<const Xor> &)
595 {
596  vec_boolean container;
597  ar(container);
598  return make_rcp<const Xor>(std::move(container));
599 }
600 template <class Archive>
601 RCP<const Basic> load_basic(Archive &ar, RCP<const Not> &)
602 {
603  RCP<const Boolean> arg;
604  ar(arg);
605  return make_rcp<const Not>(arg);
606 }
607 template <class Archive>
608 RCP<const Basic> load_basic(Archive &ar, RCP<const Piecewise> &)
609 {
610  PiecewiseVec vec;
611  ar(vec);
612  return make_rcp<const Piecewise>(std::move(vec));
613 }
614 template <class Archive>
615 RCP<const Basic> load_basic(Archive &ar, RCP<const Contains> &)
616 {
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);
621 }
622 template <class Archive>
623 RCP<const Basic> load_basic(Archive &ar, RCP<const Reals> &)
624 {
625  return reals();
626 }
627 template <class Archive>
628 RCP<const Basic> load_basic(Archive &ar, RCP<const Rationals> &)
629 {
630  return rationals();
631 }
632 template <class Archive>
633 RCP<const Basic> load_basic(Archive &ar, RCP<const EmptySet> &)
634 {
635  return emptyset();
636 }
637 template <class Archive>
638 RCP<const Basic> load_basic(Archive &ar, RCP<const Integers> &)
639 {
640  return integers();
641 }
642 template <class Archive>
643 RCP<const Basic> load_basic(Archive &ar, RCP<const UniversalSet> &)
644 {
645  return universalset();
646 }
647 template <class Archive>
648 RCP<const Basic> load_basic(Archive &ar, RCP<const Union> &)
649 {
650  set_set union_set;
651  ar(union_set);
652  return make_rcp<const Union>(std::move(union_set));
653 }
654 template <class Archive>
655 RCP<const Basic> load_basic(Archive &ar, RCP<const Complement> &)
656 {
657  RCP<const Set> universe, container;
658  ar(universe, container);
659  return make_rcp<const Complement>(universe, container);
660 }
661 template <class Archive>
662 RCP<const Basic> load_basic(Archive &ar, RCP<const ImageSet> &)
663 {
664  RCP<const Basic> sym, expr;
665  RCP<const Set> base;
666  ar(sym, expr, base);
667  return make_rcp<const ImageSet>(sym, expr, base);
668 }
669 template <class Archive>
670 RCP<const Basic> load_basic(Archive &ar, RCP<const FiniteSet> &)
671 {
672  set_basic set;
673  ar(set);
674  return make_rcp<const FiniteSet>(set);
675 }
676 template <class Archive>
677 RCP<const Basic> load_basic(Archive &ar, RCP<const ConditionSet> &)
678 {
679  RCP<const Basic> sym;
680  RCP<const Boolean> condition;
681  ar(sym, condition);
682  return make_rcp<const ConditionSet>(sym, condition);
683 }
684 #ifdef HAVE_SYMENGINE_MPFR
685 template <class Archive>
686 RCP<const Basic> load_basic(Archive &ar, RCP<const RealMPFR> &)
687 {
688  std::string num;
689  mpfr_prec_t prec;
690  ar(num, prec);
691  return make_rcp<const RealMPFR>(mpfr_class(num, prec, 10));
692 }
693 #endif
694 template <class Archive>
695 RCP<const Basic> load_basic(Archive &ar, RCP<const Derivative> &)
696 {
697  RCP<const Basic> arg;
698  multiset_basic set;
699  ar(arg, set);
700  return make_rcp<const Derivative>(arg, std::move(set));
701 }
702 template <class Archive>
703 RCP<const Basic> load_basic(Archive &ar, RCP<const Subs> &)
704 {
705  RCP<const Basic> arg;
706  map_basic_basic dict;
707  ar(arg, dict);
708  return make_rcp<const Subs>(arg, std::move(dict));
709 }
710 
711 template <class Archive, class T>
712 RCP<const Basic>
713 load_basic(Archive &ar, RCP<const T> &,
714  typename std::enable_if<std::is_base_of<OneArgFunction, T>::value,
715  int>::type * = nullptr)
716 {
717  RCP<const Basic> arg;
718  ar(arg);
719  return make_rcp<const T>(arg);
720 }
721 template <class Archive, class T>
722 RCP<const Basic>
723 load_basic(Archive &ar, RCP<const T> &,
724  typename std::enable_if<std::is_base_of<TwoArgFunction, T>::value,
725  int>::type * = nullptr)
726 {
727  RCP<const Basic> arg1, arg2;
728  ar(arg1, arg2);
729  return make_rcp<const T>(arg1, arg2);
730 }
731 template <class Archive>
732 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionSymbol> &)
733 {
734  std::string name;
735  vec_basic vec;
736  ar(name, vec);
737  return make_rcp<const FunctionSymbol>(name, std::move(vec));
738 }
739 template <class Archive>
740 RCP<const Basic> load_basic(Archive &ar, RCP<const FunctionWrapper> &)
741 {
742  throw SerializationError(StreamFmt()
743  << __FILE__ << ":" << __LINE__
744 #ifndef _MSC_VER
745  << ": " << __PRETTY_FUNCTION__
746 #endif
747  << "Loading of this type is not implemented.");
748 }
749 template <class Archive, class T>
750 RCP<const Basic>
751 load_basic(Archive &ar, RCP<const T> &,
752  typename std::enable_if<std::is_base_of<MultiArgFunction, T>::value,
753  int>::type * = nullptr)
754 {
755  vec_basic args;
756  ar(args);
757  return make_rcp<const T>(std::move(args));
758 }
759 template <class Archive, class T>
760 RCP<const Basic>
761 load_basic(Archive &ar, RCP<const T> &,
762  typename std::enable_if<std::is_base_of<Relational, T>::value,
763  int>::type * = nullptr)
764 {
765  RCP<const Basic> arg1, arg2;
766  ar(arg1, arg2);
767  return make_rcp<const T>(arg1, arg2);
768 }
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)
778 {
779  throw SerializationError(StreamFmt()
780  << __FILE__ << ":" << __LINE__
781 #ifndef _MSC_VER
782  << ": " << __PRETTY_FUNCTION__
783 #endif
784  << "Loading of this type is not implemented.");
785 }
786 
787 template <class Archive>
788 inline void save_typeid(Archive &ar, TypeID &t)
789 {
790  uint8_t i = t;
791  static_assert(TypeID::TypeID_Count < (1 << 8),
792  "TypeID cannot be saved to a 8 bit int.");
793  ar(i);
794 }
795 
796 template <class Archive>
797 inline void load_typeid(Archive &ar, TypeID &t)
798 {
799  uint8_t i;
800  ar(i);
801  if (i >= TypeID::TypeID_Count) {
802  throw SerializationError("TypeID out of range");
803  }
804  t = static_cast<TypeID>(i);
805 }
806 
808 template <class Archive, class T>
809 inline void CEREAL_LOAD_FUNCTION_NAME(Archive &ar, RCP<const T> &ptr)
810 {
812  = dynamic_cast<RCPBasicAwareInputArchive<Archive> *>(&ar);
813  if (not ar_ptr) {
814  throw SerializationError("Need a RCPBasicAwareInputArchive");
815  }
816  ptr = ar_ptr->template load_rcp_basic<T>();
817 }
818 } // namespace SymEngine
819 #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