cwrapper.cpp
1 #include <cstdlib>
2 #include <cstring>
3 
4 #include <symengine/symbol.h>
5 #include <symengine/cwrapper.h>
6 #include <symengine/printers.h>
7 #include <symengine/matrix.h>
8 #include <symengine/eval.h>
9 #include <symengine/parser.h>
10 #include <symengine/lambda_double.h>
11 #include <symengine/solve.h>
12 #ifdef HAVE_SYMENGINE_LLVM
13 #include <symengine/llvm_double.h>
14 using SymEngine::LLVMDoubleVisitor;
15 using SymEngine::LLVMFloatVisitor;
16 #ifdef HAVE_SYMENGINE_LLVM_LONG_DOUBLE
17 using SymEngine::LLVMLongDoubleVisitor;
18 #endif
19 #endif
20 
21 #define xstr(s) str(s)
22 #define str(s) #s
23 
24 using SymEngine::Basic;
25 using SymEngine::Complex;
30 using SymEngine::down_cast;
31 using SymEngine::function_symbol;
33 using SymEngine::Integer;
34 using SymEngine::integer_class;
36 using SymEngine::Number;
38 using SymEngine::rational_class;
39 using SymEngine::RCP;
41 using SymEngine::Symbol;
42 using SymEngine::zero;
43 #ifdef HAVE_SYMENGINE_MPFR
44 using SymEngine::mpfr_class;
46 #endif // HAVE_SYMENGINE_MPFR
47 #ifdef HAVE_SYMENGINE_MPC
49 #endif // HAVE_SYMENGINE_MPC
51 using SymEngine::is_a;
52 using SymEngine::rcp_static_cast;
54 using SymEngine::Set;
58 using SymEngine::vec_sym;
59 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
60 using SymEngine::get_mpq_t;
61 using SymEngine::get_mpz_t;
62 #endif
63 using SymEngine::ccode;
64 using SymEngine::diag;
65 using SymEngine::eye;
66 using SymEngine::jscode;
67 using SymEngine::julia_str;
68 using SymEngine::latex;
69 using SymEngine::mathml;
70 using SymEngine::mp_get_si;
71 using SymEngine::mp_get_ui;
72 using SymEngine::numeric_cast;
73 using SymEngine::ones;
74 using SymEngine::parse;
75 using SymEngine::SymEngineException;
76 using SymEngine::zeros;
77 
78 namespace SymEngine
79 {
80 
81 template <typename T>
82 inline bool is_aligned(T *p, size_t n = alignof(T))
83 {
84  return 0 == reinterpret_cast<uintptr_t>(p) % n;
85 }
86 
87 static std::string _str(const Basic &a)
88 {
89  return a.__str__();
90 }
91 } // namespace SymEngine
92 
93 extern "C" {
94 
95 #define CWRAPPER_BEGIN try {
96 
97 #define CWRAPPER_END \
98  return SYMENGINE_NO_EXCEPTION; \
99  } \
100  catch (SymEngineException & e) \
101  { \
102  return e.error_code(); \
103  } \
104  catch (...) \
105  { \
106  return SYMENGINE_RUNTIME_ERROR; \
107  }
108 
109 struct CRCPBasic {
110  SymEngine::RCP<const SymEngine::Basic> m;
111 };
112 
113 static_assert(sizeof(CRCPBasic) == sizeof(CRCPBasic_C),
114  "Size of 'basic' is not correct");
117  "Alignment of 'basic' is not correct");
118 
119 void basic_new_stack(basic s)
120 {
121  new (s) CRCPBasic();
122 }
123 
124 void basic_free_stack(basic s)
125 {
126  s->m.~RCP();
127 }
128 
129 basic_struct *basic_new_heap()
130 {
131  return new CRCPBasic();
132 }
133 
134 void basic_free_heap(basic_struct *s)
135 {
136  delete s;
137 }
138 
139 const char *symengine_version()
140 {
141  return SYMENGINE_VERSION;
142 }
143 
144 void basic_const_set(basic s, const char *c)
145 {
146  s->m = SymEngine::constant(std::string(c));
147 }
148 
149 void basic_const_zero(basic s)
150 {
151  s->m = SymEngine::zero;
152 }
153 
154 void basic_const_one(basic s)
155 {
156  s->m = SymEngine::one;
157 }
158 
159 void basic_const_minus_one(basic s)
160 {
161  s->m = SymEngine::minus_one;
162 }
163 
164 void basic_const_I(basic s)
165 {
166  s->m = SymEngine::I;
167 }
168 
169 void basic_const_pi(basic s)
170 {
171  s->m = SymEngine::pi;
172 }
173 
174 void basic_const_E(basic s)
175 {
176  s->m = SymEngine::E;
177 }
178 
179 void basic_const_EulerGamma(basic s)
180 {
181  s->m = SymEngine::EulerGamma;
182 }
183 
184 void basic_const_Catalan(basic s)
185 {
186  s->m = SymEngine::Catalan;
187 }
188 
189 void basic_const_GoldenRatio(basic s)
190 {
191  s->m = SymEngine::GoldenRatio;
192 }
193 
194 void basic_const_infinity(basic s)
195 {
196  s->m = SymEngine::Inf;
197 }
198 
199 void basic_const_neginfinity(basic s)
200 {
201  s->m = SymEngine::NegInf;
202 }
203 
204 void basic_const_complex_infinity(basic s)
205 {
206  s->m = SymEngine::ComplexInf;
207 }
208 
209 void basic_const_nan(basic s)
210 {
211  s->m = SymEngine::Nan;
212 }
213 
214 TypeID basic_get_class_id(const char *c)
215 {
216  static std::map<std::string, TypeID> names = {
217 #define SYMENGINE_INCLUDE_ALL
218 #define SYMENGINE_ENUM(type, Class) {xstr(Class), type},
219 #include "symengine/type_codes.inc"
220 #undef SYMENGINE_ENUM
221 #undef SYMENGINE_INCLUDE_ALL
222  {"", SYMENGINE_TypeID_Count}};
223 
224  return names[std::string(c)];
225 }
226 
227 char *basic_get_class_from_id(TypeID id)
228 {
229  static std::map<TypeID, std::string> names = {
230 #define SYMENGINE_INCLUDE_ALL
231 #define SYMENGINE_ENUM(type, Class) {type, xstr(Class)},
232 #include "symengine/type_codes.inc"
233 #undef SYMENGINE_ENUM
234 #undef SYMENGINE_INCLUDE_ALL
235  {SYMENGINE_TypeID_Count, ""}};
236 
237  std::string name = names[id];
238  auto cc = new char[name.length() + 1];
239  std::strcpy(cc, name.c_str());
240  return cc;
241 }
242 
243 TypeID basic_get_type(const basic s)
244 {
245  return static_cast<TypeID>(s->m->get_type_code());
246 }
247 
248 CWRAPPER_OUTPUT_TYPE symbol_set(basic s, const char *c)
249 {
250  CWRAPPER_BEGIN
251  s->m = SymEngine::symbol(std::string(c));
252  CWRAPPER_END
253 }
254 
255 int number_is_zero(const basic s)
256 {
257  SYMENGINE_ASSERT(is_a_Number(*(s->m)));
258  return (int)((down_cast<const Number &>(*(s->m))).is_zero());
259 }
260 
261 int number_is_negative(const basic s)
262 {
263  SYMENGINE_ASSERT(is_a_Number(*(s->m)));
264  return (int)((down_cast<const Number &>(*(s->m))).is_negative());
265 }
266 
267 int number_is_positive(const basic s)
268 {
269  SYMENGINE_ASSERT(is_a_Number(*(s->m)));
270  return (int)((down_cast<const Number &>(*(s->m))).is_positive());
271 }
272 
273 int number_is_complex(const basic s)
274 {
275  SYMENGINE_ASSERT(is_a_Number(*(s->m)));
276  return (int)((down_cast<const Number &>(*(s->m))).is_complex());
277 }
278 
279 CWRAPPER_OUTPUT_TYPE integer_set_si(basic s, long i)
280 {
281  CWRAPPER_BEGIN
282  s->m = SymEngine::integer(integer_class(i));
283  CWRAPPER_END
284 }
285 
286 CWRAPPER_OUTPUT_TYPE integer_set_ui(basic s, unsigned long i)
287 {
288  CWRAPPER_BEGIN
289  s->m = SymEngine::integer(integer_class(i));
290  CWRAPPER_END
291 }
292 
293 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
294 CWRAPPER_OUTPUT_TYPE integer_set_mpz(basic s, const mpz_t i)
295 {
296  CWRAPPER_BEGIN
297  s->m = SymEngine::integer(integer_class(i));
298  CWRAPPER_END
299 }
300 #endif
301 
302 CWRAPPER_OUTPUT_TYPE integer_set_str(basic s, const char *c)
303 {
304  CWRAPPER_BEGIN
305  s->m = SymEngine::integer(integer_class(c));
306  CWRAPPER_END
307 }
308 
309 CWRAPPER_OUTPUT_TYPE real_double_set_d(basic s, double d)
310 {
311  CWRAPPER_BEGIN
312  s->m = SymEngine::real_double(d);
313  CWRAPPER_END
314 }
315 
316 double real_double_get_d(const basic s)
317 {
318  SYMENGINE_ASSERT(is_a<RealDouble>(*(s->m)));
319  return (down_cast<const RealDouble &>(*(s->m))).as_double();
320 }
321 
322 #ifdef HAVE_SYMENGINE_MPFR
323 
324 CWRAPPER_OUTPUT_TYPE real_mpfr_set_d(basic s, double d, int prec)
325 {
326  CWRAPPER_BEGIN
327  mpfr_class mc = mpfr_class(prec);
328  mpfr_set_d(mc.get_mpfr_t(), d, MPFR_RNDN);
329  s->m = SymEngine::real_mpfr(std::move(mc));
330  CWRAPPER_END
331 }
332 
333 CWRAPPER_OUTPUT_TYPE real_mpfr_set_str(basic s, const char *c, int prec)
334 {
335  CWRAPPER_BEGIN
336  s->m = SymEngine::real_mpfr(mpfr_class(c, prec, 10));
337  CWRAPPER_END
338 }
339 
340 double real_mpfr_get_d(const basic s)
341 {
342  SYMENGINE_ASSERT(is_a<RealMPFR>(*(s->m)));
343  return mpfr_get_d(
344  ((down_cast<const RealMPFR &>(*(s->m))).as_mpfr()).get_mpfr_t(),
345  MPFR_RNDN);
346 }
347 
348 CWRAPPER_OUTPUT_TYPE real_mpfr_set(basic s, mpfr_srcptr m)
349 {
350  CWRAPPER_BEGIN
351  s->m = SymEngine::real_mpfr(mpfr_class(m));
352  CWRAPPER_END
353 }
354 
355 CWRAPPER_OUTPUT_TYPE real_mpfr_get(mpfr_ptr m, const basic s)
356 {
357  CWRAPPER_BEGIN
358  SYMENGINE_ASSERT(is_a<RealMPFR>(*(s->m)));
359  mpfr_set(m, ((down_cast<const RealMPFR &>(*(s->m))).as_mpfr()).get_mpfr_t(),
360  MPFR_RNDN);
361  CWRAPPER_END
362 }
363 
364 mpfr_prec_t real_mpfr_get_prec(const basic s)
365 {
366  SYMENGINE_ASSERT(is_a<RealMPFR>(*(s->m)));
367  return ((down_cast<const RealMPFR &>(*(s->m))).as_mpfr()).get_prec();
368 }
369 
370 #endif // HAVE_SYMENGINE_MPFR
371 
372 CWRAPPER_OUTPUT_TYPE complex_base_real_part(basic s, const basic com)
373 {
374  CWRAPPER_BEGIN
375  SYMENGINE_ASSERT(SymEngine::is_a_Complex(*(com->m)));
376  s->m = (down_cast<const ComplexBase &>(*(com->m))).real_part();
377  CWRAPPER_END
378 }
379 
380 CWRAPPER_OUTPUT_TYPE complex_base_imaginary_part(basic s, const basic com)
381 {
382  CWRAPPER_BEGIN
383  SYMENGINE_ASSERT(SymEngine::is_a_Complex(*(com->m)));
384  s->m = (down_cast<const ComplexBase &>(*(com->m))).imaginary_part();
385  CWRAPPER_END
386 }
387 
388 signed long integer_get_si(const basic s)
389 {
390  SYMENGINE_ASSERT(is_a<Integer>(*(s->m)));
391  return mp_get_si((down_cast<const Integer &>(*(s->m))).as_integer_class());
392 }
393 
394 unsigned long integer_get_ui(const basic s)
395 {
396  SYMENGINE_ASSERT(is_a<Integer>(*(s->m)));
397  return mp_get_ui((down_cast<const Integer &>(*(s->m))).as_integer_class());
398 }
399 
400 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
401 CWRAPPER_OUTPUT_TYPE integer_get_mpz(mpz_t a, const basic s)
402 {
403  CWRAPPER_BEGIN
404  SYMENGINE_ASSERT(is_a<Integer>(*(s->m)));
405  mpz_set(
406  a, get_mpz_t((down_cast<const Integer &>(*(s->m))).as_integer_class()));
407  CWRAPPER_END
408 }
409 #endif
410 
411 CWRAPPER_OUTPUT_TYPE rational_set_si(basic s, long a, long b)
412 {
413  CWRAPPER_BEGIN
414  s->m = SymEngine::Rational::from_mpq(rational_class(a, b));
415  CWRAPPER_END
416 }
417 
418 CWRAPPER_OUTPUT_TYPE rational_set_ui(basic s, unsigned long a, unsigned long b)
419 {
420  CWRAPPER_BEGIN
421  s->m = SymEngine::Rational::from_mpq(rational_class(a, b));
422  CWRAPPER_END
423 }
424 
425 CWRAPPER_OUTPUT_TYPE rational_set(basic s, const basic a, const basic b)
426 {
427  if (not is_a_Integer(a) or not is_a_Integer(b)) {
428  return SYMENGINE_RUNTIME_ERROR;
429  }
431  *(rcp_static_cast<const Integer>(a->m)),
432  *(rcp_static_cast<const Integer>(b->m)));
433  return SYMENGINE_NO_EXCEPTION;
434 }
435 
436 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
437 CWRAPPER_OUTPUT_TYPE rational_get_mpq(mpq_t a, const basic s)
438 {
439  CWRAPPER_BEGIN
440  SYMENGINE_ASSERT(is_a<Rational>(*(s->m)));
441  mpq_set(a, get_mpq_t(
442  (down_cast<const Rational &>(*(s->m))).as_rational_class()));
443  CWRAPPER_END
444 }
445 
446 CWRAPPER_OUTPUT_TYPE rational_set_mpq(basic s, const mpq_t i)
447 {
448  CWRAPPER_BEGIN
449  s->m = SymEngine::Rational::from_mpq(rational_class(i));
450  CWRAPPER_END
451 }
452 #endif
453 
454 CWRAPPER_OUTPUT_TYPE complex_set(basic s, const basic re, const basic im)
455 {
456  CWRAPPER_BEGIN
458  *(rcp_static_cast<const Number>(re->m)),
459  *(rcp_static_cast<const Number>(im->m)));
460  CWRAPPER_END
461 }
462 
463 CWRAPPER_OUTPUT_TYPE complex_set_rat(basic s, const basic re, const basic im)
464 {
465  CWRAPPER_BEGIN
467  *(rcp_static_cast<const Rational>(re->m)),
468  *(rcp_static_cast<const Rational>(im->m)));
469  CWRAPPER_END
470 }
471 
472 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
473 CWRAPPER_OUTPUT_TYPE complex_set_mpq(basic s, const mpq_t re, const mpq_t im)
474 {
475  CWRAPPER_BEGIN
476  s->m = SymEngine::Complex::from_mpq(rational_class(re), rational_class(im));
477  CWRAPPER_END
478 }
479 #endif
480 
481 dcomplex complex_double_get(const basic s)
482 {
483  SYMENGINE_ASSERT(is_a<ComplexDouble>(*(s->m)));
484  dcomplex d;
485  d.real = (down_cast<const ComplexDouble &>(*(s->m)).as_complex_double())
486  .real();
487  d.imag = (down_cast<const ComplexDouble &>(*(s->m)).as_complex_double())
488  .imag();
489  return d;
490 }
491 
492 CWRAPPER_OUTPUT_TYPE basic_diff(basic s, const basic expr, basic const symbol)
493 {
494  if (not is_a_Symbol(symbol))
495  return SYMENGINE_RUNTIME_ERROR;
496  s->m = expr->m->diff(rcp_static_cast<const Symbol>(symbol->m));
497  return SYMENGINE_NO_EXCEPTION;
498 }
499 
500 CWRAPPER_OUTPUT_TYPE basic_assign(basic a, const basic b)
501 {
502  CWRAPPER_BEGIN
503  a->m = b->m;
504  CWRAPPER_END
505 }
506 
507 CWRAPPER_OUTPUT_TYPE basic_parse(basic b, const char *str)
508 {
509  CWRAPPER_BEGIN
510  b->m = SymEngine::parse(str);
511  CWRAPPER_END
512 }
513 
514 CWRAPPER_OUTPUT_TYPE basic_parse2(basic b, const char *str, int convert_xor)
515 {
516  CWRAPPER_BEGIN
517  if (convert_xor > 0) {
518  b->m = SymEngine::parse(str);
519  } else {
520  b->m = SymEngine::parse(str, false);
521  }
522  CWRAPPER_END
523 }
524 
525 CWRAPPER_OUTPUT_TYPE basic_add(basic s, const basic a, const basic b)
526 {
527  CWRAPPER_BEGIN
528  s->m = SymEngine::add(a->m, b->m);
529  CWRAPPER_END
530 }
531 
532 CWRAPPER_OUTPUT_TYPE basic_sub(basic s, const basic a, const basic b)
533 {
534  CWRAPPER_BEGIN
535  s->m = SymEngine::sub(a->m, b->m);
536  CWRAPPER_END
537 }
538 
539 CWRAPPER_OUTPUT_TYPE basic_mul(basic s, const basic a, const basic b)
540 {
541  CWRAPPER_BEGIN
542  s->m = SymEngine::mul(a->m, b->m);
543  CWRAPPER_END
544 }
545 
546 CWRAPPER_OUTPUT_TYPE basic_pow(basic s, const basic a, const basic b)
547 {
548  CWRAPPER_BEGIN
549  s->m = SymEngine::pow(a->m, b->m);
550  CWRAPPER_END
551 }
552 
553 CWRAPPER_OUTPUT_TYPE basic_div(basic s, const basic a, const basic b)
554 {
555  CWRAPPER_BEGIN
556  s->m = SymEngine::div(a->m, b->m);
557  CWRAPPER_END
558 }
559 
560 int basic_eq(const basic a, const basic b)
561 {
562  return SymEngine::eq(*(a->m), *(b->m)) ? 1 : 0;
563 }
564 
565 int basic_neq(const basic a, const basic b)
566 {
567  return SymEngine::neq(*(a->m), *(b->m)) ? 1 : 0;
568 }
569 
570 #define IMPLEMENT_ONE_ARG_FUNC(func) \
571  CWRAPPER_OUTPUT_TYPE basic_##func(basic s, const basic a) \
572  { \
573  CWRAPPER_BEGIN \
574  s->m = SymEngine::func(a->m); \
575  CWRAPPER_END \
576  }
577 
578 IMPLEMENT_ONE_ARG_FUNC(expand)
579 IMPLEMENT_ONE_ARG_FUNC(neg)
580 IMPLEMENT_ONE_ARG_FUNC(abs)
581 IMPLEMENT_ONE_ARG_FUNC(erf)
582 IMPLEMENT_ONE_ARG_FUNC(erfc)
583 IMPLEMENT_ONE_ARG_FUNC(sin)
584 IMPLEMENT_ONE_ARG_FUNC(cos)
585 IMPLEMENT_ONE_ARG_FUNC(tan)
586 IMPLEMENT_ONE_ARG_FUNC(csc)
587 IMPLEMENT_ONE_ARG_FUNC(sec)
588 IMPLEMENT_ONE_ARG_FUNC(cot)
589 IMPLEMENT_ONE_ARG_FUNC(asin)
590 IMPLEMENT_ONE_ARG_FUNC(acos)
591 IMPLEMENT_ONE_ARG_FUNC(asec)
592 IMPLEMENT_ONE_ARG_FUNC(acsc)
593 IMPLEMENT_ONE_ARG_FUNC(atan)
594 IMPLEMENT_ONE_ARG_FUNC(acot)
595 IMPLEMENT_ONE_ARG_FUNC(sinh)
596 IMPLEMENT_ONE_ARG_FUNC(cosh)
597 IMPLEMENT_ONE_ARG_FUNC(tanh)
598 IMPLEMENT_ONE_ARG_FUNC(csch)
599 IMPLEMENT_ONE_ARG_FUNC(sech)
600 IMPLEMENT_ONE_ARG_FUNC(coth)
601 IMPLEMENT_ONE_ARG_FUNC(asinh)
602 IMPLEMENT_ONE_ARG_FUNC(acosh)
603 IMPLEMENT_ONE_ARG_FUNC(asech)
604 IMPLEMENT_ONE_ARG_FUNC(acsch)
605 IMPLEMENT_ONE_ARG_FUNC(atanh)
606 IMPLEMENT_ONE_ARG_FUNC(acoth)
607 IMPLEMENT_ONE_ARG_FUNC(lambertw)
608 IMPLEMENT_ONE_ARG_FUNC(zeta)
609 IMPLEMENT_ONE_ARG_FUNC(dirichlet_eta)
610 IMPLEMENT_ONE_ARG_FUNC(gamma)
611 IMPLEMENT_ONE_ARG_FUNC(loggamma)
612 IMPLEMENT_ONE_ARG_FUNC(sqrt)
613 IMPLEMENT_ONE_ARG_FUNC(cbrt)
614 IMPLEMENT_ONE_ARG_FUNC(exp)
615 IMPLEMENT_ONE_ARG_FUNC(log)
616 
617 #define IMPLEMENT_TWO_ARG_FUNC(func) \
618  CWRAPPER_OUTPUT_TYPE basic_##func(basic s, const basic a, const basic b) \
619  { \
620  CWRAPPER_BEGIN \
621  s->m = SymEngine::func(a->m, b->m); \
622  CWRAPPER_END \
623  }
624 
625 IMPLEMENT_TWO_ARG_FUNC(atan2)
626 IMPLEMENT_TWO_ARG_FUNC(kronecker_delta)
627 IMPLEMENT_TWO_ARG_FUNC(lowergamma)
628 IMPLEMENT_TWO_ARG_FUNC(uppergamma)
629 IMPLEMENT_TWO_ARG_FUNC(beta)
630 IMPLEMENT_TWO_ARG_FUNC(polygamma)
631 
632 #define IMPLEMENT_STR_CONVERSION(name, func) \
633  char *basic_##name(const basic s) \
634  { \
635  std::string str; \
636  try { \
637  str = func(*s->m); \
638  } catch (SymEngineException & e) { \
639  return nullptr; \
640  } catch (...) { \
641  return nullptr; \
642  } \
643  auto cc = new char[str.length() + 1]; \
644  std::strcpy(cc, str.c_str()); \
645  return cc; \
646  }
647 
648 IMPLEMENT_STR_CONVERSION(str, _str)
649 IMPLEMENT_STR_CONVERSION(str_julia, julia_str)
650 IMPLEMENT_STR_CONVERSION(str_mathml, mathml)
651 IMPLEMENT_STR_CONVERSION(str_latex, latex)
652 IMPLEMENT_STR_CONVERSION(str_ccode, ccode)
653 IMPLEMENT_STR_CONVERSION(str_jscode, jscode)
654 
655 void basic_str_free(char *s)
656 {
657  delete[] s;
658 }
659 
660 int symengine_have_component(const char *c)
661 {
662 #ifdef HAVE_SYMENGINE_MPFR
663  if (std::strcmp("mpfr", c) == 0)
664  return 1;
665 #endif
666 #ifdef HAVE_SYMENGINE_MPC
667  if (std::strcmp("mpc", c) == 0)
668  return 1;
669 #endif
670 #ifdef HAVE_SYMENGINE_FLINT
671  if (std::strcmp("flint", c) == 0)
672  return 1;
673 #endif
674 #ifdef HAVE_SYMENGINE_ARB
675  if (std::strcmp("arb", c) == 0)
676  return 1;
677 #endif
678 #ifdef HAVE_SYMENGINE_ECM
679  if (std::strcmp("ecm", c) == 0)
680  return 1;
681 #endif
682 #ifdef HAVE_SYMENGINE_PRIMESIEVE
683  if (std::strcmp("primesieve", c) == 0)
684  return 1;
685 #endif
686 #ifdef HAVE_SYMENGINE_PIRANHA
687  if (std::strcmp("piranha", c) == 0)
688  return 1;
689 #endif
690 #ifdef HAVE_SYMENGINE_BOOST
691  if (std::strcmp("boost", c) == 0)
692  return 1;
693 #endif
694 #ifdef HAVE_SYMENGINE_PTHREAD
695  if (std::strcmp("pthread", c) == 0)
696  return 1;
697 #endif
698 #ifdef HAVE_SYMENGINE_LLVM
699  if (std::strcmp("llvm", c) == 0)
700  return 1;
701 #endif
702 #ifdef HAVE_SYMENGINE_LLVM_LONG_DOUBLE
703  if (std::strcmp("llvm_long_double", c) == 0)
704  return 1;
705 #endif
706  return 0;
707 }
708 
709 int is_a_Number(const basic s)
710 {
711  return (int)is_a_Number(*(s->m));
712 }
713 int is_a_Integer(const basic c)
714 {
715  return is_a<Integer>(*(c->m));
716 }
717 int is_a_Rational(const basic c)
718 {
719  return is_a<Rational>(*(c->m));
720 }
721 int is_a_Symbol(const basic c)
722 {
723  return is_a<Symbol>(*(c->m));
724 }
725 int is_a_Complex(const basic c)
726 {
727  return is_a<Complex>(*(c->m));
728 }
729 int is_a_RealDouble(const basic c)
730 {
731  return is_a<RealDouble>(*(c->m));
732 }
733 int is_a_ComplexDouble(const basic c)
734 {
735  return is_a<ComplexDouble>(*(c->m));
736 }
737 int is_a_RealMPFR(const basic c)
738 {
739 #ifdef HAVE_SYMENGINE_MPFR
740  return is_a<RealMPFR>(*(c->m));
741 #else
742  return false;
743 #endif // HAVE_SYMENGINE_MPFR
744 }
745 int is_a_ComplexMPC(const basic c)
746 {
747 #ifdef HAVE_SYMENGINE_MPC
748  return is_a<ComplexMPC>(*(c->m));
749 #else
750  return false;
751 #endif // HAVE_SYMENGINE_MPC
752 }
753 
754 // C wrapper for std::vector<int>
755 
756 struct CVectorInt {
758 };
759 
760 CVectorInt *vectorint_new()
761 {
762  return new CVectorInt;
763 }
764 
765 int vectorint_placement_new_check(void *data, size_t size)
766 {
767  CVectorInt *self = (CVectorInt *)data;
768  if (size < sizeof(CVectorInt))
769  return 1;
770  if (not SymEngine::is_aligned(self))
771  return 2;
772  return 0;
773 }
774 
775 CVectorInt *vectorint_placement_new(void *data)
776 {
777 #if defined(WITH_SYMENGINE_ASSERT)
778  // if (size < sizeof(CVectorInt)) return 1; // Requires the 'size' argument
779  CVectorInt *self = (CVectorInt *)data;
780  SYMENGINE_ASSERT(SymEngine::is_aligned(self));
781 #endif
782  new (data) CVectorInt;
783  return (CVectorInt *)data;
784 }
785 
786 void vectorint_placement_free(CVectorInt *self)
787 {
788  self->m.~vector<int>();
789 }
790 
791 void vectorint_free(CVectorInt *self)
792 {
793  delete self;
794 }
795 
796 void vectorint_push_back(CVectorInt *self, int value)
797 {
798  self->m.push_back(value);
799 }
800 
801 int vectorint_get(CVectorInt *self, int n)
802 {
803  return self->m[n];
804 }
805 
806 // C wrapper for vec_basic
807 
808 struct CVecBasic {
810 };
811 
812 CVecBasic *vecbasic_new()
813 {
814  return new CVecBasic;
815 }
816 
817 void vecbasic_free(CVecBasic *self)
818 {
819  delete self;
820 }
821 
822 CWRAPPER_OUTPUT_TYPE vecbasic_push_back(CVecBasic *self, const basic value)
823 {
824  CWRAPPER_BEGIN
825 
826  self->m.push_back(value->m);
827 
828  CWRAPPER_END
829 }
830 
831 CWRAPPER_OUTPUT_TYPE vecbasic_get(CVecBasic *self, size_t n, basic result)
832 {
833  CWRAPPER_BEGIN
834 
835  SYMENGINE_ASSERT(n < self->m.size());
836  result->m = self->m[n];
837 
838  CWRAPPER_END
839 }
840 
841 CWRAPPER_OUTPUT_TYPE vecbasic_set(CVecBasic *self, size_t n, const basic s)
842 {
843  CWRAPPER_BEGIN
844  SYMENGINE_ASSERT(n < self->m.size());
845  self->m[n] = s->m;
846  CWRAPPER_END
847 }
848 
849 CWRAPPER_OUTPUT_TYPE vecbasic_erase(CVecBasic *self, size_t n)
850 {
851  CWRAPPER_BEGIN
852  SYMENGINE_ASSERT(n < self->m.size());
853  self->m.erase(self->m.begin() + n);
854  CWRAPPER_END
855 }
856 
857 size_t vecbasic_size(CVecBasic *self)
858 {
859  return self->m.size();
860 }
861 
862 CWRAPPER_OUTPUT_TYPE basic_max(basic s, CVecBasic *d)
863 {
864  CWRAPPER_BEGIN
865  s->m = SymEngine::max(d->m);
866  CWRAPPER_END
867 }
868 
869 CWRAPPER_OUTPUT_TYPE basic_min(basic s, CVecBasic *d)
870 {
871  CWRAPPER_BEGIN
872  s->m = SymEngine::min(d->m);
873  CWRAPPER_END
874 }
875 
876 // C wrapper for Matrix
877 
878 struct CDenseMatrix {
880 };
881 
884 };
885 
886 CDenseMatrix *dense_matrix_new()
887 {
888  return new CDenseMatrix();
889 }
890 
891 CDenseMatrix *dense_matrix_new_vec(unsigned rows, unsigned cols, CVecBasic *l)
892 {
893  return new CDenseMatrix({{rows, cols, l->m}});
894 }
895 
896 CDenseMatrix *dense_matrix_new_rows_cols(unsigned rows, unsigned cols)
897 {
898  return new CDenseMatrix({{rows, cols}});
899 }
900 
901 CSparseMatrix *sparse_matrix_new()
902 {
903  return new CSparseMatrix;
904 }
905 
906 void dense_matrix_free(CDenseMatrix *self)
907 {
908  delete self;
909 }
910 
911 void sparse_matrix_free(CSparseMatrix *self)
912 {
913  delete self;
914 }
915 
916 void sparse_matrix_init(CSparseMatrix *s)
917 {
918  s->m = SymEngine::CSRMatrix();
919 }
920 
921 void sparse_matrix_rows_cols(CSparseMatrix *s, unsigned long int rows,
922  unsigned long int cols)
923 {
924  s->m = SymEngine::CSRMatrix(numeric_cast<unsigned>(rows),
925  numeric_cast<unsigned>(cols));
926 }
927 
928 CWRAPPER_OUTPUT_TYPE dense_matrix_set(CDenseMatrix *s, const CDenseMatrix *d)
929 {
930  CWRAPPER_BEGIN
931  s->m = d->m;
932  CWRAPPER_END
933 }
934 
935 char *dense_matrix_str(const CDenseMatrix *s)
936 {
937  std::string str = s->m.__str__();
938  auto cc = new char[str.length() + 1];
939  std::strcpy(cc, str.c_str());
940  return cc;
941 }
942 
943 char *sparse_matrix_str(const CSparseMatrix *s)
944 {
945  std::string str = s->m.__str__();
946  auto cc = new char[str.length() + 1];
947  std::strcpy(cc, str.c_str());
948  return cc;
949 }
950 
951 CWRAPPER_OUTPUT_TYPE dense_matrix_rows_cols(CDenseMatrix *mat, unsigned r,
952  unsigned c)
953 {
954  CWRAPPER_BEGIN
955  mat->m.resize(r, c);
956  CWRAPPER_END
957 }
958 
959 CWRAPPER_OUTPUT_TYPE dense_matrix_get_basic(basic s, const CDenseMatrix *mat,
960  unsigned long int r,
961  unsigned long int c)
962 {
963  CWRAPPER_BEGIN
964  s->m = mat->m.get(numeric_cast<unsigned>(r), numeric_cast<unsigned>(c));
965  CWRAPPER_END
966 }
967 
968 CWRAPPER_OUTPUT_TYPE dense_matrix_set_basic(CDenseMatrix *mat,
969  unsigned long int r,
970  unsigned long int c, basic s)
971 {
972  CWRAPPER_BEGIN
973  mat->m.set(numeric_cast<unsigned>(r), numeric_cast<unsigned>(c), s->m);
974  CWRAPPER_END
975 }
976 
977 CWRAPPER_OUTPUT_TYPE sparse_matrix_get_basic(basic s, const CSparseMatrix *mat,
978  unsigned long int r,
979  unsigned long int c)
980 {
981  CWRAPPER_BEGIN
982  s->m = mat->m.get(numeric_cast<unsigned>(r), numeric_cast<unsigned>(c));
983  CWRAPPER_END
984 }
985 
986 CWRAPPER_OUTPUT_TYPE sparse_matrix_set_basic(CSparseMatrix *mat,
987  unsigned long int r,
988  unsigned long int c, basic s)
989 {
990  CWRAPPER_BEGIN
991  mat->m.set(numeric_cast<unsigned>(r), numeric_cast<unsigned>(c), s->m);
992  CWRAPPER_END
993 }
994 
995 CWRAPPER_OUTPUT_TYPE dense_matrix_det(basic s, const CDenseMatrix *mat)
996 {
997  CWRAPPER_BEGIN
998  s->m = mat->m.det();
999  CWRAPPER_END
1000 }
1001 CWRAPPER_OUTPUT_TYPE dense_matrix_inv(CDenseMatrix *s, const CDenseMatrix *mat)
1002 {
1003  CWRAPPER_BEGIN
1004  dense_matrix_rows_cols(s, mat->m.nrows(), mat->m.ncols());
1005  mat->m.inv(s->m);
1006  CWRAPPER_END
1007 }
1008 CWRAPPER_OUTPUT_TYPE dense_matrix_transpose(CDenseMatrix *s,
1009  const CDenseMatrix *mat)
1010 {
1011  CWRAPPER_BEGIN
1012  dense_matrix_rows_cols(s, mat->m.ncols(), mat->m.nrows());
1013  mat->m.transpose(s->m);
1014  CWRAPPER_END
1015 }
1016 CWRAPPER_OUTPUT_TYPE
1017 dense_matrix_submatrix(CDenseMatrix *s, const CDenseMatrix *mat,
1018  unsigned long int r1, unsigned long int c1,
1019  unsigned long int r2, unsigned long int c2,
1020  unsigned long int r, unsigned long int c)
1021 {
1022  CWRAPPER_BEGIN
1023  dense_matrix_rows_cols(s, numeric_cast<unsigned>(r2 - r1 + 1),
1024  numeric_cast<unsigned>(c2 - c1 + 1));
1025  mat->m.submatrix(s->m, numeric_cast<unsigned>(r1),
1026  numeric_cast<unsigned>(c1), numeric_cast<unsigned>(r2),
1027  numeric_cast<unsigned>(c2), numeric_cast<unsigned>(r),
1028  numeric_cast<unsigned>(c));
1029  CWRAPPER_END
1030 }
1031 
1032 CWRAPPER_OUTPUT_TYPE dense_matrix_row_join(CDenseMatrix *A,
1033  const CDenseMatrix *B)
1034 {
1035  CWRAPPER_BEGIN
1036  A->m.row_join(B->m);
1037  CWRAPPER_END
1038 }
1039 
1040 CWRAPPER_OUTPUT_TYPE dense_matrix_col_join(CDenseMatrix *A,
1041  const CDenseMatrix *B)
1042 {
1043  CWRAPPER_BEGIN
1044  A->m.col_join(B->m);
1045  CWRAPPER_END
1046 }
1047 
1048 CWRAPPER_OUTPUT_TYPE dense_matrix_row_del(CDenseMatrix *A, unsigned k)
1049 {
1050  CWRAPPER_BEGIN
1051  A->m.row_del(k);
1052  CWRAPPER_END
1053 }
1054 
1055 CWRAPPER_OUTPUT_TYPE dense_matrix_col_del(CDenseMatrix *A, unsigned k)
1056 {
1057  CWRAPPER_BEGIN
1058  A->m.col_del(k);
1059  CWRAPPER_END
1060 }
1061 
1062 unsigned long int dense_matrix_rows(const CDenseMatrix *s)
1063 {
1064  return s->m.nrows();
1065 }
1066 
1067 unsigned long int dense_matrix_cols(const CDenseMatrix *s)
1068 {
1069  return s->m.ncols();
1070 }
1071 
1072 CWRAPPER_OUTPUT_TYPE dense_matrix_add_matrix(CDenseMatrix *s,
1073  const CDenseMatrix *matA,
1074  const CDenseMatrix *matB)
1075 {
1076  CWRAPPER_BEGIN
1077  dense_matrix_rows_cols(s, matA->m.nrows(), matA->m.ncols());
1078  matA->m.add_matrix(matB->m, s->m);
1079  CWRAPPER_END
1080 }
1081 
1082 CWRAPPER_OUTPUT_TYPE dense_matrix_mul_matrix(CDenseMatrix *s,
1083  const CDenseMatrix *matA,
1084  const CDenseMatrix *matB)
1085 {
1086  CWRAPPER_BEGIN
1087  dense_matrix_rows_cols(s, matA->m.nrows(), matB->m.ncols());
1088  matA->m.mul_matrix(matB->m, s->m);
1089  CWRAPPER_END
1090 }
1091 
1092 CWRAPPER_OUTPUT_TYPE dense_matrix_add_scalar(CDenseMatrix *s,
1093  const CDenseMatrix *matA,
1094  const basic b)
1095 {
1096  CWRAPPER_BEGIN
1097  dense_matrix_rows_cols(s, matA->m.nrows(), matA->m.ncols());
1098  matA->m.add_scalar(b->m, s->m);
1099  CWRAPPER_END
1100 }
1101 
1102 CWRAPPER_OUTPUT_TYPE dense_matrix_mul_scalar(CDenseMatrix *s,
1103  const CDenseMatrix *matA,
1104  const basic b)
1105 {
1106  CWRAPPER_BEGIN
1107  dense_matrix_rows_cols(s, matA->m.nrows(), matA->m.ncols());
1108  matA->m.mul_scalar(b->m, s->m);
1109  CWRAPPER_END
1110 }
1111 
1112 CWRAPPER_OUTPUT_TYPE dense_matrix_LU(CDenseMatrix *l, CDenseMatrix *u,
1113  const CDenseMatrix *mat)
1114 {
1115  CWRAPPER_BEGIN
1116  dense_matrix_rows_cols(l, mat->m.nrows(), mat->m.ncols());
1117  dense_matrix_rows_cols(u, mat->m.nrows(), mat->m.ncols());
1118  mat->m.LU(l->m, u->m);
1119  CWRAPPER_END
1120 }
1121 
1122 CWRAPPER_OUTPUT_TYPE dense_matrix_LDL(CDenseMatrix *l, CDenseMatrix *d,
1123  const CDenseMatrix *mat)
1124 {
1125  CWRAPPER_BEGIN
1126  dense_matrix_rows_cols(l, mat->m.nrows(), mat->m.ncols());
1127  dense_matrix_rows_cols(d, mat->m.nrows(), mat->m.ncols());
1128  mat->m.LDL(l->m, d->m);
1129  CWRAPPER_END
1130 }
1131 
1132 CWRAPPER_OUTPUT_TYPE dense_matrix_FFLU(CDenseMatrix *lu,
1133  const CDenseMatrix *mat)
1134 {
1135  CWRAPPER_BEGIN
1136  dense_matrix_rows_cols(lu, mat->m.nrows(), mat->m.ncols());
1137  mat->m.FFLU(lu->m);
1138  CWRAPPER_END
1139 }
1140 
1141 CWRAPPER_OUTPUT_TYPE dense_matrix_FFLDU(CDenseMatrix *l, CDenseMatrix *d,
1142  CDenseMatrix *u,
1143  const CDenseMatrix *mat)
1144 {
1145  CWRAPPER_BEGIN
1146  dense_matrix_rows_cols(l, mat->m.nrows(), mat->m.ncols());
1147  dense_matrix_rows_cols(d, mat->m.nrows(), mat->m.ncols());
1148  dense_matrix_rows_cols(u, mat->m.nrows(), mat->m.ncols());
1149  mat->m.FFLDU(l->m, d->m, u->m);
1150  CWRAPPER_END
1151 }
1152 
1153 CWRAPPER_OUTPUT_TYPE dense_matrix_LU_solve(CDenseMatrix *x,
1154  const CDenseMatrix *A,
1155  const CDenseMatrix *b)
1156 {
1157  CWRAPPER_BEGIN
1158  dense_matrix_rows_cols(x, A->m.ncols(), 1);
1159  A->m.LU_solve(b->m, x->m);
1160  CWRAPPER_END
1161 }
1162 
1163 CWRAPPER_OUTPUT_TYPE dense_matrix_ones(CDenseMatrix *s, unsigned long int r,
1164  unsigned long int c)
1165 {
1166  CWRAPPER_BEGIN
1167  dense_matrix_rows_cols(s, numeric_cast<unsigned>(r),
1168  numeric_cast<unsigned>(c));
1169  ones(s->m);
1170  CWRAPPER_END
1171 }
1172 
1173 CWRAPPER_OUTPUT_TYPE dense_matrix_zeros(CDenseMatrix *s, unsigned long int r,
1174  unsigned long int c)
1175 {
1176  CWRAPPER_BEGIN
1177  dense_matrix_rows_cols(s, numeric_cast<unsigned>(r),
1178  numeric_cast<unsigned>(c));
1179  zeros(s->m);
1180  CWRAPPER_END
1181 }
1182 CWRAPPER_OUTPUT_TYPE dense_matrix_diag(CDenseMatrix *s, CVecBasic *d,
1183  long int k)
1184 {
1185  CWRAPPER_BEGIN
1186  unsigned int vec_size = numeric_cast<unsigned>(vecbasic_size(d));
1187  dense_matrix_rows_cols(
1188  s, numeric_cast<unsigned>(vec_size + (k >= 0 ? k : -k)),
1189  numeric_cast<unsigned>(vec_size + (k >= 0 ? k : -k)));
1190  diag(s->m, d->m, numeric_cast<int>(k));
1191  CWRAPPER_END
1192 }
1193 
1194 CWRAPPER_OUTPUT_TYPE dense_matrix_eye(CDenseMatrix *s, unsigned long int N,
1195  unsigned long int M, int k)
1196 {
1197  CWRAPPER_BEGIN
1198  dense_matrix_rows_cols(s, numeric_cast<unsigned>(N),
1199  numeric_cast<unsigned>(M));
1200  eye(s->m, k);
1201  CWRAPPER_END
1202 }
1203 
1204 CWRAPPER_OUTPUT_TYPE dense_matrix_diff(CDenseMatrix *result,
1205  const CDenseMatrix *A, basic const x)
1206 {
1207  if (not is_a_Symbol(x))
1208  return SYMENGINE_RUNTIME_ERROR;
1209  CWRAPPER_BEGIN
1210  diff(A->m, rcp_static_cast<const Symbol>(x->m), result->m);
1211  CWRAPPER_END
1212 }
1213 
1214 CWRAPPER_OUTPUT_TYPE dense_matrix_jacobian(CDenseMatrix *result,
1215  const CDenseMatrix *A,
1216  const CDenseMatrix *x)
1217 {
1218  CWRAPPER_BEGIN
1219  jacobian(A->m, x->m, result->m);
1220  CWRAPPER_END
1221 }
1222 
1223 int is_a_DenseMatrix(const CDenseMatrix *c)
1224 {
1225  return is_a<DenseMatrix>(c->m);
1226 }
1227 
1228 int is_a_SparseMatrix(const CSparseMatrix *c)
1229 {
1230  return is_a<CSRMatrix>(c->m);
1231 }
1232 
1233 int dense_matrix_eq(CDenseMatrix *lhs, CDenseMatrix *rhs)
1234 {
1235  return (lhs->m) == (rhs->m);
1236 }
1237 
1238 int sparse_matrix_eq(CSparseMatrix *lhs, CSparseMatrix *rhs)
1239 {
1240  return (lhs->m) == (rhs->m);
1241 }
1242 
1243 // C Wrapper for set_basic
1244 
1245 struct CSetBasic {
1247 };
1248 
1249 CSetBasic *setbasic_new()
1250 {
1251  return new CSetBasic;
1252 }
1253 
1254 void setbasic_free(CSetBasic *self)
1255 {
1256  delete self;
1257 }
1258 
1259 int setbasic_insert(CSetBasic *self, const basic value)
1260 {
1261  return (self->m.insert(value->m)).second ? 1 : 0;
1262 }
1263 
1264 void setbasic_get(CSetBasic *self, int n, basic result)
1265 {
1266  result->m = *std::next((self->m).begin(), n);
1267 }
1268 
1269 int setbasic_find(CSetBasic *self, basic value)
1270 {
1271  return self->m.find(value->m) != (self->m).end() ? 1 : 0;
1272 }
1273 
1274 int setbasic_erase(CSetBasic *self, const basic value)
1275 {
1276  return (self->m.erase(value->m)) ? 1 : 0;
1277 }
1278 
1279 size_t setbasic_size(CSetBasic *self)
1280 {
1281  return self->m.size();
1282 }
1283 
1284 // C Wrapper for map_basic_basic
1285 
1288 };
1289 
1290 CMapBasicBasic *mapbasicbasic_new()
1291 {
1292  return new CMapBasicBasic;
1293 }
1294 
1295 void mapbasicbasic_free(CMapBasicBasic *self)
1296 {
1297  delete self;
1298 }
1299 
1300 void mapbasicbasic_insert(CMapBasicBasic *self, const basic key,
1301  const basic mapped)
1302 {
1303  (self->m)[key->m] = mapped->m;
1304 }
1305 
1306 int mapbasicbasic_get(CMapBasicBasic *self, const basic key, basic mapped)
1307 {
1308  auto it = self->m.find(key->m);
1309  if (it != self->m.end()) {
1310  mapped->m = it->second;
1311  return 1;
1312  }
1313  return 0;
1314 }
1315 
1316 size_t mapbasicbasic_size(CMapBasicBasic *self)
1317 {
1318  return self->m.size();
1319 }
1320 
1321 // ----------------------
1322 
1323 CWRAPPER_OUTPUT_TYPE basic_get_args(const basic self, CVecBasic *args)
1324 {
1325  CWRAPPER_BEGIN
1326  args->m = self->m->get_args();
1327  CWRAPPER_END
1328 }
1329 
1330 CWRAPPER_OUTPUT_TYPE basic_free_symbols(const basic self, CSetBasic *symbols)
1331 {
1332  CWRAPPER_BEGIN
1333  symbols->m = SymEngine::free_symbols(*(self->m));
1334  CWRAPPER_END
1335 }
1336 
1337 CWRAPPER_OUTPUT_TYPE basic_function_symbols(CSetBasic *symbols,
1338  const basic self)
1339 {
1340  CWRAPPER_BEGIN
1341  symbols->m = SymEngine::atoms<SymEngine::FunctionSymbol>(*(self->m));
1342  CWRAPPER_END
1343 }
1344 
1345 size_t basic_hash(const basic self)
1346 {
1347  return static_cast<size_t>(self->m->hash());
1348 }
1349 
1350 CWRAPPER_OUTPUT_TYPE basic_subs(basic s, const basic e,
1351  const CMapBasicBasic *mapbb)
1352 {
1353  CWRAPPER_BEGIN
1354  s->m = e->m->subs(mapbb->m);
1355  CWRAPPER_END
1356 }
1357 
1358 CWRAPPER_OUTPUT_TYPE basic_subs2(basic s, const basic e, const basic a,
1359  const basic b)
1360 {
1361  CWRAPPER_BEGIN
1362  s->m = e->m->subs({{a->m, b->m}});
1363  CWRAPPER_END
1364 }
1365 
1366 CWRAPPER_OUTPUT_TYPE function_symbol_set(basic s, const char *c,
1367  const CVecBasic *arg)
1368 {
1369  CWRAPPER_BEGIN
1370  s->m = function_symbol(c, arg->m);
1371  CWRAPPER_END
1372 }
1373 
1374 char *function_symbol_get_name(const basic b)
1375 {
1376  SYMENGINE_ASSERT(is_a<FunctionSymbol>(*(b->m)));
1377  std::string str = down_cast<const FunctionSymbol &>(*(b->m)).get_name();
1378  auto cc = new char[str.length() + 1];
1379  std::strcpy(cc, str.c_str());
1380  return cc;
1381 }
1382 
1383 CWRAPPER_OUTPUT_TYPE basic_coeff(basic c, const basic b, const basic x,
1384  const basic n)
1385 {
1386  CWRAPPER_BEGIN
1387  c->m = SymEngine::coeff(*(b->m), *(x->m), *(n->m));
1388  CWRAPPER_END
1389 }
1390 
1391 // ----------------------
1392 
1393 CWRAPPER_OUTPUT_TYPE vecbasic_linsolve(CVecBasic *sol, const CVecBasic *sys,
1394  const CVecBasic *sym)
1395 {
1396  CWRAPPER_BEGIN
1397  vec_basic vb = sym->m;
1398  SYMENGINE_ASSERT(
1399  std::all_of(vb.cbegin(), vb.cend(),
1400  [](RCP<const Basic> b) { return is_a<const Symbol>(*b); }));
1401  vec_sym vs(vb.size());
1402  for (unsigned i = 0; i < vb.size(); i++)
1403  vs[i] = rcp_static_cast<const Symbol>(vb[i]);
1404  sol->m = SymEngine::linsolve(sys->m, vs);
1405  CWRAPPER_END
1406 }
1407 
1408 CWRAPPER_OUTPUT_TYPE basic_solve_poly(CSetBasic *r, const basic f,
1409  const basic s)
1410 {
1411  CWRAPPER_BEGIN
1412  SYMENGINE_ASSERT(is_a<Symbol>(*(s->m)));
1413  RCP<const Set> set
1414  = SymEngine::solve_poly(f->m, rcp_static_cast<const Symbol>(s->m));
1415  if (not is_a<FiniteSet>(*set)) {
1416  return SYMENGINE_RUNTIME_ERROR;
1417  }
1418  r->m = down_cast<const FiniteSet &>(*set).get_container();
1419  CWRAPPER_END
1420 }
1421 
1422 // ----------------------
1423 
1424 char *ascii_art_str()
1425 {
1426  std::string str = SymEngine::ascii_art();
1427  auto cc = new char[str.length() + 1];
1428  std::strcpy(cc, str.c_str());
1429  return cc;
1430 }
1431 
1432 // Cwrapper for ntheory
1433 
1434 CWRAPPER_OUTPUT_TYPE ntheory_gcd(basic s, const basic a, const basic b)
1435 {
1436  CWRAPPER_BEGIN
1437  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1438  SYMENGINE_ASSERT(is_a<Integer>(*(b->m)));
1439  s->m = SymEngine::gcd(down_cast<const Integer &>(*(a->m)),
1440  down_cast<const Integer &>(*(b->m)));
1441  CWRAPPER_END
1442 }
1443 
1444 CWRAPPER_OUTPUT_TYPE ntheory_lcm(basic s, const basic a, const basic b)
1445 {
1446  CWRAPPER_BEGIN
1447  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1448  SYMENGINE_ASSERT(is_a<Integer>(*(b->m)));
1449  s->m = SymEngine::lcm(down_cast<const Integer &>(*(a->m)),
1450  down_cast<const Integer &>(*(b->m)));
1451  CWRAPPER_END
1452 }
1453 
1454 CWRAPPER_OUTPUT_TYPE ntheory_gcd_ext(basic g, basic s, basic t, const basic a,
1455  const basic b)
1456 {
1457  CWRAPPER_BEGIN
1458  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1459  SYMENGINE_ASSERT(is_a<Integer>(*(b->m)));
1460  SymEngine::RCP<const Integer> g_, s_, t_;
1461  SymEngine::gcd_ext(SymEngine::outArg(g_), SymEngine::outArg(s_),
1462  SymEngine::outArg(t_),
1463  down_cast<const Integer &>(*(a->m)),
1464  down_cast<const Integer &>(*(b->m)));
1465  g->m = g_;
1466  s->m = s_;
1467  t->m = t_;
1468  CWRAPPER_END
1469 }
1470 
1471 CWRAPPER_OUTPUT_TYPE ntheory_nextprime(basic s, const basic a)
1472 {
1473  CWRAPPER_BEGIN
1474  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1475  s->m = SymEngine::nextprime(down_cast<const Integer &>(*(a->m)));
1476  CWRAPPER_END
1477 }
1478 
1479 CWRAPPER_OUTPUT_TYPE ntheory_mod(basic s, const basic n, const basic d)
1480 {
1481  CWRAPPER_BEGIN
1482  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1483  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1484  s->m = SymEngine::mod(down_cast<const Integer &>(*(n->m)),
1485  down_cast<const Integer &>(*(d->m)));
1486  CWRAPPER_END
1487 }
1488 
1489 CWRAPPER_OUTPUT_TYPE ntheory_quotient(basic s, const basic n, const basic d)
1490 {
1491  CWRAPPER_BEGIN
1492  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1493  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1494  s->m = SymEngine::quotient(down_cast<const Integer &>(*(n->m)),
1495  down_cast<const Integer &>(*(d->m)));
1496  CWRAPPER_END
1497 }
1498 
1499 CWRAPPER_OUTPUT_TYPE ntheory_quotient_mod(basic q, basic r, const basic n,
1500  const basic d)
1501 {
1502  CWRAPPER_BEGIN
1503  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1504  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1505  SymEngine::RCP<const Integer> q_, r_;
1506  SymEngine::quotient_mod(SymEngine::outArg(q_), SymEngine::outArg(r_),
1507  down_cast<const Integer &>(*(n->m)),
1508  down_cast<const Integer &>(*(d->m)));
1509  q->m = q_;
1510  r->m = r_;
1511  CWRAPPER_END
1512 }
1513 
1514 CWRAPPER_OUTPUT_TYPE ntheory_mod_f(basic s, const basic n, const basic d)
1515 {
1516  CWRAPPER_BEGIN
1517  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1518  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1519  s->m = SymEngine::mod_f(down_cast<const Integer &>(*(n->m)),
1520  down_cast<const Integer &>(*(d->m)));
1521  CWRAPPER_END
1522 }
1523 
1524 CWRAPPER_OUTPUT_TYPE ntheory_quotient_f(basic s, const basic n, const basic d)
1525 {
1526  CWRAPPER_BEGIN
1527  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1528  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1529  s->m = SymEngine::quotient_f(down_cast<const Integer &>(*(n->m)),
1530  down_cast<const Integer &>(*(d->m)));
1531  CWRAPPER_END
1532 }
1533 
1534 CWRAPPER_OUTPUT_TYPE ntheory_quotient_mod_f(basic q, basic r, const basic n,
1535  const basic d)
1536 {
1537  CWRAPPER_BEGIN
1538  SYMENGINE_ASSERT(is_a<Integer>(*(n->m)));
1539  SYMENGINE_ASSERT(is_a<Integer>(*(d->m)));
1540  SymEngine::RCP<const Integer> q_, r_;
1541  SymEngine::quotient_mod_f(SymEngine::outArg(q_), SymEngine::outArg(r_),
1542  down_cast<const Integer &>(*(n->m)),
1543  down_cast<const Integer &>(*(d->m)));
1544  q->m = q_;
1545  r->m = r_;
1546  CWRAPPER_END
1547 }
1548 
1549 int ntheory_mod_inverse(basic b, const basic a, const basic m)
1550 {
1551  int ret_val;
1552  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1553  SYMENGINE_ASSERT(is_a<Integer>(*(m->m)));
1554  SymEngine::RCP<const Integer> b_;
1555  ret_val = SymEngine::mod_inverse(SymEngine::outArg(b_),
1556  down_cast<const Integer &>(*(a->m)),
1557  down_cast<const Integer &>(*(m->m)));
1558  b->m = b_;
1559  return ret_val;
1560 }
1561 
1562 CWRAPPER_OUTPUT_TYPE ntheory_fibonacci(basic s, unsigned long a)
1563 {
1564  CWRAPPER_BEGIN
1565  s->m = SymEngine::fibonacci(a);
1566  CWRAPPER_END
1567 }
1568 
1569 CWRAPPER_OUTPUT_TYPE ntheory_fibonacci2(basic g, basic s, unsigned long a)
1570 {
1571  CWRAPPER_BEGIN
1572  SymEngine::RCP<const Integer> g_, s_;
1573  SymEngine::fibonacci2(SymEngine::outArg(g_), SymEngine::outArg(s_), a);
1574  g->m = g_;
1575  s->m = s_;
1576  CWRAPPER_END
1577 }
1578 
1579 CWRAPPER_OUTPUT_TYPE ntheory_lucas(basic s, unsigned long a)
1580 {
1581  CWRAPPER_BEGIN
1582  s->m = SymEngine::lucas(a);
1583  CWRAPPER_END
1584 }
1585 
1586 CWRAPPER_OUTPUT_TYPE ntheory_lucas2(basic g, basic s, unsigned long a)
1587 {
1588  CWRAPPER_BEGIN
1589  SymEngine::RCP<const Integer> g_, s_;
1590  SymEngine::lucas2(SymEngine::outArg(g_), SymEngine::outArg(s_), a);
1591  g->m = g_;
1592  s->m = s_;
1593  CWRAPPER_END
1594 }
1595 
1596 CWRAPPER_OUTPUT_TYPE ntheory_binomial(basic s, const basic a, unsigned long b)
1597 {
1598  CWRAPPER_BEGIN
1599  SYMENGINE_ASSERT(is_a<Integer>(*(a->m)));
1600  s->m = SymEngine::binomial(down_cast<const Integer &>(*(a->m)), b);
1601  CWRAPPER_END
1602 }
1603 
1604 CWRAPPER_OUTPUT_TYPE ntheory_factorial(basic s, unsigned long n)
1605 {
1606  CWRAPPER_BEGIN
1607  s->m = SymEngine::factorial(n);
1608  CWRAPPER_END
1609 }
1610 
1612 CWRAPPER_OUTPUT_TYPE basic_evalf(basic s, const basic b, unsigned long bits,
1613  int real)
1614 {
1615 
1616  CWRAPPER_BEGIN
1617  s->m = SymEngine::evalf(*(b->m), bits, (SymEngine::EvalfDomain)real);
1618  CWRAPPER_END
1619 }
1620 
1621 CWRAPPER_OUTPUT_TYPE basic_as_numer_denom(basic numer, basic denom,
1622  const basic x)
1623 {
1624  CWRAPPER_BEGIN
1625  SymEngine::as_numer_denom(x->m, SymEngine::outArg(numer->m),
1626  SymEngine::outArg(denom->m));
1627  CWRAPPER_END
1628 }
1629 
1632 };
1633 
1634 CLambdaRealDoubleVisitor *lambda_real_double_visitor_new()
1635 {
1636  return new CLambdaRealDoubleVisitor();
1637 }
1638 
1639 void lambda_real_double_visitor_init(CLambdaRealDoubleVisitor *self,
1640  const CVecBasic *args,
1641  const CVecBasic *exprs, int perform_cse)
1642 {
1643  self->m.init(args->m, exprs->m, perform_cse);
1644 }
1645 
1646 void lambda_real_double_visitor_call(CLambdaRealDoubleVisitor *self,
1647  double *const outs,
1648  const double *const inps)
1649 {
1650  self->m.call(outs, inps);
1651 }
1652 
1653 void lambda_real_double_visitor_free(CLambdaRealDoubleVisitor *self)
1654 {
1655  delete self;
1656 }
1657 
1658 #ifdef HAVE_SYMENGINE_LLVM
1659 // double
1660 struct CLLVMDoubleVisitor {
1661  SymEngine::LLVMDoubleVisitor m;
1662 };
1663 
1664 CLLVMDoubleVisitor *llvm_double_visitor_new()
1665 {
1666  return new CLLVMDoubleVisitor();
1667 }
1668 
1669 void llvm_double_visitor_init(CLLVMDoubleVisitor *self, const CVecBasic *args,
1670  const CVecBasic *exprs, int perform_cse,
1671  int opt_level)
1672 {
1673  self->m.init(args->m, exprs->m, perform_cse, opt_level);
1674 }
1675 
1676 void llvm_double_visitor_call(CLLVMDoubleVisitor *self, double *const outs,
1677  const double *const inps)
1678 {
1679  self->m.call(outs, inps);
1680 }
1681 
1682 void llvm_double_visitor_free(CLLVMDoubleVisitor *self)
1683 {
1684  delete self;
1685 }
1686 // float
1687 struct CLLVMFloatVisitor {
1688  SymEngine::LLVMFloatVisitor m;
1689 };
1690 
1691 CLLVMFloatVisitor *llvm_float_visitor_new()
1692 {
1693  return new CLLVMFloatVisitor();
1694 }
1695 
1696 void llvm_float_visitor_init(CLLVMFloatVisitor *self, const CVecBasic *args,
1697  const CVecBasic *exprs, int perform_cse,
1698  int opt_level)
1699 {
1700  self->m.init(args->m, exprs->m, perform_cse, opt_level);
1701 }
1702 
1703 void llvm_float_visitor_call(CLLVMFloatVisitor *self, float *const outs,
1704  const float *const inps)
1705 {
1706  self->m.call(outs, inps);
1707 }
1708 
1709 void llvm_float_visitor_free(CLLVMFloatVisitor *self)
1710 {
1711  delete self;
1712 }
1713 #ifdef SYMENGINE_HAVE_LLVM_LONG_DOUBLE
1714 // long double
1715 struct CLLVMLongDoubleVisitor {
1716  SymEngine::LLVMLongDoubleVisitor m;
1717 };
1718 
1719 CLLVMLongDoubleVisitor *llvm_long_double_visitor_new()
1720 {
1721  return new CLLVMLongDoubleVisitor();
1722 }
1723 
1724 void llvm_long_double_visitor_init(CLLVMLongDoubleVisitor *self,
1725  const CVecBasic *args,
1726  const CVecBasic *exprs, int perform_cse,
1727  int opt_level)
1728 {
1729  self->m.init(args->m, exprs->m, perform_cse, opt_level);
1730 }
1731 
1732 void llvm_long_double_visitor_call(CLLVMLongDoubleVisitor *self,
1733  long double *const outs,
1734  const long double *const inps)
1735 {
1736  self->m.call(outs, inps);
1737 }
1738 
1739 void llvm_long_double_visitor_free(CLLVMLongDoubleVisitor *self)
1740 {
1741  delete self;
1742 }
1743 #endif
1744 #endif
1745 
1746 CWRAPPER_OUTPUT_TYPE basic_cse(CVecBasic *replacement_syms,
1747  CVecBasic *replacement_exprs,
1748  CVecBasic *reduced_exprs, const CVecBasic *exprs)
1749 {
1750  CWRAPPER_BEGIN
1751  vec_pair replacements;
1752  SymEngine::cse(replacements, reduced_exprs->m, exprs->m);
1753  for (auto &p : replacements) {
1754  replacement_syms->m.push_back(p.first);
1755  replacement_exprs->m.push_back(p.second);
1756  }
1757  CWRAPPER_END
1758 }
1760 void symengine_print_stack_on_segfault()
1761 {
1762  SymEngine::print_stack_on_segfault();
1763 }
1764 }
T all_of(T... args)
T c_str(T... args)
The lowest unit of symbolic representation.
Definition: basic.h:95
std::string __str__() const
Definition: basic.cpp:22
ComplexBase Class for deriving all complex classes.
Definition: complex.h:16
Complex Double Class to hold std::complex<double> values.
Complex Class.
Definition: complex.h:33
static RCP< const Number > from_mpq(const rational_class re, const rational_class im)
Definition: complex.cpp:93
static RCP< const Number > from_two_rats(const Rational &re, const Rational &im)
Definition: complex.cpp:104
static RCP< const Number > from_two_nums(const Number &re, const Number &im)
Definition: complex.cpp:109
Integer Class.
Definition: integer.h:19
Rational Class.
Definition: rational.h:16
static RCP< const Number > from_mpq(const rational_class &i)
Definition: rational.cpp:23
static RCP< const Number > from_two_ints(const Integer &n, const Integer &d)
Definition: rational.cpp:44
RealDouble Class to hold double values.
Definition: real_double.h:20
T end(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool is_a_Number(const Basic &b)
Definition: number.h:130
RCP< const Basic > cbrt(const RCP< const Basic > &arg)
Definition: pow.h:66
RCP< const Integer > nextprime(const Integer &a)
Definition: ntheory.cpp:170
void fibonacci2(const Ptr< RCP< const Integer >> &g, const Ptr< RCP< const Integer >> &s, unsigned long n)
Fibonacci n and n-1.
Definition: ntheory.cpp:115
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
Definition: mul.cpp:426
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:200
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
Definition: symbol.h:82
RCP< const Integer > gcd(const Integer &a, const Integer &b)
Greatest Common Divisor.
Definition: ntheory.cpp:29
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
Definition: functions.cpp:3512
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Integer > mod(const Integer &n, const Integer &d)
modulo round toward zero
Definition: ntheory.cpp:64
RCP< const Basic > sqrt(const RCP< const Basic > &arg)
Definition: pow.h:61
RCP< const Integer > lucas(unsigned long n)
Lucas number.
Definition: ntheory.cpp:125
RCP< const Integer > quotient_f(const Integer &n, const Integer &d)
Definition: ntheory.cpp:91
RCP< const Integer > fibonacci(unsigned long n)
Fibonacci number.
Definition: ntheory.cpp:108
RCP< const Basic > sub(const RCP< const Basic > &a, const RCP< const Basic > &b)
Substracts b from a.
Definition: add.cpp:495
RCP< const Integer > mod_f(const Integer &n, const Integer &d)
modulo round toward -inf
Definition: ntheory.cpp:84
RCP< const Integer > quotient(const Integer &n, const Integer &d)
Definition: ntheory.cpp:69
int mod_inverse(const Ptr< RCP< const Integer >> &b, const Integer &a, const Integer &m)
inverse modulo
Definition: ntheory.cpp:54
bool is_a(const Basic &b)
Templatised version to check is_a type.
Definition: basic-inl.h:36
RCP< const Integer > lcm(const Integer &a, const Integer &b)
Least Common Multiple.
Definition: ntheory.cpp:47
RCP< const Integer > binomial(const Integer &n, unsigned long k)
Binomial Coefficient.
Definition: ntheory.cpp:143
void quotient_mod_f(const Ptr< RCP< const Integer >> &q, const Ptr< RCP< const Integer >> &r, const Integer &n, const Integer &d)
Definition: ntheory.cpp:98
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition: mul.cpp:347
RCP< const Integer > factorial(unsigned long n)
Factorial.
Definition: ntheory.cpp:151
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425
RCP< const Constant > constant(const std::string &name)
inline version to return Constant
Definition: constants.h:53
tribool is_zero(const Basic &b, const Assumptions *assumptions=nullptr)
Check if a number is zero.
void gcd_ext(const Ptr< RCP< const Integer >> &g, const Ptr< RCP< const Integer >> &s, const Ptr< RCP< const Integer >> &t, const Integer &a, const Integer &b)
Extended GCD.
Definition: ntheory.cpp:36
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
RCP< const Basic > expand(const RCP< const Basic > &self, bool deep=true)
Expands self
Definition: expand.cpp:369
RCP< const Basic > min(const vec_basic &arg)
Canonicalize Min:
Definition: functions.cpp:3616
bool is_a_Complex(const Basic &b)
Definition: complex.h:24
void quotient_mod(const Ptr< RCP< const Integer >> &q, const Ptr< RCP< const Integer >> &r, const Integer &n, const Integer &d)
Definition: ntheory.cpp:74
void lucas2(const Ptr< RCP< const Integer >> &g, const Ptr< RCP< const Integer >> &s, unsigned long n)
Lucas number n and n-1.
Definition: ntheory.cpp:132
T next(T... args)
T push_back(T... args)
T length(T... args)
T strcmp(T... args)
T strcpy(T... args)
Our less operator (<):
Definition: basic.h:220