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