functions.cpp
1 #include <symengine/visitor.h>
2 #include <symengine/symengine_exception.h>
3 
4 namespace SymEngine
5 {
6 
7 extern RCP<const Basic> i2;
8 extern RCP<const Basic> i3;
9 extern RCP<const Basic> i5;
10 extern RCP<const Basic> im2;
11 extern RCP<const Basic> im3;
12 extern RCP<const Basic> im5;
13 
14 RCP<const Basic> sqrt(RCP<const Basic> &arg)
15 {
16  return pow(arg, div(one, i2));
17 }
18 RCP<const Basic> cbrt(RCP<const Basic> &arg)
19 {
20  return pow(arg, div(one, i3));
21 }
22 
23 extern RCP<const Basic> sq3;
24 extern RCP<const Basic> sq2;
25 extern RCP<const Basic> sq5;
26 
27 extern RCP<const Basic> C0;
28 extern RCP<const Basic> C1;
29 extern RCP<const Basic> C2;
30 extern RCP<const Basic> C3;
31 extern RCP<const Basic> C4;
32 extern RCP<const Basic> C5;
33 extern RCP<const Basic> C6;
34 
35 extern RCP<const Basic> mC0;
36 extern RCP<const Basic> mC1;
37 extern RCP<const Basic> mC2;
38 extern RCP<const Basic> mC3;
39 extern RCP<const Basic> mC4;
40 extern RCP<const Basic> mC5;
41 extern RCP<const Basic> mC6;
42 
43 // sin_table()[n] represents the value of sin(pi*n/12) for n = 0..23
44 static const RCP<const Basic> *sin_table()
45 {
46  static const RCP<const Basic> table[]
47  = {zero, C0, C1, C2, C3, C4, one, C4, C3, C2, C1, C0,
48  zero, mC0, mC1, mC2, mC3, mC4, minus_one, mC4, mC3, mC2, mC1, mC0};
49  return table;
50 }
51 
52 static const umap_basic_basic &inverse_cst()
53 {
54  static const umap_basic_basic inverse_cst_ = {
55  {C3, i3},
56  {mC3, im3},
57  {C2, mul(i2, i2)},
58  {mC2, mul(im2, i2)},
59  {C4, integer(12)},
60  {mC4, integer(-12)},
61  {C5, i5},
62  {mC5, im5},
63  {C6, integer(10)},
64  {mC6, integer(-10)},
65  {div(one, i2), integer(6)},
66  {div(minus_one, i2), integer(-6)},
67  };
68  return inverse_cst_;
69 }
70 
71 static const umap_basic_basic &inverse_tct()
72 {
73  static const umap_basic_basic inverse_tct_ = {
74  {div(one, sq3), mul(i2, i3)},
75  {div(minus_one, sq3), mul(im2, i3)},
76  {sq3, i3},
77  {mul(minus_one, sq3), im3},
78  {add(one, sq2), div(pow(i2, i3), i3)},
79  {mul(minus_one, add(one, sq2)), div(pow(i2, i3), im3)},
80  {sub(sq2, one), pow(i2, i3)},
81  {sub(one, sq2), pow(im2, i3)},
82  {sub(i2, sq3), mul(mul(i2, i2), i3)},
83  {sub(sq3, i2), mul(mul(im2, i2), i3)},
84  {sqrt(add(i5, mul(i2, sqrt(i5)))), div(i5, i2)},
85  {mul(minus_one, sqrt(add(i5, mul(i2, sqrt(i5))))), div(im5, i2)},
86  {one, pow(i2, i2)},
87  {minus_one, mul(minus_one, pow(i2, i2))},
88  };
89  return inverse_tct_;
90 }
91 
92 Conjugate::Conjugate(const RCP<const Basic> &arg) : OneArgFunction(arg)
93 {
94  SYMENGINE_ASSIGN_TYPEID()
95  SYMENGINE_ASSERT(is_canonical(arg))
96 }
97 
98 bool Conjugate::is_canonical(const RCP<const Basic> &arg) const
99 {
100  if (is_a_Number(*arg)) {
101  if (eq(*arg, *ComplexInf)) {
102  return true;
103  }
104  return false;
105  }
106  if (is_a<Constant>(*arg)) {
107  return false;
108  }
109  if (is_a<Mul>(*arg)) {
110  return false;
111  }
112  if (is_a<Pow>(*arg)) {
113  if (is_a<Integer>(*down_cast<const Pow &>(*arg).get_exp())) {
114  return false;
115  }
116  }
117  // OneArgFunction classes
118  if (is_a<Sign>(*arg) or is_a<Conjugate>(*arg) or is_a<Erf>(*arg)
119  or is_a<Erfc>(*arg) or is_a<Gamma>(*arg) or is_a<LogGamma>(*arg)
120  or is_a<Abs>(*arg)) {
121  return false;
122  }
123  if (is_a<Sin>(*arg) or is_a<Cos>(*arg) or is_a<Tan>(*arg) or is_a<Cot>(*arg)
124  or is_a<Sec>(*arg) or is_a<Csc>(*arg)) {
125  return false;
126  }
127  if (is_a<Sinh>(*arg) or is_a<Cosh>(*arg) or is_a<Tanh>(*arg)
128  or is_a<Coth>(*arg) or is_a<Sech>(*arg) or is_a<Csch>(*arg)) {
129  return false;
130  }
131  // TwoArgFunction classes
132  if (is_a<KroneckerDelta>(*arg) or is_a<ATan2>(*arg)
133  or is_a<LowerGamma>(*arg) or is_a<UpperGamma>(*arg)
134  or is_a<Beta>(*arg)) {
135  return false;
136  }
137  // MultiArgFunction class
138  if (is_a<LeviCivita>(*arg)) {
139  return false;
140  }
141  return true;
142 }
143 
144 RCP<const Basic> Conjugate::create(const RCP<const Basic> &arg) const
145 {
146  return conjugate(arg);
147 }
148 
149 RCP<const Basic> conjugate(const RCP<const Basic> &arg)
150 {
151  if (is_a_Number(*arg)) {
152  return down_cast<const Number &>(*arg).conjugate();
153  }
154  if (is_a<Constant>(*arg) or is_a<Abs>(*arg) or is_a<KroneckerDelta>(*arg)
155  or is_a<LeviCivita>(*arg)) {
156  return arg;
157  }
158  if (is_a<Mul>(*arg)) {
159  const map_basic_basic &dict = down_cast<const Mul &>(*arg).get_dict();
160  map_basic_basic new_dict;
161  RCP<const Number> coef = rcp_static_cast<const Number>(
162  conjugate(down_cast<const Mul &>(*arg).get_coef()));
163  for (const auto &p : dict) {
164  if (is_a<Integer>(*p.second)) {
165  Mul::dict_add_term_new(outArg(coef), new_dict, p.second,
166  conjugate(p.first));
167  } else {
168  Mul::dict_add_term_new(
169  outArg(coef), new_dict, one,
170  conjugate(Mul::from_dict(one, {{p.first, p.second}})));
171  }
172  }
173  return Mul::from_dict(coef, std::move(new_dict));
174  }
175  if (is_a<Pow>(*arg)) {
176  RCP<const Basic> base = down_cast<const Pow &>(*arg).get_base();
177  RCP<const Basic> exp = down_cast<const Pow &>(*arg).get_exp();
178  if (is_a<Integer>(*exp)) {
179  return pow(conjugate(base), exp);
180  }
181  }
182  if (is_a<Conjugate>(*arg)) {
183  return down_cast<const Conjugate &>(*arg).get_arg();
184  }
185  if (is_a<Sign>(*arg) or is_a<Erf>(*arg) or is_a<Erfc>(*arg)
186  or is_a<Gamma>(*arg) or is_a<LogGamma>(*arg) or is_a<Sin>(*arg)
187  or is_a<Cos>(*arg) or is_a<Tan>(*arg) or is_a<Cot>(*arg)
188  or is_a<Sec>(*arg) or is_a<Csc>(*arg) or is_a<Sinh>(*arg)
189  or is_a<Cosh>(*arg) or is_a<Tanh>(*arg) or is_a<Coth>(*arg)
190  or is_a<Sech>(*arg) or is_a<Csch>(*arg)) {
191  const OneArgFunction &func = down_cast<const OneArgFunction &>(*arg);
192  return func.create(conjugate(func.get_arg()));
193  }
194  if (is_a<ATan2>(*arg) or is_a<LowerGamma>(*arg) or is_a<UpperGamma>(*arg)
195  or is_a<Beta>(*arg)) {
196  const TwoArgFunction &func = down_cast<const TwoArgFunction &>(*arg);
197  return func.create(conjugate(func.get_arg1()),
198  conjugate(func.get_arg2()));
199  }
200  return make_rcp<const Conjugate>(arg);
201 }
202 
203 bool get_pi_shift(const RCP<const Basic> &arg, const Ptr<RCP<const Number>> &n,
204  const Ptr<RCP<const Basic>> &x)
205 {
206  if (is_a<Add>(*arg)) {
207  const Add &s = down_cast<const Add &>(*arg);
208  RCP<const Basic> coef = s.get_coef();
209  auto size = s.get_dict().size();
210  if (size > 1) {
211  // arg should be of form `x + n*pi`
212  // `n` is an integer
213  // `x` is an `Expression`
214  bool check_pi = false;
215  RCP<const Basic> temp;
216  *x = coef;
217  for (const auto &p : s.get_dict()) {
218  if (eq(*p.first, *pi)
219  and (is_a<Integer>(*p.second)
220  or is_a<Rational>(*p.second))) {
221  check_pi = true;
222  *n = p.second;
223  } else {
224  *x = add(mul(p.first, p.second), *x);
225  }
226  }
227  if (check_pi)
228  return true;
229  else // No term with `pi` found
230  return false;
231  } else if (size == 1) {
232  // arg should be of form `a + n*pi`
233  // where `a` is a `Number`.
234  auto p = s.get_dict().begin();
235  if (eq(*p->first, *pi)
236  and (is_a<Integer>(*p->second) or is_a<Rational>(*p->second))) {
237  *n = p->second;
238  *x = coef;
239  return true;
240  } else {
241  return false;
242  }
243  } else { // Should never reach here though!
244  // Dict of size < 1
245  return false;
246  }
247  } else if (is_a<Mul>(*arg)) {
248  // `arg` is of the form `k*pi/12`
249  const Mul &s = down_cast<const Mul &>(*arg);
250  auto p = s.get_dict().begin();
251  // dict should contain symbol `pi` only
252  if (s.get_dict().size() == 1 and eq(*p->first, *pi)
253  and eq(*p->second, *one)
254  and (is_a<Integer>(*s.get_coef())
255  or is_a<Rational>(*s.get_coef()))) {
256  *n = s.get_coef();
257  *x = zero;
258  return true;
259  } else {
260  return false;
261  }
262  } else if (eq(*arg, *pi)) {
263  *n = one;
264  *x = zero;
265  return true;
266  } else if (eq(*arg, *zero)) {
267  *n = zero;
268  *x = zero;
269  return true;
270  } else {
271  return false;
272  }
273 }
274 
275 // Return true if arg is of form a+b*pi, with b integer or rational
276 // with denominator 2. The a may be zero or any expression.
277 bool trig_has_basic_shift(const RCP<const Basic> &arg)
278 {
279  if (is_a<Add>(*arg)) {
280  const Add &s = down_cast<const Add &>(*arg);
281  for (const auto &p : s.get_dict()) {
282  const auto &temp = mul(p.second, integer(2));
283  if (eq(*p.first, *pi)) {
284  if (is_a<Integer>(*temp)) {
285  return true;
286  }
287  if (is_a<Rational>(*temp)) {
288  auto m = down_cast<const Rational &>(*temp)
289  .as_rational_class();
290  return (m < 0) or (m > 1);
291  }
292  return false;
293  }
294  }
295  return false;
296  } else if (is_a<Mul>(*arg)) {
297  // is `arg` of the form `k*pi/2`?
298  // dict should contain symbol `pi` only
299  // and `k` should be a rational s.t. 0 < k < 1
300  const Mul &s = down_cast<const Mul &>(*arg);
301  RCP<const Basic> coef = mul(s.get_coef(), integer(2));
302  auto p = s.get_dict().begin();
303  if (s.get_dict().size() == 1 and eq(*p->first, *pi)
304  and eq(*p->second, *one)) {
305  if (is_a<Integer>(*coef)) {
306  return true;
307  }
308  if (is_a<Rational>(*coef)) {
309  auto m = down_cast<const Rational &>(*coef).as_rational_class();
310  return (m < 0) or (m > 1);
311  }
312  return false;
313  } else {
314  return false;
315  }
316  } else if (eq(*arg, *pi)) {
317  return true;
318  } else if (eq(*arg, *zero)) {
319  return true;
320  } else {
321  return false;
322  }
323 }
324 
325 bool could_extract_minus(const Basic &arg)
326 {
327  if (is_a_Number(arg)) {
328  if (down_cast<const Number &>(arg).is_negative()) {
329  return true;
330  } else if (is_a_Complex(arg)) {
331  const ComplexBase &c = down_cast<const ComplexBase &>(arg);
332  RCP<const Number> real_part = c.real_part();
333  return (real_part->is_negative())
334  or (eq(*real_part, *zero)
335  and c.imaginary_part()->is_negative());
336  } else {
337  return false;
338  }
339  } else if (is_a<Mul>(arg)) {
340  const Mul &s = down_cast<const Mul &>(arg);
341  return could_extract_minus(*s.get_coef());
342  } else if (is_a<Add>(arg)) {
343  const Add &s = down_cast<const Add &>(arg);
344  if (s.get_coef()->is_zero()) {
345  map_basic_num d(s.get_dict().begin(), s.get_dict().end());
346  return could_extract_minus(*d.begin()->second);
347  } else {
348  return could_extract_minus(*s.get_coef());
349  }
350  } else {
351  return false;
352  }
353 }
354 
355 bool handle_minus(const RCP<const Basic> &arg,
356  const Ptr<RCP<const Basic>> &rarg)
357 {
358  if (is_a<Mul>(*arg)) {
359  const Mul &s = down_cast<const Mul &>(*arg);
360  // Check for -Add instances to transform -(-x + 2*y) to (x - 2*y)
361  if (s.get_coef()->is_minus_one() && s.get_dict().size() == 1
362  && eq(*s.get_dict().begin()->second, *one)) {
363  return not handle_minus(mul(minus_one, arg), rarg);
364  } else if (could_extract_minus(*s.get_coef())) {
365  *rarg = mul(minus_one, arg);
366  return true;
367  }
368  } else if (is_a<Add>(*arg)) {
369  if (could_extract_minus(*arg)) {
370  const Add &s = down_cast<const Add &>(*arg);
371  umap_basic_num d = s.get_dict();
372  for (auto &p : d) {
373  p.second = p.second->mul(*minus_one);
374  }
375  *rarg = Add::from_dict(s.get_coef()->mul(*minus_one), std::move(d));
376  return true;
377  }
378  } else if (could_extract_minus(*arg)) {
379  *rarg = mul(minus_one, arg);
380  return true;
381  }
382  *rarg = arg;
383  return false;
384 }
385 
386 // \return true if conjugate has to be returned finally else false
387 bool trig_simplify(const RCP<const Basic> &arg, unsigned period, bool odd,
388  bool conj_odd, // input
389  const Ptr<RCP<const Basic>> &rarg, int &index,
390  int &sign) // output
391 {
392  bool check;
393  RCP<const Number> n;
394  RCP<const Basic> r;
395  RCP<const Basic> ret_arg;
396  check = get_pi_shift(arg, outArg(n), outArg(r));
397  if (check) {
398  RCP<const Number> t = mulnum(n, integer(12));
399  sign = 1;
400  if (is_a<Integer>(*t)) {
401  int m = numeric_cast<int>(
402  mod_f(down_cast<const Integer &>(*t), *integer(12 * period))
403  ->as_int());
404  if (eq(*r, *zero)) {
405  index = m;
406  *rarg = zero;
407  return false;
408  } else if (m == 0) {
409  index = 0;
410  bool b = handle_minus(r, outArg(ret_arg));
411  *rarg = ret_arg;
412  if (odd and b)
413  sign = -1;
414  return false;
415  }
416  }
417 
418  rational_class m;
419  if (is_a<Integer>(*n)) {
420  // 2*pi periodic => f(r + pi * n) = f(r - pi * n)
421  m = mp_abs(down_cast<const Integer &>(*n).as_integer_class());
422  m /= period;
423  } else {
424  SYMENGINE_ASSERT(is_a<Rational>(*n));
425  m = down_cast<const Rational &>(*n).as_rational_class() / period;
426  integer_class t;
427 #if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
428  mp_fdiv_r(t, get_num(m), get_den(m));
429  get_num(m) = t;
430 #else
431  integer_class quo;
432  mp_fdiv_qr(quo, t, get_num(m), get_den(m));
433  m -= rational_class(quo);
434 #endif
435  // m = a / b => m = (a % b / b)
436  }
437  // Now, arg = r + 2 * pi * m where 0 <= m < 1
438  m *= 2 * period;
439  // Now, arg = r + pi * m / 2 where 0 <= m < 4
440  if (m >= 2 and m < 3) {
441  sign = -1;
442  r = add(r, mul(pi, Rational::from_mpq((m - 2) / 2)));
443  bool b = handle_minus(r, outArg(ret_arg));
444  *rarg = ret_arg;
445  if (odd and b)
446  sign = -1 * sign;
447  return false;
448  } else if (m >= 1) {
449  if (m < 2) {
450  // 1 <= m < 2
451  sign = 1;
452  r = add(r, mul(pi, Rational::from_mpq((m - 1) / 2)));
453  } else {
454  // 3 <= m < 4
455  sign = -1;
456  r = add(r, mul(pi, Rational::from_mpq((m - 3) / 2)));
457  }
458  bool b = handle_minus(r, outArg(ret_arg));
459  *rarg = ret_arg;
460  if (not b and conj_odd)
461  sign = -sign;
462  return true;
463  } else {
464  *rarg = add(r, mul(pi, Rational::from_mpq(m / 2)));
465  index = -1;
466  return false;
467  }
468  } else {
469  bool b = handle_minus(arg, outArg(ret_arg));
470  *rarg = ret_arg;
471  index = -1;
472  if (odd and b)
473  sign = -1;
474  else
475  sign = 1;
476  return false;
477  }
478 }
479 
480 bool inverse_lookup(const umap_basic_basic &d, const RCP<const Basic> &t,
481  const Ptr<RCP<const Basic>> &index)
482 {
483  auto it = d.find(t);
484  if (it == d.end()) {
485  // Not found in lookup
486  return false;
487  } else {
488  *index = (it->second);
489  return true;
490  }
491 }
492 
493 Sign::Sign(const RCP<const Basic> &arg) : OneArgFunction(arg)
494 {
495  SYMENGINE_ASSIGN_TYPEID()
496  SYMENGINE_ASSERT(is_canonical(arg))
497 }
498 
499 bool Sign::is_canonical(const RCP<const Basic> &arg) const
500 {
501  if (is_a_Number(*arg)) {
502  if (eq(*arg, *ComplexInf)) {
503  return true;
504  }
505  return false;
506  }
507  if (is_a<Constant>(*arg)) {
508  return false;
509  }
510  if (is_a<Sign>(*arg)) {
511  return false;
512  }
513  if (is_a<Mul>(*arg)) {
514  if (neq(*down_cast<const Mul &>(*arg).get_coef(), *one)
515  and neq(*down_cast<const Mul &>(*arg).get_coef(), *minus_one)) {
516  return false;
517  }
518  }
519  return true;
520 }
521 
522 RCP<const Basic> Sign::create(const RCP<const Basic> &arg) const
523 {
524  return sign(arg);
525 }
526 
527 RCP<const Basic> sign(const RCP<const Basic> &arg)
528 {
529  if (is_a_Number(*arg)) {
530  if (is_a<NaN>(*arg)) {
531  return Nan;
532  }
533  if (down_cast<const Number &>(*arg).is_zero()) {
534  return zero;
535  }
536  if (down_cast<const Number &>(*arg).is_positive()) {
537  return one;
538  }
539  if (down_cast<const Number &>(*arg).is_negative()) {
540  return minus_one;
541  }
542  if (is_a_Complex(*arg)
543  and down_cast<const ComplexBase &>(*arg).is_re_zero()) {
544  RCP<const Number> r
545  = down_cast<const ComplexBase &>(*arg).imaginary_part();
546  if (down_cast<const Number &>(*r).is_positive()) {
547  return I;
548  }
549  if (down_cast<const Number &>(*r).is_negative()) {
550  return mul(minus_one, I);
551  }
552  }
553  }
554  if (is_a<Constant>(*arg)) {
555  if (eq(*arg, *pi) or eq(*arg, *E) or eq(*arg, *EulerGamma)
556  or eq(*arg, *Catalan) or eq(*arg, *GoldenRatio))
557  return one;
558  }
559  if (is_a<Sign>(*arg)) {
560  return arg;
561  }
562  if (is_a<Mul>(*arg)) {
563  RCP<const Basic> s = sign(down_cast<const Mul &>(*arg).get_coef());
564  map_basic_basic dict = down_cast<const Mul &>(*arg).get_dict();
565  return mul(s,
566  make_rcp<const Sign>(Mul::from_dict(one, std::move(dict))));
567  }
568  return make_rcp<const Sign>(arg);
569 }
570 
571 Floor::Floor(const RCP<const Basic> &arg) : OneArgFunction(arg)
572 {
573  SYMENGINE_ASSIGN_TYPEID()
574  SYMENGINE_ASSERT(is_canonical(arg))
575 }
576 
577 bool Floor::is_canonical(const RCP<const Basic> &arg) const
578 {
579  if (is_a_Number(*arg)) {
580  return false;
581  }
582  if (is_a<Constant>(*arg)) {
583  return false;
584  }
585  if (is_a<Floor>(*arg)) {
586  return false;
587  }
588  if (is_a<Ceiling>(*arg)) {
589  return false;
590  }
591  if (is_a<Truncate>(*arg)) {
592  return false;
593  }
594  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
595  return false;
596  }
597  if (is_a<Add>(*arg)) {
598  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
599  if (neq(*zero, *s) and is_a<Integer>(*s)) {
600  return false;
601  }
602  }
603  return true;
604 }
605 
606 RCP<const Basic> Floor::create(const RCP<const Basic> &arg) const
607 {
608  return floor(arg);
609 }
610 
611 RCP<const Basic> floor(const RCP<const Basic> &arg)
612 {
613  if (is_a_Number(*arg)) {
614  if (down_cast<const Number &>(*arg).is_exact()) {
615  if (is_a<Rational>(*arg)) {
616  const Rational &s = down_cast<const Rational &>(*arg);
617  integer_class quotient;
618  mp_fdiv_q(quotient, SymEngine::get_num(s.as_rational_class()),
619  SymEngine::get_den(s.as_rational_class()));
620  return integer(std::move(quotient));
621  }
622  return arg;
623  }
624  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
625  return _arg->get_eval().floor(*_arg);
626  }
627  if (is_a<Constant>(*arg)) {
628  if (eq(*arg, *pi)) {
629  return integer(3);
630  }
631  if (eq(*arg, *E)) {
632  return integer(2);
633  }
634  if (eq(*arg, *GoldenRatio)) {
635  return integer(1);
636  }
637  if (eq(*arg, *Catalan) or eq(*arg, *EulerGamma)) {
638  return integer(0);
639  }
640  }
641  if (is_a<Floor>(*arg)) {
642  return arg;
643  }
644  if (is_a<Ceiling>(*arg)) {
645  return arg;
646  }
647  if (is_a<Truncate>(*arg)) {
648  return arg;
649  }
650  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
651  throw SymEngineException(
652  "Boolean objects not allowed in this context.");
653  }
654  if (is_a<Add>(*arg)) {
655  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
656  umap_basic_num d = down_cast<const Add &>(*arg).get_dict();
657  if (is_a<Integer>(*s)
658  and not down_cast<const Integer &>(*s).is_zero()) {
659  return add(s, floor(Add::from_dict(zero, std::move(d))));
660  }
661  }
662  return make_rcp<const Floor>(arg);
663 }
664 
665 Ceiling::Ceiling(const RCP<const Basic> &arg) : OneArgFunction(arg)
666 {
667  SYMENGINE_ASSIGN_TYPEID()
668  SYMENGINE_ASSERT(is_canonical(arg))
669 }
670 
671 bool Ceiling::is_canonical(const RCP<const Basic> &arg) const
672 {
673  if (is_a_Number(*arg)) {
674  return false;
675  }
676  if (is_a<Constant>(*arg)) {
677  return false;
678  }
679  if (is_a<Floor>(*arg)) {
680  return false;
681  }
682  if (is_a<Ceiling>(*arg)) {
683  return false;
684  }
685  if (is_a<Truncate>(*arg)) {
686  return false;
687  }
688  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
689  return false;
690  }
691  if (is_a<Add>(*arg)) {
692  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
693  if (neq(*zero, *s) and is_a<Integer>(*s)) {
694  return false;
695  }
696  }
697  return true;
698 }
699 
700 RCP<const Basic> Ceiling::create(const RCP<const Basic> &arg) const
701 {
702  return ceiling(arg);
703 }
704 
705 RCP<const Basic> ceiling(const RCP<const Basic> &arg)
706 {
707  if (is_a_Number(*arg)) {
708  if (down_cast<const Number &>(*arg).is_exact()) {
709  if (is_a<Rational>(*arg)) {
710  const Rational &s = down_cast<const Rational &>(*arg);
711  integer_class quotient;
712  mp_cdiv_q(quotient, SymEngine::get_num(s.as_rational_class()),
713  SymEngine::get_den(s.as_rational_class()));
714  return integer(std::move(quotient));
715  }
716  return arg;
717  }
718  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
719  return _arg->get_eval().ceiling(*_arg);
720  }
721  if (is_a<Constant>(*arg)) {
722  if (eq(*arg, *pi)) {
723  return integer(4);
724  }
725  if (eq(*arg, *E)) {
726  return integer(3);
727  }
728  if (eq(*arg, *GoldenRatio)) {
729  return integer(2);
730  }
731  if (eq(*arg, *Catalan) or eq(*arg, *EulerGamma)) {
732  return integer(1);
733  }
734  }
735  if (is_a<Floor>(*arg)) {
736  return arg;
737  }
738  if (is_a<Ceiling>(*arg)) {
739  return arg;
740  }
741  if (is_a<Truncate>(*arg)) {
742  return arg;
743  }
744  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
745  throw SymEngineException(
746  "Boolean objects not allowed in this context.");
747  }
748  if (is_a<Add>(*arg)) {
749  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
750  umap_basic_num d = down_cast<const Add &>(*arg).get_dict();
751  if (is_a<Integer>(*s)) {
752  return add(
753  s, make_rcp<const Ceiling>(Add::from_dict(zero, std::move(d))));
754  }
755  }
756  return make_rcp<const Ceiling>(arg);
757 }
758 
759 Truncate::Truncate(const RCP<const Basic> &arg) : OneArgFunction(arg)
760 {
761  SYMENGINE_ASSIGN_TYPEID()
762  SYMENGINE_ASSERT(is_canonical(arg))
763 }
764 
765 bool Truncate::is_canonical(const RCP<const Basic> &arg) const
766 {
767  if (is_a_Number(*arg)) {
768  return false;
769  }
770  if (is_a<Constant>(*arg)) {
771  return false;
772  }
773  if (is_a<Floor>(*arg)) {
774  return false;
775  }
776  if (is_a<Ceiling>(*arg)) {
777  return false;
778  }
779  if (is_a<Truncate>(*arg)) {
780  return false;
781  }
782  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
783  return false;
784  }
785  if (is_a<Add>(*arg)) {
786  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
787  if (neq(*zero, *s) and is_a<Integer>(*s)) {
788  return false;
789  }
790  }
791  return true;
792 }
793 
794 RCP<const Basic> Truncate::create(const RCP<const Basic> &arg) const
795 {
796  return truncate(arg);
797 }
798 
799 RCP<const Basic> truncate(const RCP<const Basic> &arg)
800 {
801  if (is_a_Number(*arg)) {
802  if (down_cast<const Number &>(*arg).is_exact()) {
803  if (is_a<Rational>(*arg)) {
804  const Rational &s = down_cast<const Rational &>(*arg);
805  integer_class quotient;
806  mp_tdiv_q(quotient, SymEngine::get_num(s.as_rational_class()),
807  SymEngine::get_den(s.as_rational_class()));
808  return integer(std::move(quotient));
809  }
810  return arg;
811  }
812  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
813  return _arg->get_eval().truncate(*_arg);
814  }
815  if (is_a<Constant>(*arg)) {
816  if (eq(*arg, *pi)) {
817  return integer(3);
818  }
819  if (eq(*arg, *E)) {
820  return integer(2);
821  }
822  if (eq(*arg, *GoldenRatio)) {
823  return integer(1);
824  }
825  if (eq(*arg, *Catalan) or eq(*arg, *EulerGamma)) {
826  return integer(0);
827  }
828  }
829  if (is_a<Floor>(*arg)) {
830  return arg;
831  }
832  if (is_a<Ceiling>(*arg)) {
833  return arg;
834  }
835  if (is_a<Truncate>(*arg)) {
836  return arg;
837  }
838  if (is_a<BooleanAtom>(*arg) or is_a_Relational(*arg)) {
839  throw SymEngineException(
840  "Boolean objects not allowed in this context.");
841  }
842  if (is_a<Add>(*arg)) {
843  RCP<const Number> s = down_cast<const Add &>(*arg).get_coef();
844  umap_basic_num d = down_cast<const Add &>(*arg).get_dict();
845  if (is_a<Integer>(*s)) {
846  return add(s, make_rcp<const Truncate>(
847  Add::from_dict(zero, std::move(d))));
848  }
849  }
850  return make_rcp<const Truncate>(arg);
851 }
852 
853 Sin::Sin(const RCP<const Basic> &arg) : TrigFunction(arg)
854 {
855  SYMENGINE_ASSIGN_TYPEID()
856  SYMENGINE_ASSERT(is_canonical(arg))
857 }
858 
859 bool Sin::is_canonical(const RCP<const Basic> &arg) const
860 {
861  // e.g. sin(0)
862  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
863  return false;
864  // e.g sin(7*pi/2+y)
865  if (trig_has_basic_shift(arg)) {
866  return false;
867  }
868  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
869  return false;
870  }
871  return true;
872 }
873 
874 RCP<const Basic> sin(const RCP<const Basic> &arg)
875 {
876  if (eq(*arg, *zero))
877  return zero;
878  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
879  return down_cast<const Number &>(*arg).get_eval().sin(*arg);
880  }
881 
882  if (is_a<ASin>(*arg)) {
883  return down_cast<const ASin &>(*arg).get_arg();
884  } else if (is_a<ACsc>(*arg)) {
885  return div(one, down_cast<const ACsc &>(*arg).get_arg());
886  }
887 
888  RCP<const Basic> ret_arg;
889  int index, sign;
890  bool conjugate = trig_simplify(arg, 2, true, false, // input
891  outArg(ret_arg), index, sign); // output
892 
893  if (conjugate) {
894  // cos has to be returned
895  if (sign == 1) {
896  return cos(ret_arg);
897  } else {
898  return mul(minus_one, cos(ret_arg));
899  }
900  } else {
901  if (eq(*ret_arg, *zero)) {
902  return mul(integer(sign), sin_table()[index]);
903  } else {
904  // If ret_arg is the same as arg, a `Sin` instance is returned
905  // Or else `sin` is called again.
906  if (sign == 1) {
907  if (neq(*ret_arg, *arg)) {
908  return sin(ret_arg);
909  } else {
910  return make_rcp<const Sin>(arg);
911  }
912  } else {
913  return mul(minus_one, sin(ret_arg));
914  }
915  }
916  }
917 }
918 
919 /* ---------------------------- */
920 
921 Cos::Cos(const RCP<const Basic> &arg) : TrigFunction(arg)
922 {
923  SYMENGINE_ASSIGN_TYPEID()
924  SYMENGINE_ASSERT(is_canonical(arg))
925 }
926 
927 bool Cos::is_canonical(const RCP<const Basic> &arg) const
928 {
929  // e.g. cos(0)
930  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
931  return false;
932  // e.g cos(k*pi/2)
933  if (trig_has_basic_shift(arg)) {
934  return false;
935  }
936  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
937  return false;
938  }
939  return true;
940 }
941 
942 RCP<const Basic> cos(const RCP<const Basic> &arg)
943 {
944  if (eq(*arg, *zero))
945  return one;
946  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
947  return down_cast<const Number &>(*arg).get_eval().cos(*arg);
948  }
949 
950  if (is_a<ACos>(*arg)) {
951  return down_cast<const ACos &>(*arg).get_arg();
952  } else if (is_a<ASec>(*arg)) {
953  return div(one, down_cast<const ASec &>(*arg).get_arg());
954  }
955 
956  RCP<const Basic> ret_arg;
957  int index, sign;
958  bool conjugate = trig_simplify(arg, 2, false, true, // input
959  outArg(ret_arg), index, sign); // output
960 
961  if (conjugate) {
962  // sin has to be returned
963  if (sign == 1) {
964  return sin(ret_arg);
965  } else {
966  return mul(minus_one, sin(ret_arg));
967  }
968  } else {
969  if (eq(*ret_arg, *zero)) {
970  return mul(integer(sign), sin_table()[(index + 6) % 24]);
971  } else {
972  if (sign == 1) {
973  if (neq(*ret_arg, *arg)) {
974  return cos(ret_arg);
975  } else {
976  return make_rcp<const Cos>(ret_arg);
977  }
978  } else {
979  return mul(minus_one, cos(ret_arg));
980  }
981  }
982  }
983 }
984 
985 /* ---------------------------- */
986 
987 Tan::Tan(const RCP<const Basic> &arg) : TrigFunction(arg)
988 {
989  SYMENGINE_ASSIGN_TYPEID()
990  SYMENGINE_ASSERT(is_canonical(arg))
991 }
992 
993 bool Tan::is_canonical(const RCP<const Basic> &arg) const
994 {
995  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
996  return false;
997  // e.g tan(k*pi/2)
998  if (trig_has_basic_shift(arg)) {
999  return false;
1000  }
1001  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1002  return false;
1003  }
1004  return true;
1005 }
1006 
1007 RCP<const Basic> tan(const RCP<const Basic> &arg)
1008 {
1009  if (eq(*arg, *zero))
1010  return zero;
1011  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1012  return down_cast<const Number &>(*arg).get_eval().tan(*arg);
1013  }
1014 
1015  if (is_a<ATan>(*arg)) {
1016  return down_cast<const ATan &>(*arg).get_arg();
1017  } else if (is_a<ACot>(*arg)) {
1018  return div(one, down_cast<const ACot &>(*arg).get_arg());
1019  }
1020 
1021  RCP<const Basic> ret_arg;
1022  int index, sign;
1023  bool conjugate = trig_simplify(arg, 1, true, true, // input
1024  outArg(ret_arg), index, sign); // output
1025 
1026  if (conjugate) {
1027  // cot has to be returned
1028  if (sign == 1) {
1029  return cot(ret_arg);
1030  } else {
1031  return mul(minus_one, cot(ret_arg));
1032  }
1033  } else {
1034  if (eq(*ret_arg, *zero)) {
1035  return mul(integer(sign),
1036  div(sin_table()[index], sin_table()[(index + 6) % 24]));
1037  } else {
1038  if (sign == 1) {
1039  if (neq(*ret_arg, *arg)) {
1040  return tan(ret_arg);
1041  } else {
1042  return make_rcp<const Tan>(ret_arg);
1043  }
1044  } else {
1045  return mul(minus_one, tan(ret_arg));
1046  }
1047  }
1048  }
1049 }
1050 
1051 /* ---------------------------- */
1052 
1053 Cot::Cot(const RCP<const Basic> &arg) : TrigFunction(arg)
1054 {
1055  SYMENGINE_ASSIGN_TYPEID()
1056  SYMENGINE_ASSERT(is_canonical(arg))
1057 }
1058 
1059 bool Cot::is_canonical(const RCP<const Basic> &arg) const
1060 {
1061  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
1062  return false;
1063  // e.g cot(k*pi/2)
1064  if (trig_has_basic_shift(arg)) {
1065  return false;
1066  }
1067  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1068  return false;
1069  }
1070  return true;
1071 }
1072 
1073 RCP<const Basic> cot(const RCP<const Basic> &arg)
1074 {
1075  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1076  return down_cast<const Number &>(*arg).get_eval().cot(*arg);
1077  }
1078 
1079  if (is_a<ACot>(*arg)) {
1080  return down_cast<const ACot &>(*arg).get_arg();
1081  } else if (is_a<ATan>(*arg)) {
1082  return div(one, down_cast<const ATan &>(*arg).get_arg());
1083  }
1084 
1085  RCP<const Basic> ret_arg;
1086  int index, sign;
1087  bool conjugate = trig_simplify(arg, 1, true, true, // input
1088  outArg(ret_arg), index, sign); // output
1089 
1090  if (conjugate) {
1091  // tan has to be returned
1092  if (sign == 1) {
1093  return tan(ret_arg);
1094  } else {
1095  return mul(minus_one, tan(ret_arg));
1096  }
1097  } else {
1098  if (eq(*ret_arg, *zero)) {
1099  return mul(integer(sign),
1100  div(sin_table()[(index + 6) % 24], sin_table()[index]));
1101  } else {
1102  if (sign == 1) {
1103  if (neq(*ret_arg, *arg)) {
1104  return cot(ret_arg);
1105  } else {
1106  return make_rcp<const Cot>(ret_arg);
1107  }
1108  } else {
1109  return mul(minus_one, cot(ret_arg));
1110  }
1111  }
1112  }
1113 }
1114 
1115 /* ---------------------------- */
1116 
1117 Csc::Csc(const RCP<const Basic> &arg) : TrigFunction(arg)
1118 {
1119  SYMENGINE_ASSIGN_TYPEID()
1120  SYMENGINE_ASSERT(is_canonical(arg))
1121 }
1122 
1123 bool Csc::is_canonical(const RCP<const Basic> &arg) const
1124 {
1125  // e.g. Csc(0)
1126  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
1127  return false;
1128  // e.g csc(k*pi/2)
1129  if (trig_has_basic_shift(arg)) {
1130  return false;
1131  }
1132  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1133  return false;
1134  }
1135  return true;
1136 }
1137 
1138 RCP<const Basic> csc(const RCP<const Basic> &arg)
1139 {
1140  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1141  return down_cast<const Number &>(*arg).get_eval().csc(*arg);
1142  }
1143 
1144  if (is_a<ACsc>(*arg)) {
1145  return down_cast<const ACsc &>(*arg).get_arg();
1146  } else if (is_a<ASin>(*arg)) {
1147  return div(one, down_cast<const ASin &>(*arg).get_arg());
1148  }
1149 
1150  RCP<const Basic> ret_arg;
1151  int index, sign;
1152  bool conjugate = trig_simplify(arg, 2, true, false, // input
1153  outArg(ret_arg), index, sign); // output
1154 
1155  if (conjugate) {
1156  // cos has to be returned
1157  if (sign == 1) {
1158  return sec(ret_arg);
1159  } else {
1160  return mul(minus_one, sec(ret_arg));
1161  }
1162  } else {
1163  if (eq(*ret_arg, *zero)) {
1164  return mul(integer(sign), div(one, sin_table()[index]));
1165  } else {
1166  if (sign == 1) {
1167  if (neq(*ret_arg, *arg)) {
1168  return csc(ret_arg);
1169  } else {
1170  return make_rcp<const Csc>(ret_arg);
1171  }
1172  } else {
1173  return mul(minus_one, csc(ret_arg));
1174  }
1175  }
1176  }
1177 }
1178 
1179 /* ---------------------------- */
1180 
1181 Sec::Sec(const RCP<const Basic> &arg) : TrigFunction(arg)
1182 {
1183  SYMENGINE_ASSIGN_TYPEID()
1184  SYMENGINE_ASSERT(is_canonical(arg))
1185 }
1186 
1187 bool Sec::is_canonical(const RCP<const Basic> &arg) const
1188 {
1189  // e.g. Sec(0)
1190  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
1191  return false;
1192  // e.g sec(k*pi/2)
1193  if (trig_has_basic_shift(arg)) {
1194  return false;
1195  }
1196  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1197  return false;
1198  }
1199  return true;
1200 }
1201 
1202 RCP<const Basic> sec(const RCP<const Basic> &arg)
1203 {
1204  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1205  return down_cast<const Number &>(*arg).get_eval().sec(*arg);
1206  }
1207 
1208  if (is_a<ASec>(*arg)) {
1209  return down_cast<const ASec &>(*arg).get_arg();
1210  } else if (is_a<ACos>(*arg)) {
1211  return div(one, down_cast<const ACos &>(*arg).get_arg());
1212  }
1213 
1214  RCP<const Basic> ret_arg;
1215  int index, sign;
1216  bool conjugate = trig_simplify(arg, 2, false, true, // input
1217  outArg(ret_arg), index, sign); // output
1218 
1219  if (conjugate) {
1220  // csc has to be returned
1221  if (sign == 1) {
1222  return csc(ret_arg);
1223  } else {
1224  return mul(minus_one, csc(ret_arg));
1225  }
1226  } else {
1227  if (eq(*ret_arg, *zero)) {
1228  return mul(integer(sign), div(one, sin_table()[(index + 6) % 24]));
1229  } else {
1230  if (sign == 1) {
1231  if (neq(*ret_arg, *arg)) {
1232  return sec(ret_arg);
1233  } else {
1234  return make_rcp<const Sec>(ret_arg);
1235  }
1236  } else {
1237  return mul(minus_one, sec(ret_arg));
1238  }
1239  }
1240  }
1241 }
1242 /* ---------------------------- */
1243 
1244 // simplifies trigonometric functions wherever possible
1245 // currently deals with simplifications of type sin(acos())
1246 RCP<const Basic> trig_to_sqrt(const RCP<const Basic> &arg)
1247 {
1248  RCP<const Basic> i_arg;
1249 
1250  if (is_a<Sin>(*arg)) {
1251  if (is_a<ACos>(*arg->get_args()[0])) {
1252  i_arg = down_cast<const ACos &>(*(arg->get_args()[0])).get_arg();
1253  return sqrt(sub(one, pow(i_arg, i2)));
1254  } else if (is_a<ATan>(*arg->get_args()[0])) {
1255  i_arg = down_cast<const ATan &>(*(arg->get_args()[0])).get_arg();
1256  return div(i_arg, sqrt(add(one, pow(i_arg, i2))));
1257  } else if (is_a<ASec>(*arg->get_args()[0])) {
1258  i_arg = down_cast<const ASec &>(*(arg->get_args()[0])).get_arg();
1259  return sqrt(sub(one, pow(i_arg, im2)));
1260  } else if (is_a<ACot>(*arg->get_args()[0])) {
1261  i_arg = down_cast<const ACot &>(*(arg->get_args()[0])).get_arg();
1262  return div(one, mul(i_arg, sqrt(add(one, pow(i_arg, im2)))));
1263  }
1264  } else if (is_a<Cos>(*arg)) {
1265  if (is_a<ASin>(*arg->get_args()[0])) {
1266  i_arg = down_cast<const ASin &>(*(arg->get_args()[0])).get_arg();
1267  return sqrt(sub(one, pow(i_arg, i2)));
1268  } else if (is_a<ATan>(*arg->get_args()[0])) {
1269  i_arg = down_cast<const ATan &>(*(arg->get_args()[0])).get_arg();
1270  return div(one, sqrt(add(one, pow(i_arg, i2))));
1271  } else if (is_a<ACsc>(*arg->get_args()[0])) {
1272  i_arg = down_cast<const ACsc &>(*(arg->get_args()[0])).get_arg();
1273  return sqrt(sub(one, pow(i_arg, im2)));
1274  } else if (is_a<ACot>(*arg->get_args()[0])) {
1275  i_arg = down_cast<const ACot &>(*(arg->get_args()[0])).get_arg();
1276  return div(one, sqrt(add(one, pow(i_arg, im2))));
1277  }
1278  } else if (is_a<Tan>(*arg)) {
1279  if (is_a<ASin>(*arg->get_args()[0])) {
1280  i_arg = down_cast<const ASin &>(*(arg->get_args()[0])).get_arg();
1281  return div(i_arg, sqrt(sub(one, pow(i_arg, i2))));
1282  } else if (is_a<ACos>(*arg->get_args()[0])) {
1283  i_arg = down_cast<const ACos &>(*(arg->get_args()[0])).get_arg();
1284  return div(sqrt(sub(one, pow(i_arg, i2))), i_arg);
1285  } else if (is_a<ACsc>(*arg->get_args()[0])) {
1286  i_arg = down_cast<const ACsc &>(*(arg->get_args()[0])).get_arg();
1287  return div(one, mul(i_arg, sqrt(sub(one, pow(i_arg, im2)))));
1288  } else if (is_a<ASec>(*arg->get_args()[0])) {
1289  i_arg = down_cast<const ASec &>(*(arg->get_args()[0])).get_arg();
1290  return mul(i_arg, sqrt(sub(one, pow(i_arg, im2))));
1291  }
1292  } else if (is_a<Csc>(*arg)) {
1293  if (is_a<ACos>(*arg->get_args()[0])) {
1294  i_arg = down_cast<const ACos &>(*(arg->get_args()[0])).get_arg();
1295  return div(one, sqrt(sub(one, pow(i_arg, i2))));
1296  } else if (is_a<ATan>(*arg->get_args()[0])) {
1297  i_arg = down_cast<const ATan &>(*(arg->get_args()[0])).get_arg();
1298  return div(sqrt(add(one, pow(i_arg, i2))), i_arg);
1299  } else if (is_a<ASec>(*arg->get_args()[0])) {
1300  i_arg = down_cast<const ASec &>(*(arg->get_args()[0])).get_arg();
1301  return div(one, sqrt(sub(one, pow(i_arg, im2))));
1302  } else if (is_a<ACot>(*arg->get_args()[0])) {
1303  i_arg = down_cast<const ACot &>(*(arg->get_args()[0])).get_arg();
1304  return mul(i_arg, sqrt(add(one, pow(i_arg, im2))));
1305  }
1306  } else if (is_a<Sec>(*arg)) {
1307  if (is_a<ASin>(*arg->get_args()[0])) {
1308  i_arg = down_cast<const ASin &>(*(arg->get_args()[0])).get_arg();
1309  return div(one, sqrt(sub(one, pow(i_arg, i2))));
1310  } else if (is_a<ATan>(*arg->get_args()[0])) {
1311  i_arg = down_cast<const ATan &>(*(arg->get_args()[0])).get_arg();
1312  return sqrt(add(one, pow(i_arg, i2)));
1313  } else if (is_a<ACsc>(*arg->get_args()[0])) {
1314  i_arg = down_cast<const ACsc &>(*(arg->get_args()[0])).get_arg();
1315  return div(one, sqrt(sub(one, pow(i_arg, im2))));
1316  } else if (is_a<ACot>(*arg->get_args()[0])) {
1317  i_arg = down_cast<const ACot &>(*(arg->get_args()[0])).get_arg();
1318  return sqrt(add(one, pow(i_arg, im2)));
1319  }
1320  } else if (is_a<Cot>(*arg)) {
1321  if (is_a<ASin>(*arg->get_args()[0])) {
1322  i_arg = down_cast<const ASin &>(*(arg->get_args()[0])).get_arg();
1323  return div(sqrt(sub(one, pow(i_arg, i2))), i_arg);
1324  } else if (is_a<ACos>(*arg->get_args()[0])) {
1325  i_arg = down_cast<const ACos &>(*(arg->get_args()[0])).get_arg();
1326  return div(i_arg, sqrt(sub(one, pow(i_arg, i2))));
1327  } else if (is_a<ACsc>(*arg->get_args()[0])) {
1328  i_arg = down_cast<const ACsc &>(*(arg->get_args()[0])).get_arg();
1329  return mul(i_arg, sqrt(sub(one, pow(i_arg, im2))));
1330  } else if (is_a<ASec>(*arg->get_args()[0])) {
1331  i_arg = down_cast<const ASec &>(*(arg->get_args()[0])).get_arg();
1332  return div(one, mul(i_arg, sqrt(sub(one, pow(i_arg, im2)))));
1333  }
1334  }
1335 
1336  return arg;
1337 }
1338 
1339 /* ---------------------------- */
1340 ASin::ASin(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1341 {
1342  SYMENGINE_ASSIGN_TYPEID()
1343  SYMENGINE_ASSERT(is_canonical(arg))
1344 }
1345 
1346 bool ASin::is_canonical(const RCP<const Basic> &arg) const
1347 {
1348  if (eq(*arg, *zero) or eq(*arg, *one) or eq(*arg, *minus_one))
1349  return false;
1350  RCP<const Basic> index;
1351  if (inverse_lookup(inverse_cst(), get_arg(), outArg(index))) {
1352  return false;
1353  }
1354  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1355  return false;
1356  }
1357  return true;
1358 }
1359 
1360 RCP<const Basic> asin(const RCP<const Basic> &arg)
1361 {
1362  if (eq(*arg, *zero))
1363  return zero;
1364  else if (eq(*arg, *one))
1365  return div(pi, i2);
1366  else if (eq(*arg, *minus_one))
1367  return mul(minus_one, div(pi, i2));
1368  else if (is_a_Number(*arg)
1369  and not down_cast<const Number &>(*arg).is_exact()) {
1370  return down_cast<const Number &>(*arg).get_eval().asin(*arg);
1371  }
1372 
1373  RCP<const Basic> index;
1374  bool b = inverse_lookup(inverse_cst(), arg, outArg(index));
1375  if (b) {
1376  return div(pi, index);
1377  } else {
1378  return make_rcp<const ASin>(arg);
1379  }
1380 }
1381 
1382 ACos::ACos(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1383 {
1384  SYMENGINE_ASSIGN_TYPEID()
1385  SYMENGINE_ASSERT(is_canonical(arg))
1386 }
1387 
1388 bool ACos::is_canonical(const RCP<const Basic> &arg) const
1389 {
1390  if (eq(*arg, *zero) or eq(*arg, *one) or eq(*arg, *minus_one))
1391  return false;
1392  RCP<const Basic> index;
1393  if (inverse_lookup(inverse_cst(), get_arg(), outArg(index))) {
1394  return false;
1395  }
1396  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1397  return false;
1398  }
1399  return true;
1400 }
1401 
1402 RCP<const Basic> acos(const RCP<const Basic> &arg)
1403 {
1404  if (eq(*arg, *zero))
1405  return div(pi, i2);
1406  else if (eq(*arg, *one))
1407  return zero;
1408  else if (eq(*arg, *minus_one))
1409  return pi;
1410  else if (is_a_Number(*arg)
1411  and not down_cast<const Number &>(*arg).is_exact()) {
1412  return down_cast<const Number &>(*arg).get_eval().acos(*arg);
1413  }
1414 
1415  RCP<const Basic> index;
1416  bool b = inverse_lookup(inverse_cst(), arg, outArg(index));
1417  if (b) {
1418  return sub(div(pi, i2), div(pi, index));
1419  } else {
1420  return make_rcp<const ACos>(arg);
1421  }
1422 }
1423 
1424 ASec::ASec(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1425 {
1426  SYMENGINE_ASSIGN_TYPEID()
1427  SYMENGINE_ASSERT(is_canonical(arg))
1428 }
1429 
1430 bool ASec::is_canonical(const RCP<const Basic> &arg) const
1431 {
1432  if (eq(*arg, *one) or eq(*arg, *minus_one))
1433  return false;
1434  RCP<const Basic> index;
1435  if (inverse_lookup(inverse_cst(), div(one, get_arg()), outArg(index))) {
1436  return false;
1437  } else if (is_a_Number(*arg)
1438  and not down_cast<const Number &>(*arg).is_exact()) {
1439  return false;
1440  }
1441  return true;
1442 }
1443 
1444 RCP<const Basic> asec(const RCP<const Basic> &arg)
1445 {
1446  if (eq(*arg, *one))
1447  return zero;
1448  else if (eq(*arg, *minus_one))
1449  return pi;
1450  else if (is_a_Number(*arg)
1451  and not down_cast<const Number &>(*arg).is_exact()) {
1452  return down_cast<const Number &>(*arg).get_eval().asec(*arg);
1453  }
1454 
1455  RCP<const Basic> index;
1456  bool b = inverse_lookup(inverse_cst(), div(one, arg), outArg(index));
1457  if (b) {
1458  return sub(div(pi, i2), div(pi, index));
1459  } else {
1460  return make_rcp<const ASec>(arg);
1461  }
1462 }
1463 
1464 ACsc::ACsc(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1465 {
1466  SYMENGINE_ASSIGN_TYPEID()
1467  SYMENGINE_ASSERT(is_canonical(arg))
1468 }
1469 
1470 bool ACsc::is_canonical(const RCP<const Basic> &arg) const
1471 {
1472  if (eq(*arg, *one) or eq(*arg, *minus_one))
1473  return false;
1474  RCP<const Basic> index;
1475  if (inverse_lookup(inverse_cst(), div(one, arg), outArg(index))) {
1476  return false;
1477  }
1478  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1479  return false;
1480  }
1481  return true;
1482 }
1483 
1484 RCP<const Basic> acsc(const RCP<const Basic> &arg)
1485 {
1486  if (eq(*arg, *one))
1487  return div(pi, i2);
1488  else if (eq(*arg, *minus_one))
1489  return div(pi, im2);
1490  else if (is_a_Number(*arg)
1491  and not down_cast<const Number &>(*arg).is_exact()) {
1492  return down_cast<const Number &>(*arg).get_eval().acsc(*arg);
1493  }
1494 
1495  RCP<const Basic> index;
1496  bool b = inverse_lookup(inverse_cst(), div(one, arg), outArg(index));
1497  if (b) {
1498  return div(pi, index);
1499  } else {
1500  return make_rcp<const ACsc>(arg);
1501  }
1502 }
1503 
1504 ATan::ATan(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1505 {
1506  SYMENGINE_ASSIGN_TYPEID()
1507  SYMENGINE_ASSERT(is_canonical(arg))
1508 }
1509 
1510 bool ATan::is_canonical(const RCP<const Basic> &arg) const
1511 {
1512  if (eq(*arg, *zero) or eq(*arg, *one) or eq(*arg, *minus_one))
1513  return false;
1514  RCP<const Basic> index;
1515  if (inverse_lookup(inverse_tct(), get_arg(), outArg(index))) {
1516  return false;
1517  }
1518  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1519  return false;
1520  }
1521  return true;
1522 }
1523 
1524 RCP<const Basic> atan(const RCP<const Basic> &arg)
1525 {
1526  if (eq(*arg, *zero))
1527  return zero;
1528  else if (eq(*arg, *one))
1529  return div(pi, mul(i2, i2));
1530  else if (eq(*arg, *minus_one))
1531  return mul(minus_one, div(pi, mul(i2, i2)));
1532  else if (is_a_Number(*arg)
1533  and not down_cast<const Number &>(*arg).is_exact()) {
1534  return down_cast<const Number &>(*arg).get_eval().atan(*arg);
1535  }
1536 
1537  RCP<const Basic> index;
1538  bool b = inverse_lookup(inverse_tct(), arg, outArg(index));
1539  if (b) {
1540  return div(pi, index);
1541  } else {
1542  return make_rcp<const ATan>(arg);
1543  }
1544 }
1545 
1546 ACot::ACot(const RCP<const Basic> &arg) : InverseTrigFunction(arg)
1547 {
1548  SYMENGINE_ASSIGN_TYPEID()
1549  SYMENGINE_ASSERT(is_canonical(arg))
1550 }
1551 
1552 bool ACot::is_canonical(const RCP<const Basic> &arg) const
1553 {
1554  if (eq(*arg, *zero) or eq(*arg, *one) or eq(*arg, *minus_one))
1555  return false;
1556  RCP<const Basic> index;
1557  if (inverse_lookup(inverse_tct(), arg, outArg(index))) {
1558  return false;
1559  }
1560  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
1561  return false;
1562  }
1563  return true;
1564 }
1565 
1566 RCP<const Basic> acot(const RCP<const Basic> &arg)
1567 {
1568  if (eq(*arg, *zero))
1569  return div(pi, i2);
1570  else if (eq(*arg, *one))
1571  return div(pi, mul(i2, i2));
1572  else if (eq(*arg, *minus_one))
1573  return mul(i3, div(pi, mul(i2, i2)));
1574  else if (is_a_Number(*arg)
1575  and not down_cast<const Number &>(*arg).is_exact()) {
1576  return down_cast<const Number &>(*arg).get_eval().acot(*arg);
1577  }
1578 
1579  RCP<const Basic> index;
1580  bool b = inverse_lookup(inverse_tct(), arg, outArg(index));
1581  if (b) {
1582  return sub(div(pi, i2), div(pi, index));
1583  } else {
1584  return make_rcp<const ACot>(arg);
1585  }
1586 }
1587 
1588 ATan2::ATan2(const RCP<const Basic> &num, const RCP<const Basic> &den)
1589  : TwoArgFunction(num, den)
1590 {
1591  SYMENGINE_ASSIGN_TYPEID()
1592  SYMENGINE_ASSERT(is_canonical(num, den))
1593 }
1594 
1595 bool ATan2::is_canonical(const RCP<const Basic> &num,
1596  const RCP<const Basic> &den) const
1597 {
1598  if (eq(*num, *zero) or eq(*num, *den) or eq(*num, *mul(minus_one, den)))
1599  return false;
1600  RCP<const Basic> index;
1601  bool b = inverse_lookup(inverse_tct(), div(num, den), outArg(index));
1602  if (b)
1603  return false;
1604  else
1605  return true;
1606 }
1607 
1608 RCP<const Basic> ATan2::create(const RCP<const Basic> &a,
1609  const RCP<const Basic> &b) const
1610 {
1611  return atan2(a, b);
1612 }
1613 
1614 RCP<const Basic> atan2(const RCP<const Basic> &num, const RCP<const Basic> &den)
1615 {
1616  if (eq(*num, *zero)) {
1617  if (is_a_Number(*den)) {
1618  RCP<const Number> den_new = rcp_static_cast<const Number>(den);
1619  if (den_new->is_negative())
1620  return pi;
1621  else if (den_new->is_positive())
1622  return zero;
1623  else {
1624  return Nan;
1625  }
1626  }
1627  } else if (eq(*den, *zero)) {
1628  if (is_a_Number(*num)) {
1629  RCP<const Number> num_new = rcp_static_cast<const Number>(num);
1630  if (num_new->is_negative())
1631  return div(pi, im2);
1632  else
1633  return div(pi, i2);
1634  }
1635  }
1636  RCP<const Basic> index;
1637  bool b = inverse_lookup(inverse_tct(), div(num, den), outArg(index));
1638  if (b) {
1639  // Ideally the answer should depend on the signs of `num` and `den`
1640  // Currently is_positive() and is_negative() is not implemented for
1641  // types other than `Number`
1642  // Hence this will give exact answers in case when num and den are
1643  // numbers in SymEngine sense and when num and den are positive.
1644  // for the remaining cases in which we just return the value from
1645  // the lookup table.
1646  // TODO: update once is_positive() and is_negative() is implemented
1647  // in `Basic`
1648  if (is_a_Number(*den) and is_a_Number(*num)) {
1649  RCP<const Number> den_new = rcp_static_cast<const Number>(den);
1650  RCP<const Number> num_new = rcp_static_cast<const Number>(num);
1651 
1652  if (den_new->is_positive()) {
1653  return div(pi, index);
1654  } else if (den_new->is_negative()) {
1655  if (num_new->is_negative()) {
1656  return sub(div(pi, index), pi);
1657  } else {
1658  return add(div(pi, index), pi);
1659  }
1660  } else {
1661  return div(pi, index);
1662  }
1663  } else {
1664  return div(pi, index);
1665  }
1666  } else {
1667  return make_rcp<const ATan2>(num, den);
1668  }
1669 }
1670 
1671 /* ---------------------------- */
1672 
1673 RCP<const Basic> Sin::create(const RCP<const Basic> &arg) const
1674 {
1675  return sin(arg);
1676 }
1677 
1678 RCP<const Basic> Cos::create(const RCP<const Basic> &arg) const
1679 {
1680  return cos(arg);
1681 }
1682 
1683 RCP<const Basic> Tan::create(const RCP<const Basic> &arg) const
1684 {
1685  return tan(arg);
1686 }
1687 
1688 RCP<const Basic> Cot::create(const RCP<const Basic> &arg) const
1689 {
1690  return cot(arg);
1691 }
1692 
1693 RCP<const Basic> Sec::create(const RCP<const Basic> &arg) const
1694 {
1695  return sec(arg);
1696 }
1697 
1698 RCP<const Basic> Csc::create(const RCP<const Basic> &arg) const
1699 {
1700  return csc(arg);
1701 }
1702 
1703 RCP<const Basic> ASin::create(const RCP<const Basic> &arg) const
1704 {
1705  return asin(arg);
1706 }
1707 
1708 RCP<const Basic> ACos::create(const RCP<const Basic> &arg) const
1709 {
1710  return acos(arg);
1711 }
1712 
1713 RCP<const Basic> ATan::create(const RCP<const Basic> &arg) const
1714 {
1715  return atan(arg);
1716 }
1717 
1718 RCP<const Basic> ACot::create(const RCP<const Basic> &arg) const
1719 {
1720  return acot(arg);
1721 }
1722 
1723 RCP<const Basic> ASec::create(const RCP<const Basic> &arg) const
1724 {
1725  return asec(arg);
1726 }
1727 
1728 RCP<const Basic> ACsc::create(const RCP<const Basic> &arg) const
1729 {
1730  return acsc(arg);
1731 }
1732 
1733 /* ---------------------------- */
1734 
1735 Log::Log(const RCP<const Basic> &arg) : OneArgFunction(arg)
1736 {
1737  SYMENGINE_ASSIGN_TYPEID()
1738  SYMENGINE_ASSERT(is_canonical(arg))
1739 }
1740 
1741 bool Log::is_canonical(const RCP<const Basic> &arg) const
1742 {
1743  // log(0)
1744  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
1745  return false;
1746  // log(1)
1747  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_one())
1748  return false;
1749  // log(E)
1750  if (eq(*arg, *E))
1751  return false;
1752 
1753  if (is_a_Number(*arg) and down_cast<const Number &>(*arg).is_negative())
1754  return false;
1755 
1756  // log(Inf) is also handled here.
1757  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact())
1758  return false;
1759 
1760  // log(3I) should be expanded to log(3) + I*pi/2
1761  if (is_a<Complex>(*arg) and down_cast<const Complex &>(*arg).is_re_zero())
1762  return false;
1763  // log(num/den) = log(num) - log(den)
1764  if (is_a<Rational>(*arg))
1765  return false;
1766  return true;
1767 }
1768 
1769 RCP<const Basic> Log::create(const RCP<const Basic> &a) const
1770 {
1771  return log(a);
1772 }
1773 
1774 RCP<const Basic> log(const RCP<const Basic> &arg)
1775 {
1776  if (eq(*arg, *zero))
1777  return ComplexInf;
1778  if (eq(*arg, *one))
1779  return zero;
1780  if (eq(*arg, *E))
1781  return one;
1782 
1783  if (is_a_Number(*arg)) {
1784  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
1785  if (not _arg->is_exact()) {
1786  return _arg->get_eval().log(*_arg);
1787  } else if (_arg->is_negative()) {
1788  return add(log(mul(minus_one, _arg)), mul(pi, I));
1789  }
1790  }
1791 
1792  if (is_a<Rational>(*arg)) {
1793  RCP<const Integer> num, den;
1794  get_num_den(down_cast<const Rational &>(*arg), outArg(num),
1795  outArg(den));
1796  return sub(log(num), log(den));
1797  }
1798 
1799  if (is_a<Complex>(*arg)) {
1800  RCP<const Complex> _arg = rcp_static_cast<const Complex>(arg);
1801  if (_arg->is_re_zero()) {
1802  RCP<const Number> arg_img = _arg->imaginary_part();
1803  if (arg_img->is_negative()) {
1804  return sub(log(mul(minus_one, arg_img)),
1805  mul(I, div(pi, integer(2))));
1806  } else if (arg_img->is_zero()) {
1807  return ComplexInf;
1808  } else if (arg_img->is_positive()) {
1809  return add(log(arg_img), mul(I, div(pi, integer(2))));
1810  }
1811  }
1812  }
1813 
1814  return make_rcp<const Log>(arg);
1815 }
1816 
1817 RCP<const Basic> log(const RCP<const Basic> &arg, const RCP<const Basic> &base)
1818 {
1819  return div(log(arg), log(base));
1820 }
1821 
1822 LambertW::LambertW(const RCP<const Basic> &arg) : OneArgFunction{arg}
1823 {
1824  SYMENGINE_ASSIGN_TYPEID()
1825  SYMENGINE_ASSERT(is_canonical(arg))
1826 }
1827 
1828 bool LambertW::is_canonical(const RCP<const Basic> &arg) const
1829 {
1830  if (eq(*arg, *zero))
1831  return false;
1832  if (eq(*arg, *E))
1833  return false;
1834  if (eq(*arg, *div(neg(one), E)))
1835  return false;
1836  if (eq(*arg, *div(log(i2), im2)))
1837  return false;
1838  return true;
1839 }
1840 
1841 RCP<const Basic> LambertW::create(const RCP<const Basic> &arg) const
1842 {
1843  return lambertw(arg);
1844 }
1845 
1846 RCP<const Basic> lambertw(const RCP<const Basic> &arg)
1847 {
1848  if (eq(*arg, *zero))
1849  return zero;
1850  if (eq(*arg, *E))
1851  return one;
1852  if (eq(*arg, *div(neg(one), E)))
1853  return minus_one;
1854  if (eq(*arg, *div(log(i2), im2)))
1855  return mul(minus_one, log(i2));
1856  return make_rcp<const LambertW>(arg);
1857 }
1858 
1859 FunctionSymbol::FunctionSymbol(std::string name, const RCP<const Basic> &arg)
1860  : MultiArgFunction({arg}), name_{name} {SYMENGINE_ASSIGN_TYPEID()
1861  SYMENGINE_ASSERT(
1862  is_canonical(get_vec()))}
1863 
1864  FunctionSymbol::FunctionSymbol(std::string name, const vec_basic &arg)
1865  : MultiArgFunction(arg), name_{name}
1866 {
1867  SYMENGINE_ASSIGN_TYPEID()
1868  SYMENGINE_ASSERT(is_canonical(get_vec()))
1869 }
1870 
1871 bool FunctionSymbol::is_canonical(const vec_basic &arg) const
1872 {
1873  return true;
1874 }
1875 
1876 hash_t FunctionSymbol::__hash__() const
1877 {
1878  hash_t seed = SYMENGINE_FUNCTIONSYMBOL;
1879  for (const auto &a : get_vec())
1880  hash_combine<Basic>(seed, *a);
1881  hash_combine<std::string>(seed, name_);
1882  return seed;
1883 }
1884 
1885 bool FunctionSymbol::__eq__(const Basic &o) const
1886 {
1887  if (is_a<FunctionSymbol>(o)
1888  and name_ == down_cast<const FunctionSymbol &>(o).name_
1889  and unified_eq(get_vec(),
1890  down_cast<const FunctionSymbol &>(o).get_vec()))
1891  return true;
1892  return false;
1893 }
1894 
1895 int FunctionSymbol::compare(const Basic &o) const
1896 {
1897  SYMENGINE_ASSERT(is_a<FunctionSymbol>(o))
1898  const FunctionSymbol &s = down_cast<const FunctionSymbol &>(o);
1899  if (name_ == s.name_)
1900  return unified_compare(get_vec(), s.get_vec());
1901  else
1902  return name_ < s.name_ ? -1 : 1;
1903 }
1904 
1905 RCP<const Basic> FunctionSymbol::create(const vec_basic &x) const
1906 {
1907  return make_rcp<const FunctionSymbol>(name_, x);
1908 }
1909 
1910 RCP<const Basic> function_symbol(std::string name, const vec_basic &arg)
1911 {
1912  return make_rcp<const FunctionSymbol>(name, arg);
1913 }
1914 
1915 RCP<const Basic> function_symbol(std::string name, const RCP<const Basic> &arg)
1916 {
1917  return make_rcp<const FunctionSymbol>(name, arg);
1918 }
1919 
1920 FunctionWrapper::FunctionWrapper(std::string name, const RCP<const Basic> &arg)
1921  : FunctionSymbol(name, arg){SYMENGINE_ASSIGN_TYPEID()}
1922 
1923  FunctionWrapper::FunctionWrapper(std::string name, const vec_basic &vec)
1924  : FunctionSymbol(name, vec){SYMENGINE_ASSIGN_TYPEID()}
1925 
1926  /* ---------------------------- */
1927 
1928  Derivative::Derivative(const RCP<const Basic> &arg,
1929  const multiset_basic &x)
1930  : arg_{arg}, x_{x}
1931 {
1932  SYMENGINE_ASSIGN_TYPEID()
1933  SYMENGINE_ASSERT(is_canonical(arg, x))
1934 }
1935 
1936 bool Derivative::is_canonical(const RCP<const Basic> &arg,
1937  const multiset_basic &x) const
1938 {
1939  // Check that 'x' are Symbols:
1940  for (const auto &a : x)
1941  if (not is_a<Symbol>(*a))
1942  return false;
1943  if (is_a<FunctionSymbol>(*arg) or is_a<LeviCivita>(*arg)) {
1944  for (auto &p : x) {
1945  RCP<const Symbol> s = rcp_static_cast<const Symbol>(p);
1946  RCP<const MultiArgFunction> f
1947  = rcp_static_cast<const MultiArgFunction>(arg);
1948  bool found_s = false;
1949  // 's' should be one of the args of the function
1950  // and should not appear anywhere else.
1951  for (const auto &a : f->get_args()) {
1952  if (eq(*a, *s)) {
1953  if (found_s) {
1954  return false;
1955  } else {
1956  found_s = true;
1957  }
1958  } else if (neq(*a->diff(s), *zero)) {
1959  return false;
1960  }
1961  }
1962  if (!found_s) {
1963  return false;
1964  }
1965  }
1966  return true;
1967  } else if (is_a<Abs>(*arg)) {
1968  return true;
1969  } else if (is_a<FunctionWrapper>(*arg)) {
1970  return true;
1971  } else if (is_a<PolyGamma>(*arg) or is_a<Zeta>(*arg)
1972  or is_a<UpperGamma>(*arg) or is_a<LowerGamma>(*arg)
1973  or is_a<Dirichlet_eta>(*arg)) {
1974  bool found = false;
1975  auto v = arg->get_args();
1976  for (auto &p : x) {
1977  if (has_symbol(*v[0], *rcp_static_cast<const Symbol>(p))) {
1978  found = true;
1979  break;
1980  }
1981  }
1982  return found;
1983  } else if (is_a<KroneckerDelta>(*arg)) {
1984  bool found = false;
1985  auto v = arg->get_args();
1986  for (auto &p : x) {
1987  if (has_symbol(*v[0], *rcp_static_cast<const Symbol>(p))
1988  or has_symbol(*v[1], *rcp_static_cast<const Symbol>(p))) {
1989  found = true;
1990  break;
1991  }
1992  }
1993  return found;
1994  }
1995  return false;
1996 }
1997 
1998 hash_t Derivative::__hash__() const
1999 {
2000  hash_t seed = SYMENGINE_DERIVATIVE;
2001  hash_combine<Basic>(seed, *arg_);
2002  for (auto &p : x_) {
2003  hash_combine<Basic>(seed, *p);
2004  }
2005  return seed;
2006 }
2007 
2008 bool Derivative::__eq__(const Basic &o) const
2009 {
2010  if (is_a<Derivative>(o)
2011  and eq(*arg_, *(down_cast<const Derivative &>(o).arg_))
2012  and unified_eq(x_, down_cast<const Derivative &>(o).x_))
2013  return true;
2014  return false;
2015 }
2016 
2017 int Derivative::compare(const Basic &o) const
2018 {
2019  SYMENGINE_ASSERT(is_a<Derivative>(o))
2020  const Derivative &s = down_cast<const Derivative &>(o);
2021  int cmp = arg_->__cmp__(*(s.arg_));
2022  if (cmp != 0)
2023  return cmp;
2024  cmp = unified_compare(x_, s.x_);
2025  return cmp;
2026 }
2027 
2028 // Subs class
2029 Subs::Subs(const RCP<const Basic> &arg, const map_basic_basic &dict)
2030  : arg_{arg}, dict_{dict}
2031 {
2032  SYMENGINE_ASSIGN_TYPEID()
2033  SYMENGINE_ASSERT(is_canonical(arg, dict))
2034 }
2035 
2036 bool Subs::is_canonical(const RCP<const Basic> &arg,
2037  const map_basic_basic &dict) const
2038 {
2039  if (is_a<Derivative>(*arg)) {
2040  return true;
2041  }
2042  return false;
2043 }
2044 
2045 hash_t Subs::__hash__() const
2046 {
2047  hash_t seed = SYMENGINE_SUBS;
2048  hash_combine<Basic>(seed, *arg_);
2049  for (const auto &p : dict_) {
2050  hash_combine<Basic>(seed, *p.first);
2051  hash_combine<Basic>(seed, *p.second);
2052  }
2053  return seed;
2054 }
2055 
2056 bool Subs::__eq__(const Basic &o) const
2057 {
2058  if (is_a<Subs>(o) and eq(*arg_, *(down_cast<const Subs &>(o).arg_))
2059  and unified_eq(dict_, down_cast<const Subs &>(o).dict_))
2060  return true;
2061  return false;
2062 }
2063 
2064 int Subs::compare(const Basic &o) const
2065 {
2066  SYMENGINE_ASSERT(is_a<Subs>(o))
2067  const Subs &s = down_cast<const Subs &>(o);
2068  int cmp = arg_->__cmp__(*(s.arg_));
2069  if (cmp != 0)
2070  return cmp;
2071  cmp = unified_compare(dict_, s.dict_);
2072  return cmp;
2073 }
2074 
2075 vec_basic Subs::get_variables() const
2076 {
2077  vec_basic v;
2078  for (const auto &p : dict_) {
2079  v.push_back(p.first);
2080  }
2081  return v;
2082 }
2083 
2084 vec_basic Subs::get_point() const
2085 {
2086  vec_basic v;
2087  for (const auto &p : dict_) {
2088  v.push_back(p.second);
2089  }
2090  return v;
2091 }
2092 
2094 {
2095  vec_basic v = {arg_};
2096  for (const auto &p : dict_) {
2097  v.push_back(p.first);
2098  }
2099  for (const auto &p : dict_) {
2100  v.push_back(p.second);
2101  }
2102  return v;
2103 }
2104 
2105 Sinh::Sinh(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2106 {
2107  SYMENGINE_ASSIGN_TYPEID()
2108  SYMENGINE_ASSERT(is_canonical(arg))
2109 }
2110 
2111 bool Sinh::is_canonical(const RCP<const Basic> &arg) const
2112 {
2113  if (eq(*arg, *zero))
2114  return false;
2115  if (is_a_Number(*arg)) {
2116  if (down_cast<const Number &>(*arg).is_negative()) {
2117  return false;
2118  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2119  return false;
2120  }
2121  }
2122  if (could_extract_minus(*arg))
2123  return false;
2124  return true;
2125 }
2126 
2127 RCP<const Basic> sinh(const RCP<const Basic> &arg)
2128 {
2129  if (eq(*arg, *zero))
2130  return zero;
2131  if (is_a_Number(*arg)) {
2132  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2133  if (not _arg->is_exact()) {
2134  return _arg->get_eval().sinh(*_arg);
2135  } else if (_arg->is_negative()) {
2136  return neg(sinh(zero->sub(*_arg)));
2137  }
2138  }
2139  RCP<const Basic> d;
2140  bool b = handle_minus(arg, outArg(d));
2141  if (b) {
2142  return neg(sinh(d));
2143  }
2144  return make_rcp<const Sinh>(d);
2145 }
2146 
2147 Csch::Csch(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2148 {
2149  SYMENGINE_ASSIGN_TYPEID()
2150  SYMENGINE_ASSERT(is_canonical(arg))
2151 }
2152 
2153 bool Csch::is_canonical(const RCP<const Basic> &arg) const
2154 {
2155  if (eq(*arg, *zero))
2156  return false;
2157  if (is_a_Number(*arg)) {
2158  if (down_cast<const Number &>(*arg).is_negative()) {
2159  return false;
2160  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2161  return false;
2162  }
2163  }
2164  if (could_extract_minus(*arg))
2165  return false;
2166  return true;
2167 }
2168 
2169 RCP<const Basic> csch(const RCP<const Basic> &arg)
2170 {
2171  if (eq(*arg, *zero)) {
2172  return ComplexInf;
2173  }
2174  if (is_a_Number(*arg)) {
2175  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2176  if (not _arg->is_exact()) {
2177  return _arg->get_eval().csch(*_arg);
2178  } else if (_arg->is_negative()) {
2179  return neg(csch(zero->sub(*_arg)));
2180  }
2181  }
2182  RCP<const Basic> d;
2183  bool b = handle_minus(arg, outArg(d));
2184  if (b) {
2185  return neg(csch(d));
2186  }
2187  return make_rcp<const Csch>(d);
2188 }
2189 
2190 Cosh::Cosh(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2191 {
2192  SYMENGINE_ASSIGN_TYPEID()
2193  SYMENGINE_ASSERT(is_canonical(arg))
2194 }
2195 
2196 bool Cosh::is_canonical(const RCP<const Basic> &arg) const
2197 {
2198  if (eq(*arg, *zero))
2199  return false;
2200  if (is_a_Number(*arg)) {
2201  if (down_cast<const Number &>(*arg).is_negative()) {
2202  return false;
2203  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2204  return false;
2205  }
2206  }
2207  if (could_extract_minus(*arg))
2208  return false;
2209  return true;
2210 }
2211 
2212 RCP<const Basic> cosh(const RCP<const Basic> &arg)
2213 {
2214  if (eq(*arg, *zero))
2215  return one;
2216  if (is_a_Number(*arg)) {
2217  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2218  if (not _arg->is_exact()) {
2219  return _arg->get_eval().cosh(*_arg);
2220  } else if (_arg->is_negative()) {
2221  return cosh(zero->sub(*_arg));
2222  }
2223  }
2224  RCP<const Basic> d;
2225  handle_minus(arg, outArg(d));
2226  return make_rcp<const Cosh>(d);
2227 }
2228 
2229 Sech::Sech(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2230 {
2231  SYMENGINE_ASSIGN_TYPEID()
2232  SYMENGINE_ASSERT(is_canonical(arg))
2233 }
2234 
2235 bool Sech::is_canonical(const RCP<const Basic> &arg) const
2236 {
2237  if (eq(*arg, *zero))
2238  return false;
2239  if (is_a_Number(*arg)) {
2240  if (down_cast<const Number &>(*arg).is_negative()) {
2241  return false;
2242  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2243  return false;
2244  }
2245  }
2246  if (could_extract_minus(*arg))
2247  return false;
2248  return true;
2249 }
2250 
2251 RCP<const Basic> sech(const RCP<const Basic> &arg)
2252 {
2253  if (eq(*arg, *zero))
2254  return one;
2255  if (is_a_Number(*arg)) {
2256  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2257  if (not _arg->is_exact()) {
2258  return _arg->get_eval().sech(*_arg);
2259  } else if (_arg->is_negative()) {
2260  return sech(zero->sub(*_arg));
2261  }
2262  }
2263  RCP<const Basic> d;
2264  handle_minus(arg, outArg(d));
2265  return make_rcp<const Sech>(d);
2266 }
2267 
2268 Tanh::Tanh(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2269 {
2270  SYMENGINE_ASSIGN_TYPEID()
2271  SYMENGINE_ASSERT(is_canonical(arg))
2272 }
2273 
2274 bool Tanh::is_canonical(const RCP<const Basic> &arg) const
2275 {
2276  if (eq(*arg, *zero))
2277  return false;
2278  if (is_a_Number(*arg)) {
2279  if (down_cast<const Number &>(*arg).is_negative()) {
2280  return false;
2281  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2282  return false;
2283  }
2284  }
2285  if (could_extract_minus(*arg))
2286  return false;
2287  return true;
2288 }
2289 
2290 RCP<const Basic> tanh(const RCP<const Basic> &arg)
2291 {
2292  if (eq(*arg, *zero))
2293  return zero;
2294  if (is_a_Number(*arg)) {
2295  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2296  if (not _arg->is_exact()) {
2297  return _arg->get_eval().tanh(*_arg);
2298  } else if (_arg->is_negative()) {
2299  return neg(tanh(zero->sub(*_arg)));
2300  }
2301  }
2302 
2303  RCP<const Basic> d;
2304  bool b = handle_minus(arg, outArg(d));
2305  if (b) {
2306  return neg(tanh(d));
2307  }
2308  return make_rcp<const Tanh>(d);
2309 }
2310 
2311 Coth::Coth(const RCP<const Basic> &arg) : HyperbolicFunction(arg)
2312 {
2313  SYMENGINE_ASSIGN_TYPEID()
2314  SYMENGINE_ASSERT(is_canonical(arg))
2315 }
2316 
2317 bool Coth::is_canonical(const RCP<const Basic> &arg) const
2318 {
2319  if (eq(*arg, *zero))
2320  return false;
2321  if (is_a_Number(*arg)) {
2322  if (down_cast<const Number &>(*arg).is_negative()) {
2323  return false;
2324  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2325  return false;
2326  }
2327  }
2328  if (could_extract_minus(*arg))
2329  return false;
2330  return true;
2331 }
2332 
2333 RCP<const Basic> coth(const RCP<const Basic> &arg)
2334 {
2335  if (eq(*arg, *zero)) {
2336  return ComplexInf;
2337  }
2338  if (is_a_Number(*arg)) {
2339  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2340  if (not _arg->is_exact()) {
2341  return _arg->get_eval().coth(*_arg);
2342  } else if (_arg->is_negative()) {
2343  return neg(coth(zero->sub(*_arg)));
2344  }
2345  }
2346  RCP<const Basic> d;
2347  bool b = handle_minus(arg, outArg(d));
2348  if (b) {
2349  return neg(coth(d));
2350  }
2351  return make_rcp<const Coth>(d);
2352 }
2353 
2354 ASinh::ASinh(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2355 {
2356  SYMENGINE_ASSIGN_TYPEID()
2357  SYMENGINE_ASSERT(is_canonical(arg))
2358 }
2359 
2360 bool ASinh::is_canonical(const RCP<const Basic> &arg) const
2361 {
2362  if (eq(*arg, *zero) or eq(*arg, *one) or eq(*arg, *minus_one))
2363  return false;
2364  if (is_a_Number(*arg)) {
2365  if (down_cast<const Number &>(*arg).is_negative()) {
2366  return false;
2367  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2368  return false;
2369  }
2370  }
2371  if (could_extract_minus(*arg))
2372  return false;
2373  return true;
2374 }
2375 
2376 RCP<const Basic> asinh(const RCP<const Basic> &arg)
2377 {
2378  if (eq(*arg, *zero))
2379  return zero;
2380  if (eq(*arg, *one))
2381  return log(add(one, sq2));
2382  if (eq(*arg, *minus_one))
2383  return log(sub(sq2, one));
2384  if (is_a_Number(*arg)) {
2385  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2386  if (not _arg->is_exact()) {
2387  return _arg->get_eval().asinh(*_arg);
2388  } else if (_arg->is_negative()) {
2389  return neg(asinh(zero->sub(*_arg)));
2390  }
2391  }
2392  RCP<const Basic> d;
2393  bool b = handle_minus(arg, outArg(d));
2394  if (b) {
2395  return neg(asinh(d));
2396  }
2397  return make_rcp<const ASinh>(d);
2398 }
2399 
2400 ACsch::ACsch(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2401 {
2402  SYMENGINE_ASSIGN_TYPEID()
2403  SYMENGINE_ASSERT(is_canonical(arg))
2404 }
2405 
2406 bool ACsch::is_canonical(const RCP<const Basic> &arg) const
2407 {
2408  if (eq(*arg, *one) or eq(*arg, *minus_one))
2409  return false;
2410  if (is_a_Number(*arg)) {
2411  if (down_cast<const Number &>(*arg).is_negative()) {
2412  return false;
2413  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2414  return false;
2415  }
2416  }
2417  if (could_extract_minus(*arg))
2418  return false;
2419  return true;
2420 }
2421 
2422 RCP<const Basic> acsch(const RCP<const Basic> &arg)
2423 {
2424  if (eq(*arg, *one))
2425  return log(add(one, sq2));
2426  if (eq(*arg, *minus_one))
2427  return log(sub(sq2, one));
2428 
2429  if (is_a_Number(*arg)) {
2430  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2431  if (not _arg->is_exact()) {
2432  return _arg->get_eval().acsch(*_arg);
2433  }
2434  }
2435 
2436  RCP<const Basic> d;
2437  bool b = handle_minus(arg, outArg(d));
2438  if (b) {
2439  return neg(acsch(d));
2440  }
2441  return make_rcp<const ACsch>(d);
2442 }
2443 
2444 ACosh::ACosh(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2445 {
2446  SYMENGINE_ASSIGN_TYPEID()
2447  SYMENGINE_ASSERT(is_canonical(arg))
2448 }
2449 
2450 bool ACosh::is_canonical(const RCP<const Basic> &arg) const
2451 {
2452  // TODO: Lookup into a cst table once complex is implemented
2453  if (eq(*arg, *one))
2454  return false;
2455  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2456  return false;
2457  }
2458  return true;
2459 }
2460 
2461 RCP<const Basic> acosh(const RCP<const Basic> &arg)
2462 {
2463  // TODO: Lookup into a cst table once complex is implemented
2464  if (eq(*arg, *one))
2465  return zero;
2466  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2467  return down_cast<const Number &>(*arg).get_eval().acosh(*arg);
2468  }
2469  return make_rcp<const ACosh>(arg);
2470 }
2471 
2472 ATanh::ATanh(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2473 {
2474  SYMENGINE_ASSIGN_TYPEID()
2475  SYMENGINE_ASSERT(is_canonical(arg))
2476 }
2477 
2478 bool ATanh::is_canonical(const RCP<const Basic> &arg) const
2479 {
2480  if (eq(*arg, *zero))
2481  return false;
2482  if (is_a_Number(*arg)) {
2483  if (down_cast<const Number &>(*arg).is_negative()) {
2484  return false;
2485  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2486  return false;
2487  }
2488  }
2489  if (could_extract_minus(*arg))
2490  return false;
2491  return true;
2492 }
2493 
2494 RCP<const Basic> atanh(const RCP<const Basic> &arg)
2495 {
2496  if (eq(*arg, *zero))
2497  return zero;
2498  if (is_a_Number(*arg)) {
2499  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2500  if (not _arg->is_exact()) {
2501  return _arg->get_eval().atanh(*_arg);
2502  } else if (_arg->is_negative()) {
2503  return neg(atanh(zero->sub(*_arg)));
2504  }
2505  }
2506  RCP<const Basic> d;
2507  bool b = handle_minus(arg, outArg(d));
2508  if (b) {
2509  return neg(atanh(d));
2510  }
2511  return make_rcp<const ATanh>(d);
2512 }
2513 
2514 ACoth::ACoth(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2515 {
2516  SYMENGINE_ASSIGN_TYPEID()
2517  SYMENGINE_ASSERT(is_canonical(arg))
2518 }
2519 
2520 bool ACoth::is_canonical(const RCP<const Basic> &arg) const
2521 {
2522  if (is_a_Number(*arg)) {
2523  if (down_cast<const Number &>(*arg).is_negative()) {
2524  return false;
2525  } else if (not down_cast<const Number &>(*arg).is_exact()) {
2526  return false;
2527  }
2528  }
2529  if (could_extract_minus(*arg))
2530  return false;
2531  return true;
2532 }
2533 
2534 RCP<const Basic> acoth(const RCP<const Basic> &arg)
2535 {
2536  if (is_a_Number(*arg)) {
2537  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2538  if (not _arg->is_exact()) {
2539  return _arg->get_eval().acoth(*_arg);
2540  } else if (_arg->is_negative()) {
2541  return neg(acoth(zero->sub(*_arg)));
2542  }
2543  }
2544  RCP<const Basic> d;
2545  bool b = handle_minus(arg, outArg(d));
2546  if (b) {
2547  return neg(acoth(d));
2548  }
2549  return make_rcp<const ACoth>(d);
2550 }
2551 
2552 ASech::ASech(const RCP<const Basic> &arg) : InverseHyperbolicFunction(arg)
2553 {
2554  SYMENGINE_ASSIGN_TYPEID()
2555  SYMENGINE_ASSERT(is_canonical(arg))
2556 }
2557 
2558 bool ASech::is_canonical(const RCP<const Basic> &arg) const
2559 {
2560  // TODO: Lookup into a cst table once complex is implemented
2561  if (eq(*arg, *one))
2562  return false;
2563  if (eq(*arg, *zero))
2564  return false;
2565  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2566  return false;
2567  }
2568  return true;
2569 }
2570 
2571 RCP<const Basic> asech(const RCP<const Basic> &arg)
2572 {
2573  // TODO: Lookup into a cst table once complex is implemented
2574  if (eq(*arg, *one))
2575  return zero;
2576  if (eq(*arg, *zero))
2577  return Inf;
2578  if (is_a_Number(*arg)) {
2579  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2580  if (not _arg->is_exact()) {
2581  return _arg->get_eval().asech(*_arg);
2582  }
2583  }
2584  return make_rcp<const ASech>(arg);
2585 }
2586 
2587 RCP<const Basic> Sinh::create(const RCP<const Basic> &arg) const
2588 {
2589  return sinh(arg);
2590 }
2591 
2592 RCP<const Basic> Csch::create(const RCP<const Basic> &arg) const
2593 {
2594  return csch(arg);
2595 }
2596 
2597 RCP<const Basic> Cosh::create(const RCP<const Basic> &arg) const
2598 {
2599  return cosh(arg);
2600 }
2601 
2602 RCP<const Basic> Sech::create(const RCP<const Basic> &arg) const
2603 {
2604  return sech(arg);
2605 }
2606 
2607 RCP<const Basic> Tanh::create(const RCP<const Basic> &arg) const
2608 {
2609  return tanh(arg);
2610 }
2611 
2612 RCP<const Basic> Coth::create(const RCP<const Basic> &arg) const
2613 {
2614  return coth(arg);
2615 }
2616 
2617 RCP<const Basic> ASinh::create(const RCP<const Basic> &arg) const
2618 {
2619  return asinh(arg);
2620 }
2621 
2622 RCP<const Basic> ACsch::create(const RCP<const Basic> &arg) const
2623 {
2624  return acsch(arg);
2625 }
2626 
2627 RCP<const Basic> ACosh::create(const RCP<const Basic> &arg) const
2628 {
2629  return acosh(arg);
2630 }
2631 
2632 RCP<const Basic> ATanh::create(const RCP<const Basic> &arg) const
2633 {
2634  return atanh(arg);
2635 }
2636 
2637 RCP<const Basic> ACoth::create(const RCP<const Basic> &arg) const
2638 {
2639  return acoth(arg);
2640 }
2641 
2642 RCP<const Basic> ASech::create(const RCP<const Basic> &arg) const
2643 {
2644  return asech(arg);
2645 }
2646 
2647 KroneckerDelta::KroneckerDelta(const RCP<const Basic> &i,
2648  const RCP<const Basic> &j)
2649  : TwoArgFunction(i, j)
2650 {
2651  SYMENGINE_ASSIGN_TYPEID()
2652  SYMENGINE_ASSERT(is_canonical(i, j))
2653 }
2654 
2655 bool KroneckerDelta::is_canonical(const RCP<const Basic> &i,
2656  const RCP<const Basic> &j) const
2657 {
2658  RCP<const Basic> diff = expand(sub(i, j));
2659  if (eq(*diff, *zero)) {
2660  return false;
2661  } else if (is_a_Number(*diff)) {
2662  return false;
2663  } else {
2664  // TODO: SymPy uses default key sorting to return in order
2665  return true;
2666  }
2667 }
2668 
2669 RCP<const Basic> KroneckerDelta::create(const RCP<const Basic> &a,
2670  const RCP<const Basic> &b) const
2671 {
2672  return kronecker_delta(a, b);
2673 }
2674 
2675 RCP<const Basic> kronecker_delta(const RCP<const Basic> &i,
2676  const RCP<const Basic> &j)
2677 {
2678  // Expand is needed to simplify things like `i-(i+1)` to `-1`
2679  RCP<const Basic> diff = expand(sub(i, j));
2680  if (eq(*diff, *zero)) {
2681  return one;
2682  } else if (is_a_Number(*diff)) {
2683  return zero;
2684  } else {
2685  // SymPy uses default key sorting to return in order
2686  return make_rcp<const KroneckerDelta>(i, j);
2687  }
2688 }
2689 
2690 bool has_dup(const vec_basic &arg)
2691 {
2692  map_basic_basic d;
2693  auto it = d.end();
2694  for (const auto &p : arg) {
2695  it = d.find(p);
2696  if (it == d.end()) {
2697  insert(d, p, one);
2698  } else {
2699  return true;
2700  }
2701  }
2702  return false;
2703 }
2704 
2706 {
2707  SYMENGINE_ASSIGN_TYPEID()
2708  SYMENGINE_ASSERT(is_canonical(get_vec()))
2709 }
2710 
2711 bool LeviCivita::is_canonical(const vec_basic &arg) const
2712 {
2713  bool are_int = true;
2714  for (const auto &p : arg) {
2715  if (not(is_a_Number(*p))) {
2716  are_int = false;
2717  break;
2718  }
2719  }
2720  if (are_int) {
2721  return false;
2722  } else if (has_dup(arg)) {
2723  return false;
2724  } else {
2725  return true;
2726  }
2727 }
2728 
2729 RCP<const Basic> LeviCivita::create(const vec_basic &a) const
2730 {
2731  return levi_civita(a);
2732 }
2733 
2734 RCP<const Basic> eval_levicivita(const vec_basic &arg, int len)
2735 {
2736  int i, j;
2737  RCP<const Basic> res = one;
2738  for (i = 0; i < len; i++) {
2739  for (j = i + 1; j < len; j++) {
2740  res = mul(sub(arg[j], arg[i]), res);
2741  }
2742  res = div(res, factorial(i));
2743  }
2744  return res;
2745 }
2746 
2747 RCP<const Basic> levi_civita(const vec_basic &arg)
2748 {
2749  bool are_int = true;
2750  int len = 0;
2751  for (const auto &p : arg) {
2752  if (not(is_a_Number(*p))) {
2753  are_int = false;
2754  break;
2755  } else {
2756  len++;
2757  }
2758  }
2759  if (are_int) {
2760  return eval_levicivita(arg, len);
2761  } else if (has_dup(arg)) {
2762  return zero;
2763  } else {
2764  return make_rcp<const LeviCivita>(std::move(arg));
2765  }
2766 }
2767 
2768 Zeta::Zeta(const RCP<const Basic> &s, const RCP<const Basic> &a)
2769  : TwoArgFunction(s, a){SYMENGINE_ASSIGN_TYPEID()
2770  SYMENGINE_ASSERT(is_canonical(s, a))}
2771 
2772  Zeta::Zeta(const RCP<const Basic> &s)
2773  : TwoArgFunction(s, one)
2774 {
2775  SYMENGINE_ASSIGN_TYPEID()
2776  SYMENGINE_ASSERT(is_canonical(s, one))
2777 }
2778 
2779 bool Zeta::is_canonical(const RCP<const Basic> &s,
2780  const RCP<const Basic> &a) const
2781 {
2782  if (eq(*s, *zero))
2783  return false;
2784  if (eq(*s, *one))
2785  return false;
2786  if (is_a<Integer>(*s) and is_a<Integer>(*a)) {
2787  auto s_ = down_cast<const Integer &>(*s).as_int();
2788  if (s_ < 0 || s_ % 2 == 0)
2789  return false;
2790  }
2791  return true;
2792 }
2793 
2794 RCP<const Basic> Zeta::create(const RCP<const Basic> &a,
2795  const RCP<const Basic> &b) const
2796 {
2797  return zeta(a, b);
2798 }
2799 
2800 RCP<const Basic> zeta(const RCP<const Basic> &s, const RCP<const Basic> &a)
2801 {
2802  if (is_a_Number(*s)) {
2803  if (down_cast<const Number &>(*s).is_zero()) {
2804  return sub(div(one, i2), a);
2805  } else if (down_cast<const Number &>(*s).is_one()) {
2806  return infty(0);
2807  } else if (is_a<Integer>(*s) and is_a<Integer>(*a)) {
2808  auto s_ = down_cast<const Integer &>(*s).as_int();
2809  auto a_ = down_cast<const Integer &>(*a).as_int();
2810  RCP<const Basic> zeta;
2811  if (s_ < 0) {
2812  RCP<const Number> res = (s_ % 2 == 0) ? one : minus_one;
2813  zeta
2814  = mulnum(res, divnum(bernoulli(-s_ + 1), integer(-s_ + 1)));
2815  } else if (s_ % 2 == 0) {
2816  RCP<const Number> b = bernoulli(s_);
2817  RCP<const Number> f = factorial(s_);
2818  zeta = divnum(pownum(integer(2), integer(s_ - 1)), f);
2819  zeta = mul(zeta, mul(pow(pi, s), abs(b)));
2820  } else {
2821  return make_rcp<const Zeta>(s, a);
2822  }
2823  if (a_ < 0)
2824  return add(zeta, harmonic(-a_, s_));
2825  return sub(zeta, harmonic(a_ - 1, s_));
2826  }
2827  }
2828  return make_rcp<const Zeta>(s, a);
2829 }
2830 
2831 RCP<const Basic> zeta(const RCP<const Basic> &s)
2832 {
2833  return zeta(s, one);
2834 }
2835 
2836 Dirichlet_eta::Dirichlet_eta(const RCP<const Basic> &s) : OneArgFunction(s)
2837 {
2838  SYMENGINE_ASSIGN_TYPEID()
2839  SYMENGINE_ASSERT(is_canonical(s))
2840 }
2841 
2842 bool Dirichlet_eta::is_canonical(const RCP<const Basic> &s) const
2843 {
2844  if (eq(*s, *one))
2845  return false;
2846  if (not(is_a<Zeta>(*zeta(s))))
2847  return false;
2848  return true;
2849 }
2850 
2851 RCP<const Basic> Dirichlet_eta::rewrite_as_zeta() const
2852 {
2853  return mul(sub(one, pow(i2, sub(one, get_arg()))), zeta(get_arg()));
2854 }
2855 
2856 RCP<const Basic> Dirichlet_eta::create(const RCP<const Basic> &arg) const
2857 {
2858  return dirichlet_eta(arg);
2859 }
2860 
2861 RCP<const Basic> dirichlet_eta(const RCP<const Basic> &s)
2862 {
2863  if (is_a_Number(*s) and down_cast<const Number &>(*s).is_one()) {
2864  return log(i2);
2865  }
2866  RCP<const Basic> z = zeta(s);
2867  if (is_a<Zeta>(*z)) {
2868  return make_rcp<const Dirichlet_eta>(s);
2869  } else {
2870  return mul(sub(one, pow(i2, sub(one, s))), z);
2871  }
2872 }
2873 
2874 bool Erf::is_canonical(const RCP<const Basic> &arg) const
2875 {
2876  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
2877  return false;
2878  if (could_extract_minus(*arg))
2879  return false;
2880  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2881  return false;
2882  }
2883  return true;
2884 }
2885 
2886 RCP<const Basic> Erf::create(const RCP<const Basic> &arg) const
2887 {
2888  return erf(arg);
2889 }
2890 
2891 RCP<const Basic> erf(const RCP<const Basic> &arg)
2892 {
2893  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero()) {
2894  return zero;
2895  }
2896  if (is_a_Number(*arg)) {
2897  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2898  if (not _arg->is_exact()) {
2899  return _arg->get_eval().erf(*_arg);
2900  }
2901  }
2902  RCP<const Basic> d;
2903  bool b = handle_minus(arg, outArg(d));
2904  if (b) {
2905  return neg(erf(d));
2906  }
2907  return make_rcp<const Erf>(d);
2908 }
2909 
2910 bool Erfc::is_canonical(const RCP<const Basic> &arg) const
2911 {
2912  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero())
2913  return false;
2914  if (could_extract_minus(*arg))
2915  return false;
2916  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2917  return false;
2918  }
2919  return true;
2920 }
2921 
2922 RCP<const Basic> Erfc::create(const RCP<const Basic> &arg) const
2923 {
2924  return erfc(arg);
2925 }
2926 
2927 RCP<const Basic> erfc(const RCP<const Basic> &arg)
2928 {
2929  if (is_a<Integer>(*arg) and down_cast<const Integer &>(*arg).is_zero()) {
2930  return one;
2931  }
2932  if (is_a_Number(*arg)) {
2933  RCP<const Number> _arg = rcp_static_cast<const Number>(arg);
2934  if (not _arg->is_exact()) {
2935  return _arg->get_eval().erfc(*_arg);
2936  }
2937  }
2938 
2939  RCP<const Basic> d;
2940  bool b = handle_minus(arg, outArg(d));
2941  if (b) {
2942  return add(integer(2), neg(erfc(d)));
2943  }
2944  return make_rcp<const Erfc>(d);
2945 }
2946 
2947 Gamma::Gamma(const RCP<const Basic> &arg) : OneArgFunction{arg}
2948 {
2949  SYMENGINE_ASSIGN_TYPEID()
2950  SYMENGINE_ASSERT(is_canonical(arg))
2951 }
2952 
2953 bool Gamma::is_canonical(const RCP<const Basic> &arg) const
2954 {
2955  if (is_a<Integer>(*arg))
2956  return false;
2957  if (is_a<Rational>(*arg)
2958  and (get_den(down_cast<const Rational &>(*arg).as_rational_class()))
2959  == 2) {
2960  return false;
2961  }
2962  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
2963  return false;
2964  }
2965  return true;
2966 }
2967 
2968 RCP<const Basic> Gamma::create(const RCP<const Basic> &arg) const
2969 {
2970  return gamma(arg);
2971 }
2972 
2973 RCP<const Basic> gamma_positive_int(const RCP<const Basic> &arg)
2974 {
2975  SYMENGINE_ASSERT(is_a<Integer>(*arg))
2976  RCP<const Integer> arg_ = rcp_static_cast<const Integer>(arg);
2977  SYMENGINE_ASSERT(arg_->is_positive())
2978  return factorial((arg_->subint(*one))->as_int());
2979 }
2980 
2981 RCP<const Basic> gamma_multiple_2(const RCP<const Basic> &arg)
2982 {
2983  SYMENGINE_ASSERT(is_a<Rational>(*arg))
2984  RCP<const Rational> arg_ = rcp_static_cast<const Rational>(arg);
2985  SYMENGINE_ASSERT(get_den(arg_->as_rational_class()) == 2)
2986  RCP<const Integer> n, k;
2987  RCP<const Number> coeff;
2988  n = quotient_f(*(integer(mp_abs(get_num(arg_->as_rational_class())))),
2989  *(integer(get_den(arg_->as_rational_class()))));
2990  if (arg_->is_positive()) {
2991  k = n;
2992  coeff = one;
2993  } else {
2994  n = n->addint(*one);
2995  k = n;
2996  if ((n->as_int() & 1) == 0) {
2997  coeff = one;
2998  } else {
2999  coeff = minus_one;
3000  }
3001  }
3002  int j = 1;
3003  for (int i = 3; i < 2 * k->as_int(); i = i + 2) {
3004  j = j * i;
3005  }
3006  coeff = mulnum(coeff, integer(j));
3007  if (arg_->is_positive()) {
3008  return div(mul(coeff, sqrt(pi)), pow(i2, n));
3009  } else {
3010  return div(mul(pow(i2, n), sqrt(pi)), coeff);
3011  }
3012 }
3013 
3014 RCP<const Basic> gamma(const RCP<const Basic> &arg)
3015 {
3016  if (is_a<Integer>(*arg)) {
3017  RCP<const Integer> arg_ = rcp_static_cast<const Integer>(arg);
3018  if (arg_->is_positive()) {
3019  return gamma_positive_int(arg);
3020  } else {
3021  return ComplexInf;
3022  }
3023  } else if (is_a<Rational>(*arg)) {
3024  RCP<const Rational> arg_ = rcp_static_cast<const Rational>(arg);
3025  if ((get_den(arg_->as_rational_class())) == 2) {
3026  return gamma_multiple_2(arg);
3027  } else {
3028  return make_rcp<const Gamma>(arg);
3029  }
3030  } else if (is_a_Number(*arg)
3031  and not down_cast<const Number &>(*arg).is_exact()) {
3032  return down_cast<const Number &>(*arg).get_eval().gamma(*arg);
3033  }
3034  return make_rcp<const Gamma>(arg);
3035 }
3036 
3037 LowerGamma::LowerGamma(const RCP<const Basic> &s, const RCP<const Basic> &x)
3038  : TwoArgFunction(s, x)
3039 {
3040  SYMENGINE_ASSIGN_TYPEID()
3041  SYMENGINE_ASSERT(is_canonical(s, x))
3042 }
3043 
3044 bool LowerGamma::is_canonical(const RCP<const Basic> &s,
3045  const RCP<const Basic> &x) const
3046 {
3047  // Only special values are evaluated
3048  if (eq(*s, *one))
3049  return false;
3050  if (is_a<Integer>(*s)
3051  and down_cast<const Integer &>(*s).as_integer_class() > 1)
3052  return false;
3053  if (is_a<Integer>(*mul(i2, s)))
3054  return false;
3055 #ifdef HAVE_SYMENGINE_MPFR
3056 #if MPFR_VERSION_MAJOR > 3
3057  if (is_a<RealMPFR>(*s) && is_a<RealMPFR>(*x))
3058  return false;
3059 #endif
3060 #endif
3061  return true;
3062 }
3063 
3064 RCP<const Basic> LowerGamma::create(const RCP<const Basic> &a,
3065  const RCP<const Basic> &b) const
3066 {
3067  return lowergamma(a, b);
3068 }
3069 
3070 RCP<const Basic> lowergamma(const RCP<const Basic> &s,
3071  const RCP<const Basic> &x)
3072 {
3073  // Only special values are being evaluated
3074  if (is_a<Integer>(*s)) {
3075  RCP<const Integer> s_int = rcp_static_cast<const Integer>(s);
3076  if (s_int->is_one()) {
3077  return sub(one, exp(mul(minus_one, x)));
3078  } else if (s_int->as_integer_class() > 1) {
3079  s_int = s_int->subint(*one);
3080  return sub(mul(s_int, lowergamma(s_int, x)),
3081  mul(pow(x, s_int), exp(mul(minus_one, x))));
3082  } else {
3083  return make_rcp<const LowerGamma>(s, x);
3084  }
3085  } else if (is_a<Integer>(*(mul(i2, s)))) {
3086  RCP<const Number> s_num = rcp_static_cast<const Number>(s);
3087  s_num = subnum(s_num, one);
3088  if (eq(*s, *div(one, integer(2)))) {
3089  return mul(sqrt(pi),
3090  erf(sqrt(x))); // base case for s of the form n/2
3091  } else if (s_num->is_positive()) {
3092  return sub(mul(s_num, lowergamma(s_num, x)),
3093  mul(pow(x, s_num), exp(mul(minus_one, x))));
3094  } else {
3095  return div(add(lowergamma(add(s, one), x),
3096  mul(pow(x, s), exp(mul(minus_one, x)))),
3097  s);
3098  }
3099 #ifdef HAVE_SYMENGINE_MPFR
3100 #if MPFR_VERSION_MAJOR > 3
3101  } else if (is_a<RealMPFR>(*s) && is_a<RealMPFR>(*x)) {
3102  const auto &s_ = down_cast<const RealMPFR &>(*s).i.get_mpfr_t();
3103  const auto &x_ = down_cast<const RealMPFR &>(*x).i.get_mpfr_t();
3104  if (mpfr_cmp_si(x_, 0) >= 0) {
3105  mpfr_class t(std::max(mpfr_get_prec(s_), mpfr_get_prec(x_)));
3106  mpfr_class u(std::max(mpfr_get_prec(s_), mpfr_get_prec(x_)));
3107  mpfr_gamma_inc(t.get_mpfr_t(), s_, x_, MPFR_RNDN);
3108  mpfr_gamma(u.get_mpfr_t(), s_, MPFR_RNDN);
3109  mpfr_sub(t.get_mpfr_t(), u.get_mpfr_t(), t.get_mpfr_t(), MPFR_RNDN);
3110  return real_mpfr(std::move(t));
3111  } else {
3112  throw NotImplementedError("Not implemented.");
3113  }
3114 #endif
3115 #endif
3116  }
3117  return make_rcp<const LowerGamma>(s, x);
3118 }
3119 
3120 UpperGamma::UpperGamma(const RCP<const Basic> &s, const RCP<const Basic> &x)
3121  : TwoArgFunction(s, x)
3122 {
3123  SYMENGINE_ASSIGN_TYPEID()
3124  SYMENGINE_ASSERT(is_canonical(s, x))
3125 }
3126 
3127 bool UpperGamma::is_canonical(const RCP<const Basic> &s,
3128  const RCP<const Basic> &x) const
3129 {
3130  // Only special values are evaluated
3131  if (eq(*s, *one))
3132  return false;
3133  if (is_a<Integer>(*s)
3134  and down_cast<const Integer &>(*s).as_integer_class() > 1)
3135  return false;
3136  if (is_a<Integer>(*mul(i2, s)))
3137  return false;
3138 #ifdef HAVE_SYMENGINE_MPFR
3139 #if MPFR_VERSION_MAJOR > 3
3140  if (is_a<RealMPFR>(*s) && is_a<RealMPFR>(*x))
3141  return false;
3142 #endif
3143 #endif
3144  return true;
3145 }
3146 
3147 RCP<const Basic> UpperGamma::create(const RCP<const Basic> &a,
3148  const RCP<const Basic> &b) const
3149 {
3150  return uppergamma(a, b);
3151 }
3152 
3153 RCP<const Basic> uppergamma(const RCP<const Basic> &s,
3154  const RCP<const Basic> &x)
3155 {
3156  // Only special values are being evaluated
3157  if (is_a<Integer>(*s)) {
3158  RCP<const Integer> s_int = rcp_static_cast<const Integer>(s);
3159  if (s_int->is_one()) {
3160  return exp(mul(minus_one, x));
3161  } else if (s_int->as_integer_class() > 1) {
3162  s_int = s_int->subint(*one);
3163  return add(mul(s_int, uppergamma(s_int, x)),
3164  mul(pow(x, s_int), exp(mul(minus_one, x))));
3165  } else {
3166  // TODO: implement unpolarfy to handle this case
3167  return make_rcp<const LowerGamma>(s, x);
3168  }
3169  } else if (is_a<Integer>(*(mul(i2, s)))) {
3170  RCP<const Number> s_num = rcp_static_cast<const Number>(s);
3171  s_num = subnum(s_num, one);
3172  if (eq(*s, *div(one, integer(2)))) {
3173  return mul(sqrt(pi),
3174  erfc(sqrt(x))); // base case for s of the form n/2
3175  } else if (s_num->is_positive()) {
3176  return add(mul(s_num, uppergamma(s_num, x)),
3177  mul(pow(x, s_num), exp(mul(minus_one, x))));
3178  } else {
3179  return div(sub(uppergamma(add(s, one), x),
3180  mul(pow(x, s), exp(mul(minus_one, x)))),
3181  s);
3182  }
3183 #ifdef HAVE_SYMENGINE_MPFR
3184 #if MPFR_VERSION_MAJOR > 3
3185  } else if (is_a<RealMPFR>(*s) && is_a<RealMPFR>(*x)) {
3186  const auto &s_ = down_cast<const RealMPFR &>(*s).i.get_mpfr_t();
3187  const auto &x_ = down_cast<const RealMPFR &>(*x).i.get_mpfr_t();
3188  if (mpfr_cmp_si(x_, 0) >= 0) {
3189  mpfr_class t(std::max(mpfr_get_prec(s_), mpfr_get_prec(x_)));
3190  mpfr_gamma_inc(t.get_mpfr_t(), s_, x_, MPFR_RNDN);
3191  return real_mpfr(std::move(t));
3192  } else {
3193  throw NotImplementedError("Not implemented.");
3194  }
3195 #endif
3196 #endif
3197  }
3198  return make_rcp<const UpperGamma>(s, x);
3199 }
3200 
3201 bool LogGamma::is_canonical(const RCP<const Basic> &arg) const
3202 {
3203  if (is_a<Integer>(*arg)) {
3204  RCP<const Integer> arg_int = rcp_static_cast<const Integer>(arg);
3205  if (not arg_int->is_positive()) {
3206  return false;
3207  }
3208  if (eq(*integer(1), *arg_int) or eq(*integer(2), *arg_int)
3209  or eq(*integer(3), *arg_int)) {
3210  return false;
3211  }
3212  }
3213  return true;
3214 }
3215 
3216 RCP<const Basic> LogGamma::rewrite_as_gamma() const
3217 {
3218  return log(gamma(get_arg()));
3219 }
3220 
3221 RCP<const Basic> LogGamma::create(const RCP<const Basic> &arg) const
3222 {
3223  return loggamma(arg);
3224 }
3225 
3226 RCP<const Basic> loggamma(const RCP<const Basic> &arg)
3227 {
3228  if (is_a<Integer>(*arg)) {
3229  RCP<const Integer> arg_int = rcp_static_cast<const Integer>(arg);
3230  if (not arg_int->is_positive()) {
3231  return Inf;
3232  }
3233  if (eq(*integer(1), *arg_int) or eq(*integer(2), *arg_int)) {
3234  return zero;
3235  } else if (eq(*integer(3), *arg_int)) {
3236  return log(integer(2));
3237  }
3238  }
3239  return make_rcp<const LogGamma>(arg);
3240 }
3241 
3242 RCP<const Beta> Beta::from_two_basic(const RCP<const Basic> &x,
3243  const RCP<const Basic> &y)
3244 {
3245  if (x->__cmp__(*y) == -1) {
3246  return make_rcp<const Beta>(y, x);
3247  }
3248  return make_rcp<const Beta>(x, y);
3249 }
3250 
3251 bool Beta::is_canonical(const RCP<const Basic> &x, const RCP<const Basic> &y)
3252 {
3253  if (x->__cmp__(*y) == -1) {
3254  return false;
3255  }
3256  if (is_a<Integer>(*x)
3257  or (is_a<Rational>(*x)
3258  and (get_den(down_cast<const Rational &>(*x).as_rational_class()))
3259  == 2)) {
3260  if (is_a<Integer>(*y)
3261  or (is_a<Rational>(*y)
3262  and (get_den(
3263  down_cast<const Rational &>(*y).as_rational_class()))
3264  == 2)) {
3265  return false;
3266  }
3267  }
3268  return true;
3269 }
3270 
3271 RCP<const Basic> Beta::rewrite_as_gamma() const
3272 {
3273  return div(mul(gamma(get_arg1()), gamma(get_arg2())),
3274  gamma(add(get_arg1(), get_arg2())));
3275 }
3276 
3277 RCP<const Basic> Beta::create(const RCP<const Basic> &a,
3278  const RCP<const Basic> &b) const
3279 {
3280  return beta(a, b);
3281 }
3282 
3283 RCP<const Basic> beta(const RCP<const Basic> &x, const RCP<const Basic> &y)
3284 {
3285  // Only special values are being evaluated
3286  if (eq(*add(x, y), *one)) {
3287  return ComplexInf;
3288  }
3289 
3290  if (is_a<Integer>(*x)) {
3291  RCP<const Integer> x_int = rcp_static_cast<const Integer>(x);
3292  if (x_int->is_positive()) {
3293  if (is_a<Integer>(*y)) {
3294  RCP<const Integer> y_int = rcp_static_cast<const Integer>(y);
3295  if (y_int->is_positive()) {
3296  return div(
3297  mul(gamma_positive_int(x), gamma_positive_int(y)),
3298  gamma_positive_int(add(x, y)));
3299  } else {
3300  return ComplexInf;
3301  }
3302  } else if (is_a<Rational>(*y)) {
3303  RCP<const Rational> y_ = rcp_static_cast<const Rational>(y);
3304  if (get_den(y_->as_rational_class()) == 2) {
3305  return div(mul(gamma_positive_int(x), gamma_multiple_2(y)),
3306  gamma_multiple_2(add(x, y)));
3307  } else {
3308  return Beta::from_two_basic(x, y);
3309  }
3310  }
3311  } else {
3312  return ComplexInf;
3313  }
3314  }
3315 
3316  if (is_a<Integer>(*y)) {
3317  RCP<const Integer> y_int = rcp_static_cast<const Integer>(y);
3318  if (y_int->is_positive()) {
3319  if (is_a<Rational>(*x)) {
3320  RCP<const Rational> x_ = rcp_static_cast<const Rational>(x);
3321  if (get_den(x_->as_rational_class()) == 2) {
3322  return div(mul(gamma_positive_int(y), gamma_multiple_2(x)),
3323  gamma_multiple_2(add(x, y)));
3324  } else {
3325  return Beta::from_two_basic(x, y);
3326  }
3327  }
3328  } else {
3329  return ComplexInf;
3330  }
3331  }
3332 
3333  if (is_a<const Rational>(*x)
3334  and get_den(down_cast<const Rational &>(*x).as_rational_class()) == 2) {
3335  if (is_a<Integer>(*y)) {
3336  RCP<const Integer> y_int = rcp_static_cast<const Integer>(y);
3337  if (y_int->is_positive()) {
3338  return div(mul(gamma_multiple_2(x), gamma_positive_int(y)),
3339  gamma_multiple_2(add(x, y)));
3340  } else {
3341  return ComplexInf;
3342  }
3343  }
3344  if (is_a<const Rational>(*y)
3345  and get_den((down_cast<const Rational &>(*y)).as_rational_class())
3346  == 2) {
3347  return div(mul(gamma_multiple_2(x), gamma_multiple_2(y)),
3348  gamma_positive_int(add(x, y)));
3349  }
3350  }
3351  return Beta::from_two_basic(x, y);
3352 }
3353 
3354 bool PolyGamma::is_canonical(const RCP<const Basic> &n,
3355  const RCP<const Basic> &x)
3356 {
3357  if (is_a_Number(*x) and not(down_cast<const Number &>(*x)).is_positive()) {
3358  return false;
3359  }
3360  if (eq(*n, *zero)) {
3361  if (eq(*x, *one)) {
3362  return false;
3363  }
3364  if (is_a<Rational>(*x)) {
3365  auto x_ = rcp_static_cast<const Rational>(x);
3366  auto den = get_den(x_->as_rational_class());
3367  if (den == 2 or den == 3 or den == 4) {
3368  return false;
3369  }
3370  }
3371  }
3372  return true;
3373 }
3374 
3375 RCP<const Basic> PolyGamma::rewrite_as_zeta() const
3376 {
3377  if (not is_a<Integer>(*get_arg1())) {
3378  return rcp_from_this();
3379  }
3380  RCP<const Integer> n = rcp_static_cast<const Integer>(get_arg1());
3381  if (not(n->is_positive())) {
3382  return rcp_from_this();
3383  }
3384  if ((n->as_int() & 1) == 0) {
3385  return neg(mul(factorial(n->as_int()), zeta(add(n, one), get_arg2())));
3386  } else {
3387  return mul(factorial(n->as_int()), zeta(add(n, one), get_arg2()));
3388  }
3389 }
3390 
3391 RCP<const Basic> PolyGamma::create(const RCP<const Basic> &a,
3392  const RCP<const Basic> &b) const
3393 {
3394  return polygamma(a, b);
3395 }
3396 
3397 RCP<const Basic> polygamma(const RCP<const Basic> &n_,
3398  const RCP<const Basic> &x_)
3399 {
3400  // Only special values are being evaluated
3401  if (is_a_Number(*x_)
3402  and not(down_cast<const Number &>(*x_)).is_positive()) {
3403  return ComplexInf;
3404  }
3405  if (is_a<Integer>(*n_) and is_a<Integer>(*x_)) {
3406  auto n = down_cast<const Integer &>(*n_).as_int();
3407  auto x = down_cast<const Integer &>(*x_).as_int();
3408  if (n == 0) {
3409  return sub(harmonic(x - 1, 1), EulerGamma);
3410  } else if (n % 2 == 1) {
3411  return mul(factorial(n), zeta(add(n_, one), x_));
3412  }
3413  }
3414  if (eq(*n_, *zero)) {
3415  if (eq(*x_, *one)) {
3416  return neg(EulerGamma);
3417  }
3418  if (is_a<Rational>(*x_)) {
3419  RCP<const Rational> x = rcp_static_cast<const Rational>(x_);
3420  const auto den = get_den(x->as_rational_class());
3421  const auto num = get_num(x->as_rational_class());
3422  const integer_class r = num % den;
3423  RCP<const Basic> res;
3424  if (den == 2) {
3425  res = sub(mul(im2, log(i2)), EulerGamma);
3426  } else if (den == 3) {
3427  if (num == 1) {
3428  res = add(neg(div(div(pi, i2), sqrt(i3))),
3429  sub(div(mul(im3, log(i3)), i2), EulerGamma));
3430  } else {
3431  res = add(div(div(pi, i2), sqrt(i3)),
3432  sub(div(mul(im3, log(i3)), i2), EulerGamma));
3433  }
3434  } else if (den == 4) {
3435  if (num == 1) {
3436  res = add(div(pi, im2), sub(mul(im3, log(i2)), EulerGamma));
3437  } else {
3438  res = add(div(pi, i2), sub(mul(im3, log(i2)), EulerGamma));
3439  }
3440  } else {
3441  return make_rcp<const PolyGamma>(n_, x_);
3442  }
3443  rational_class a(0), f(r, den);
3444  for (unsigned long i = 0; i < (num - r) / den; ++i) {
3445  a += 1 / (f + i);
3446  }
3447  return add(Rational::from_mpq(a), res);
3448  }
3449  }
3450  return make_rcp<const PolyGamma>(n_, x_);
3451 }
3452 
3453 RCP<const Basic> digamma(const RCP<const Basic> &x)
3454 {
3455  return polygamma(zero, x);
3456 }
3457 
3458 RCP<const Basic> trigamma(const RCP<const Basic> &x)
3459 {
3460  return polygamma(one, x);
3461 }
3462 
3463 Abs::Abs(const RCP<const Basic> &arg) : OneArgFunction(arg)
3464 {
3465  SYMENGINE_ASSIGN_TYPEID()
3466  SYMENGINE_ASSERT(is_canonical(arg))
3467 }
3468 
3469 bool Abs::is_canonical(const RCP<const Basic> &arg) const
3470 {
3471  if (is_a<Integer>(*arg) or is_a<Rational>(*arg) or is_a<Complex>(*arg))
3472  return false;
3473  if (is_a_Number(*arg) and not down_cast<const Number &>(*arg).is_exact()) {
3474  return false;
3475  }
3476  if (is_a<Abs>(*arg)) {
3477  return false;
3478  }
3479 
3480  if (could_extract_minus(*arg)) {
3481  return false;
3482  }
3483 
3484  return true;
3485 }
3486 
3487 RCP<const Basic> Abs::create(const RCP<const Basic> &arg) const
3488 {
3489  return abs(arg);
3490 }
3491 
3492 RCP<const Basic> abs(const RCP<const Basic> &arg)
3493 {
3494  if (is_a<Integer>(*arg)) {
3495  RCP<const Integer> arg_ = rcp_static_cast<const Integer>(arg);
3496  if (arg_->is_negative()) {
3497  return arg_->neg();
3498  } else {
3499  return arg_;
3500  }
3501  } else if (is_a<Rational>(*arg)) {
3502  RCP<const Rational> arg_ = rcp_static_cast<const Rational>(arg);
3503  if (arg_->is_negative()) {
3504  return arg_->neg();
3505  } else {
3506  return arg_;
3507  }
3508  } else if (is_a<Complex>(*arg)) {
3509  RCP<const Complex> arg_ = rcp_static_cast<const Complex>(arg);
3510  return sqrt(Rational::from_mpq(arg_->real_ * arg_->real_
3511  + arg_->imaginary_ * arg_->imaginary_));
3512  } else if (is_a_Number(*arg)
3513  and not down_cast<const Number &>(*arg).is_exact()) {
3514  return down_cast<const Number &>(*arg).get_eval().abs(*arg);
3515  }
3516  if (is_a<Abs>(*arg)) {
3517  return arg;
3518  }
3519 
3520  RCP<const Basic> d;
3521  handle_minus(arg, outArg(d));
3522  return make_rcp<const Abs>(d);
3523 }
3524 
3525 Max::Max(const vec_basic &&arg) : MultiArgFunction(std::move(arg))
3526 {
3527  SYMENGINE_ASSIGN_TYPEID()
3528  SYMENGINE_ASSERT(is_canonical(get_vec()))
3529 }
3530 
3531 bool Max::is_canonical(const vec_basic &arg) const
3532 {
3533  if (arg.size() < 2)
3534  return false;
3535 
3536  bool non_number_exists = false;
3537 
3538  for (const auto &p : arg) {
3539  if (is_a<Complex>(*p) or is_a<Max>(*p))
3540  return false;
3541  if (not is_a_Number(*p))
3542  non_number_exists = true;
3543  }
3544  if (not std::is_sorted(arg.begin(), arg.end(), RCPBasicKeyLess()))
3545  return false;
3546 
3547  return non_number_exists; // all arguments cant be numbers
3548 }
3549 
3550 RCP<const Basic> Max::create(const vec_basic &a) const
3551 {
3552  return max(a);
3553 }
3554 
3555 RCP<const Basic> max(const vec_basic &arg)
3556 {
3557  bool number_set = false;
3558  RCP<const Number> max_number, difference;
3559  set_basic new_args;
3560 
3561  for (const auto &p : arg) {
3562  if (is_a<Complex>(*p))
3563  throw SymEngineException("Complex can't be passed to max!");
3564 
3565  if (is_a_Number(*p)) {
3566  if (not number_set) {
3567  max_number = rcp_static_cast<const Number>(p);
3568 
3569  } else {
3570  if (eq(*p, *Inf)) {
3571  return Inf;
3572  } else if (eq(*p, *NegInf)) {
3573  continue;
3574  }
3575  difference = down_cast<const Number &>(*p).sub(*max_number);
3576 
3577  if (difference->is_zero() and not difference->is_exact()) {
3578  if (max_number->is_exact())
3579  max_number = rcp_static_cast<const Number>(p);
3580  } else if (difference->is_positive()) {
3581  max_number = rcp_static_cast<const Number>(p);
3582  }
3583  }
3584  number_set = true;
3585 
3586  } else if (is_a<Max>(*p)) {
3587  for (const auto &l : down_cast<const Max &>(*p).get_args()) {
3588  if (is_a_Number(*l)) {
3589  if (not number_set) {
3590  max_number = rcp_static_cast<const Number>(l);
3591 
3592  } else {
3593  difference = rcp_static_cast<const Number>(l)->sub(
3594  *max_number);
3595 
3596  if (difference->is_zero()
3597  and not difference->is_exact()) {
3598  if (max_number->is_exact())
3599  max_number = rcp_static_cast<const Number>(l);
3600  } else if (difference->is_positive()) {
3601  max_number = rcp_static_cast<const Number>(l);
3602  }
3603  }
3604  number_set = true;
3605  } else {
3606  new_args.insert(l);
3607  }
3608  }
3609  } else {
3610  new_args.insert(p);
3611  }
3612  }
3613 
3614  if (number_set)
3615  new_args.insert(max_number);
3616 
3617  vec_basic final_args(new_args.size());
3618  std::copy(new_args.begin(), new_args.end(), final_args.begin());
3619 
3620  if (final_args.size() > 1) {
3621  return make_rcp<const Max>(std::move(final_args));
3622  } else if (final_args.size() == 1) {
3623  return final_args[0];
3624  } else {
3625  throw SymEngineException("Empty vec_basic passed to max!");
3626  }
3627 }
3628 
3629 Min::Min(const vec_basic &&arg) : MultiArgFunction(std::move(arg))
3630 {
3631  SYMENGINE_ASSIGN_TYPEID()
3632  SYMENGINE_ASSERT(is_canonical(get_vec()))
3633 }
3634 
3635 bool Min::is_canonical(const vec_basic &arg) const
3636 {
3637  if (arg.size() < 2)
3638  return false;
3639 
3640  bool non_number_exists = false;
3641 
3642  for (const auto &p : arg) {
3643  if (is_a<Complex>(*p) or is_a<Min>(*p))
3644  return false;
3645  if (not is_a_Number(*p))
3646  non_number_exists = true;
3647  }
3648  if (not std::is_sorted(arg.begin(), arg.end(), RCPBasicKeyLess()))
3649  return false;
3650 
3651  return non_number_exists; // all arguments cant be numbers
3652 }
3653 
3654 RCP<const Basic> Min::create(const vec_basic &a) const
3655 {
3656  return min(a);
3657 }
3658 
3659 RCP<const Basic> min(const vec_basic &arg)
3660 {
3661  bool number_set = false;
3662  RCP<const Number> min_number, difference;
3663  set_basic new_args;
3664 
3665  for (const auto &p : arg) {
3666  if (is_a<Complex>(*p))
3667  throw SymEngineException("Complex can't be passed to min!");
3668 
3669  if (is_a_Number(*p)) {
3670  if (not number_set) {
3671  min_number = rcp_static_cast<const Number>(p);
3672 
3673  } else {
3674  if (eq(*p, *Inf)) {
3675  continue;
3676  } else if (eq(*p, *NegInf)) {
3677  return NegInf;
3678  }
3679  difference = min_number->sub(*rcp_static_cast<const Number>(p));
3680 
3681  if (difference->is_zero() and not difference->is_exact()) {
3682  if (min_number->is_exact())
3683  min_number = rcp_static_cast<const Number>(p);
3684  } else if (difference->is_positive()) {
3685  min_number = rcp_static_cast<const Number>(p);
3686  }
3687  }
3688  number_set = true;
3689 
3690  } else if (is_a<Min>(*p)) {
3691  for (const auto &l : down_cast<const Min &>(*p).get_args()) {
3692  if (is_a_Number(*l)) {
3693  if (not number_set) {
3694  min_number = rcp_static_cast<const Number>(l);
3695 
3696  } else {
3697  difference = min_number->sub(
3698  *rcp_static_cast<const Number>(l));
3699 
3700  if (difference->is_zero()
3701  and not difference->is_exact()) {
3702  if (min_number->is_exact())
3703  min_number = rcp_static_cast<const Number>(l);
3704  } else if (difference->is_positive()) {
3705  min_number = rcp_static_cast<const Number>(l);
3706  }
3707  }
3708  number_set = true;
3709  } else {
3710  new_args.insert(l);
3711  }
3712  }
3713  } else {
3714  new_args.insert(p);
3715  }
3716  }
3717 
3718  if (number_set)
3719  new_args.insert(min_number);
3720 
3721  vec_basic final_args(new_args.size());
3722  std::copy(new_args.begin(), new_args.end(), final_args.begin());
3723 
3724  if (final_args.size() > 1) {
3725  return make_rcp<const Min>(std::move(final_args));
3726  } else if (final_args.size() == 1) {
3727  return final_args[0];
3728  } else {
3729  throw SymEngineException("Empty vec_basic passed to min!");
3730  }
3731 }
3732 
3733 UnevaluatedExpr::UnevaluatedExpr(const RCP<const Basic> &arg)
3734  : OneArgFunction(arg)
3735 {
3736  SYMENGINE_ASSIGN_TYPEID()
3737  SYMENGINE_ASSERT(is_canonical(arg))
3738 }
3739 
3740 bool UnevaluatedExpr::is_canonical(const RCP<const Basic> &arg) const
3741 {
3742  return true;
3743 }
3744 
3745 RCP<const Basic> UnevaluatedExpr::create(const RCP<const Basic> &arg) const
3746 {
3747  return make_rcp<const UnevaluatedExpr>(arg);
3748 }
3749 
3750 RCP<const Basic> unevaluated_expr(const RCP<const Basic> &arg)
3751 {
3752  return make_rcp<const UnevaluatedExpr>(arg);
3753 }
3754 
3755 } // namespace SymEngine
T begin(T... args)
T cbrt(T... args)
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1708
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1388
ACos(const RCP< const Basic > &arg)
ACos Constructor.
Definition: functions.cpp:1382
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2450
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2627
ACosh(const RCP< const Basic > &arg)
ACosh Constructor.
Definition: functions.cpp:2444
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1552
ACot(const RCP< const Basic > &arg)
ACot Constructor.
Definition: functions.cpp:1546
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1718
ACoth(const RCP< const Basic > &arg)
ACoth Constructor.
Definition: functions.cpp:2514
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2637
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2520
ACsc(const RCP< const Basic > &arg)
ACsc Constructor.
Definition: functions.cpp:1464
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1470
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1728
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2622
ACsch(const RCP< const Basic > &arg)
ACsch Constructor.
Definition: functions.cpp:2400
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2406
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1723
ASec(const RCP< const Basic > &arg)
ASec Constructor.
Definition: functions.cpp:1424
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1430
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2642
ASech(const RCP< const Basic > &arg)
ASech Constructor.
Definition: functions.cpp:2552
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2558
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1703
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1346
ASin(const RCP< const Basic > &arg)
ASin Constructor.
Definition: functions.cpp:1340
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2617
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2360
ASinh(const RCP< const Basic > &arg)
ASinh Constructor.
Definition: functions.cpp:2354
RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const override
Definition: functions.cpp:1608
bool is_canonical(const RCP< const Basic > &num, const RCP< const Basic > &den) const
Definition: functions.cpp:1595
ATan2(const RCP< const Basic > &num, const RCP< const Basic > &den)
ATan2 Constructor.
Definition: functions.cpp:1588
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1510
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1713
ATan(const RCP< const Basic > &arg)
ATan Constructor.
Definition: functions.cpp:1504
ATanh(const RCP< const Basic > &arg)
ATanh Constructor.
Definition: functions.cpp:2472
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2632
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2478
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:3487
Abs(const RCP< const Basic > &arg)
Abs Constructor.
Definition: functions.cpp:3463
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:3469
The base class for representing addition in symbolic expressions.
Definition: add.h:27
static RCP< const Basic > from_dict(const RCP< const Number > &coef, umap_basic_num &&d)
Create an appropriate instance from dictionary quickly.
Definition: add.cpp:140
const RCP< const Number > & get_coef() const
Definition: add.h:142
The lowest unit of symbolic representation.
Definition: basic.h:97
static RCP< const Beta > from_two_basic(const RCP< const Basic > &x, const RCP< const Basic > &y)
return Beta with ordered arguments
Definition: functions.cpp:3242
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
bool is_canonical(const RCP< const Basic > &s, const RCP< const Basic > &x)
Definition: functions.cpp:3251
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:700
Ceiling(const RCP< const Basic > &arg)
Ceiling Constructor.
Definition: functions.cpp:665
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:671
ComplexBase Class for deriving all complex classes.
Definition: complex.h:16
Conjugate(const RCP< const Basic > &arg)
Conjugate constructor.
Definition: functions.cpp:92
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:144
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:98
Cos(const RCP< const Basic > &arg)
Cos Constructor.
Definition: functions.cpp:921
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1678
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:927
Cosh(const RCP< const Basic > &arg)
Cosh Constructor.
Definition: functions.cpp:2190
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2196
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2597
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1059
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1688
Cot(const RCP< const Basic > &arg)
Cot Constructor.
Definition: functions.cpp:1053
Coth(const RCP< const Basic > &arg)
Coth Constructor.
Definition: functions.cpp:2311
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2612
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2317
Csc(const RCP< const Basic > &arg)
Csc Constructor.
Definition: functions.cpp:1117
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1123
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1698
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2592
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2153
Csch(const RCP< const Basic > &arg)
Csch Constructor.
Definition: functions.cpp:2147
hash_t __hash__() const override
Definition: functions.cpp:1998
bool __eq__(const Basic &o) const override
Test equality.
Definition: functions.cpp:2008
multiset_basic x_
The expression to be differentiated.
Definition: functions.h:701
int compare(const Basic &o) const override
Definition: functions.cpp:2017
bool is_canonical(const RCP< const Basic > &s) const
Definition: functions.cpp:2842
virtual RCP< const Basic > create(const RCP< const Basic > &arg) const=0
Method to construct classes with canonicalization.
Dirichlet_eta(const RCP< const Basic > &s)
Dirichlet_eta Constructor.
Definition: functions.cpp:2836
RCP< const Basic > rewrite_as_zeta() const
Rewrites in the form of zeta.
Definition: functions.cpp:2851
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2886
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2874
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2922
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2910
Floor(const RCP< const Basic > &arg)
Floor Constructor.
Definition: functions.cpp:571
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:606
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:577
FunctionSymbol(std::string name, const vec_basic &arg)
FunctionSymbol Constructors.
Definition: functions.cpp:1864
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2953
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2968
Gamma(const RCP< const Basic > &arg)
Gamma Constructor.
Definition: functions.cpp:2947
Integer Class.
Definition: integer.h:19
bool is_canonical(const RCP< const Basic > &i, const RCP< const Basic > &j) const
Definition: functions.cpp:2655
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
KroneckerDelta(const RCP< const Basic > &i, const RCP< const Basic > &j)
KroneckerDelta Constructor.
Definition: functions.cpp:2647
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1841
LambertW(const RCP< const Basic > &arg)
LambertW Constructor.
Definition: functions.cpp:1822
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1828
bool is_canonical(const vec_basic &arg) const
Definition: functions.cpp:2711
LeviCivita(const vec_basic &&arg)
LeviCivita Constructor.
Definition: functions.cpp:2705
RCP< const Basic > create(const vec_basic &arg) const override
Definition: functions.cpp:2729
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:3221
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:3201
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1741
Log(const RCP< const Basic > &arg)
Log Constructor.
Definition: functions.cpp:1735
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1769
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
The lower incomplete gamma function.
LowerGamma(const RCP< const Basic > &s, const RCP< const Basic > &x)
LowerGamma Constructor.
Definition: functions.cpp:3037
bool is_canonical(const RCP< const Basic > &s, const RCP< const Basic > &x) const
Definition: functions.cpp:3044
bool is_canonical(const vec_basic &arg) const
Definition: functions.cpp:3531
RCP< const Basic > create(const vec_basic &arg) const override
Definition: functions.cpp:3550
Max(const vec_basic &&arg)
Max Constructor.
Definition: functions.cpp:3525
bool is_canonical(const vec_basic &arg) const
Definition: functions.cpp:3635
Min(const vec_basic &&arg)
Min Constructor.
Definition: functions.cpp:3629
RCP< const Basic > create(const vec_basic &arg) const override
Definition: functions.cpp:3654
static RCP< const Basic > from_dict(const RCP< const Number > &coef, map_basic_basic &&d)
Create a Mul from a dict.
Definition: mul.cpp:115
virtual RCP< const Basic > create(const RCP< const Basic > &arg) const =0
Method to construct classes with canonicalization.
RCP< const Basic > get_arg() const
Definition: functions.h:36
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
Rational Class.
Definition: rational.h:16
static RCP< const Number > from_mpq(const rational_class &i)
Definition: rational.cpp:23
const rational_class & as_rational_class() const
Convert to rational_class.
Definition: rational.h:50
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1693
Sec(const RCP< const Basic > &arg)
Sec Constructor.
Definition: functions.cpp:1181
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:1187
Sech(const RCP< const Basic > &arg)
Sech Constructor.
Definition: functions.cpp:2229
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2602
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2235
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:499
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:522
Sign(const RCP< const Basic > &arg)
Sign constructor.
Definition: functions.cpp:493
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1673
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:859
Sin(const RCP< const Basic > &arg)
Sin Constructor.
Definition: functions.cpp:853
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2111
Sinh(const RCP< const Basic > &arg)
Sinh Constructor.
Definition: functions.cpp:2105
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2587
vec_basic get_args() const override
Returns the list of arguments.
Definition: functions.cpp:2093
int compare(const Basic &o) const override
Definition: functions.cpp:2064
hash_t __hash__() const override
Definition: functions.cpp:2045
bool __eq__(const Basic &o) const override
Test equality.
Definition: functions.cpp:2056
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:1683
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:993
Tan(const RCP< const Basic > &arg)
Tan Constructor.
Definition: functions.cpp:987
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:2274
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:2607
Tanh(const RCP< const Basic > &arg)
Tanh Constructor.
Definition: functions.cpp:2268
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:765
Truncate(const RCP< const Basic > &arg)
Truncate Constructor.
Definition: functions.cpp:759
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:794
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const =0
Method to construct classes with canonicalization.
RCP< const Basic > get_arg1() const
Definition: functions.h:91
RCP< const Basic > get_arg2() const
Definition: functions.h:96
RCP< const Basic > create(const RCP< const Basic > &arg) const override
Definition: functions.cpp:3745
UnevaluatedExpr(const RCP< const Basic > &arg)
UnevaluatedExpr Constructor.
Definition: functions.cpp:3733
bool is_canonical(const RCP< const Basic > &arg) const
Definition: functions.cpp:3740
UpperGamma(const RCP< const Basic > &s, const RCP< const Basic > &x)
UpperGamma Constructor.
Definition: functions.cpp:3120
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
The upper incomplete gamma function.
bool is_canonical(const RCP< const Basic > &s, const RCP< const Basic > &x) const
Definition: functions.cpp:3127
Zeta(const RCP< const Basic > &s, const RCP< const Basic > &a)
Zeta Constructor.
Definition: functions.cpp:2768
virtual RCP< const Basic > create(const RCP< const Basic > &a, const RCP< const Basic > &b) const=0
Method to construct classes with canonicalization.
bool is_canonical(const RCP< const Basic > &s, const RCP< const Basic > &a) const
Definition: functions.cpp:2779
T copy(T... args)
T end(T... args)
T find(T... args)
T insert(T... args)
T is_sorted(T... args)
T max(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
void get_num_den(const Rational &rat, const Ptr< RCP< const Integer >> &num, const Ptr< RCP< const Integer >> &den)
returns the num and den of rational rat as RCP<const Integer>
Definition: rational.cpp:130
RCP< const Basic > acos(const RCP< const Basic > &arg)
Canonicalize ACos:
Definition: functions.cpp:1402
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
Definition: mul.cpp:431
std::enable_if< std::is_integral< T >::value, RCP< const Integer > >::type integer(T i)
Definition: integer.h:197
RCP< const Basic > sec(const RCP< const Basic > &arg)
Canonicalize Sec:
Definition: functions.cpp:1202
RCP< const Number > mulnum(const RCP< const Number > &self, const RCP< const Number > &other)
Multiply self and other
Definition: number.h:93
RCP< const Basic > polygamma(const RCP< const Basic > &n_, const RCP< const Basic > &x_)
Canonicalize PolyGamma.
Definition: functions.cpp:3397
RCP< const Number > pownum(const RCP< const Number > &self, const RCP< const Number > &other)
Raise self to power other
Definition: number.h:105
RCP< const Basic > beta(const RCP< const Basic > &x, const RCP< const Basic > &y)
Canonicalize Beta:
Definition: functions.cpp:3283
RCP< const Basic > zeta(const RCP< const Basic > &s, const RCP< const Basic > &a)
Create a new Zeta instance:
Definition: functions.cpp:2800
RCP< const Basic > max(const vec_basic &arg)
Canonicalize Max:
Definition: functions.cpp:3555
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Basic > coth(const RCP< const Basic > &arg)
Canonicalize Coth:
Definition: functions.cpp:2333
bool get_pi_shift(const RCP< const Basic > &arg, const Ptr< RCP< const Number >> &n, const Ptr< RCP< const Basic >> &x)
Definition: functions.cpp:203
RCP< const Basic > sign(const RCP< const Basic > &arg)
Canonicalize Sign.
Definition: functions.cpp:527
RCP< const Basic > atan2(const RCP< const Basic > &num, const RCP< const Basic > &den)
Canonicalize ATan2:
Definition: functions.cpp:1614
RCP< const Basic > ceiling(const RCP< const Basic > &arg)
Canonicalize Ceiling:
Definition: functions.cpp:705
RCP< const Number > divnum(const RCP< const Number > &self, const RCP< const Number > &other)
Divide self and other
Definition: number.h:99
RCP< const Number > subnum(const RCP< const Number > &self, const RCP< const Number > &other)
Subtract self and other
Definition: number.h:87
RCP< const Basic > abs(const RCP< const Basic > &arg)
Canonicalize Abs:
Definition: functions.cpp:3492
RCP< const Basic > acsc(const RCP< const Basic > &arg)
Canonicalize ACsc:
Definition: functions.cpp:1484
RCP< const Integer > quotient_f(const Integer &n, const Integer &d)
Definition: ntheory.cpp:94
bool inverse_lookup(const umap_basic_basic &d, const RCP< const Basic > &t, const Ptr< RCP< const Basic >> &index)
Definition: functions.cpp:480
RCP< const Basic > sech(const RCP< const Basic > &arg)
Canonicalize Sech:
Definition: functions.cpp:2251
RCP< const Basic > gamma(const RCP< const Basic > &arg)
Canonicalize Gamma:
Definition: functions.cpp:3014
RCP< const Basic > sub(const RCP< const Basic > &a, const RCP< const Basic > &b)
Substracts b from a.
Definition: add.cpp:495
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 Integer > mod_f(const Integer &n, const Integer &d)
modulo round toward -inf
Definition: ntheory.cpp:87
RCP< const Integer > quotient(const Integer &n, const Integer &d)
Definition: ntheory.cpp:72
RCP< const Basic > asin(const RCP< const Basic > &arg)
Canonicalize ASin:
Definition: functions.cpp:1360
RCP< const Basic > acoth(const RCP< const Basic > &arg)
Canonicalize ACoth:
Definition: functions.cpp:2534
RCP< const Basic > tan(const RCP< const Basic > &arg)
Canonicalize Tan:
Definition: functions.cpp:1007
RCP< const Basic > cosh(const RCP< const Basic > &arg)
Canonicalize Cosh:
Definition: functions.cpp:2212
RCP< const Basic > asec(const RCP< const Basic > &arg)
Canonicalize ASec:
Definition: functions.cpp:1444
RCP< const Basic > acsch(const RCP< const Basic > &arg)
Canonicalize ACsch:
Definition: functions.cpp:2422
bool could_extract_minus(const Basic &arg)
Definition: functions.cpp:325
RCP< const Basic > atan(const RCP< const Basic > &arg)
Canonicalize ATan:
Definition: functions.cpp:1524
RCP< const Basic > asinh(const RCP< const Basic > &arg)
Canonicalize ASinh:
Definition: functions.cpp:2376
RCP< const Basic > tanh(const RCP< const Basic > &arg)
Canonicalize Tanh:
Definition: functions.cpp:2290
RCP< const Basic > cot(const RCP< const Basic > &arg)
Canonicalize Cot:
Definition: functions.cpp:1073
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition: mul.cpp:352
void insert(T1 &m, const T2 &first, const T3 &second)
Definition: dict.h:83
RCP< const Basic > atanh(const RCP< const Basic > &arg)
Canonicalize ATanh:
Definition: functions.cpp:2494
RCP< const Basic > floor(const RCP< const Basic > &arg)
Canonicalize Floor:
Definition: functions.cpp:611
RCP< const Basic > erfc(const RCP< const Basic > &arg)
Canonicalize Erfc:
Definition: functions.cpp:2927
RCP< const Basic > levi_civita(const vec_basic &arg)
Canonicalize LeviCivita:
Definition: functions.cpp:2747
RCP< const Basic > acosh(const RCP< const Basic > &arg)
Canonicalize ACosh:
Definition: functions.cpp:2461
RCP< const Basic > lowergamma(const RCP< const Basic > &s, const RCP< const Basic > &x)
Canonicalize LowerGamma:
Definition: functions.cpp:3070
RCP< const Basic > truncate(const RCP< const Basic > &arg)
Canonicalize Truncate:
Definition: functions.cpp:799
RCP< const Basic > loggamma(const RCP< const Basic > &arg)
Canonicalize LogGamma:
Definition: functions.cpp:3226
RCP< const Basic > cos(const RCP< const Basic > &arg)
Canonicalize Cos:
Definition: functions.cpp:942
RCP< const Basic > log(const RCP< const Basic > &arg)
Returns the Natural Logarithm from argument arg
Definition: functions.cpp:1774
RCP< const Basic > csc(const RCP< const Basic > &arg)
Canonicalize Csc:
Definition: functions.cpp:1138
RCP< const Basic > dirichlet_eta(const RCP< const Basic > &s)
Create a new Dirichlet_eta instance:
Definition: functions.cpp:2861
RCP< const Integer > factorial(unsigned long n)
Factorial.
Definition: ntheory.cpp:154
RCP< const Basic > add(const RCP< const Basic > &a, const RCP< const Basic > &b)
Adds two objects (safely).
Definition: add.cpp:425
RCP< const Basic > csch(const RCP< const Basic > &arg)
Canonicalize Csch:
Definition: functions.cpp:2169
int unified_compare(const T &a, const T &b)
Definition: dict.h:205
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:3659
bool is_a_Complex(const Basic &b)
Definition: complex.h:24
RCP< const Basic > erf(const RCP< const Basic > &arg)
Canonicalize Erf:
Definition: functions.cpp:2891
RCP< const Number > bernoulli(unsigned long n)
Definition: ntheory.cpp:496
RCP< const Basic > trig_to_sqrt(const RCP< const Basic > &arg)
Definition: functions.cpp:1246
RCP< const Basic > asech(const RCP< const Basic > &arg)
Canonicalize ASech:
Definition: functions.cpp:2571
RCP< const Basic > lambertw(const RCP< const Basic > &arg)
Create a new LambertW instance:
Definition: functions.cpp:1846
RCP< const Number > harmonic(unsigned long n, long m)
Computes the sum of the inverses of the first perfect mth powers.
Definition: ntheory.cpp:523
RCP< const Basic > sinh(const RCP< const Basic > &arg)
Canonicalize Sinh:
Definition: functions.cpp:2127
RCP< const Basic > kronecker_delta(const RCP< const Basic > &i, const RCP< const Basic > &j)
Canonicalize KroneckerDelta:
Definition: functions.cpp:2675
RCP< const Basic > neg(const RCP< const Basic > &a)
Negation.
Definition: mul.cpp:443
RCP< const Basic > acot(const RCP< const Basic > &arg)
Canonicalize ACot:
Definition: functions.cpp:1566
RCP< const Basic > conjugate(const RCP< const Basic > &arg)
Canonicalize Conjugate.
Definition: functions.cpp:149
RCP< const Basic > sin(const RCP< const Basic > &arg)
Canonicalize Sin:
Definition: functions.cpp:874
RCP< const Basic > uppergamma(const RCP< const Basic > &s, const RCP< const Basic > &x)
Canonicalize UpperGamma:
Definition: functions.cpp:3153
STL namespace.
T pow(T... args)
T push_back(T... args)
T size(T... args)
T sqrt(T... args)
Our less operator (<):
Definition: basic.h:228