series.h
Go to the documentation of this file.
1 
6 #ifndef SYMENGINE_SERIES_H
7 #define SYMENGINE_SERIES_H
8 
9 #include <list>
10 
11 #include <symengine/integer.h>
12 #include <symengine/symengine_exception.h>
13 
14 namespace SymEngine
15 {
16 
18 {
19 public:
20  virtual RCP<const Basic> as_basic() const = 0;
21  virtual umap_int_basic as_dict() const = 0;
22  virtual RCP<const Basic> get_coeff(int) const = 0;
23  virtual unsigned get_degree() const = 0;
24  virtual const std::string &get_var() const = 0;
25 };
26 
27 template <typename Poly, typename Coeff, typename Series>
29 {
30 protected:
31  const Poly p_;
32  const std::string var_;
33  const unsigned degree_;
34 
35 public:
36  inline SeriesBase(Poly p, std::string var, unsigned degree)
37  : p_(std::move(p)), var_(var), degree_(degree)
38  {
39  }
40  inline unsigned get_degree() const override
41  {
42  return degree_;
43  }
44 
45  inline const std::string &get_var() const override
46  {
47  return var_;
48  }
49 
50  inline const Poly &get_poly() const
51  {
52  return p_;
53  }
54 
55  inline bool is_zero() const override
56  {
57  return false;
58  }
59 
60  inline bool is_one() const override
61  {
62  return false;
63  }
64 
65  inline bool is_minus_one() const override
66  {
67  return false;
68  }
69 
70  inline bool is_negative() const override
71  {
72  return false;
73  }
74 
75  inline bool is_positive() const override
76  {
77  return false;
78  }
79 
80  inline bool is_complex() const override
81  {
82  return false;
83  }
84 
85  inline bool __eq__(const Basic &o) const override
86  {
87  return (is_a<Series>(o) and var_ == down_cast<const Series &>(o).var_
88  and p_ == down_cast<const Series &>(o).p_
89  and degree_ == down_cast<const Series &>(o).degree_);
90  }
91 
92  RCP<const Number> add(const Number &other) const override
93  {
94  if (is_a<Series>(other)) {
95  const Series &o = down_cast<const Series &>(other);
96  auto deg = std::min(degree_, o.degree_);
97  if (var_ != o.var_) {
98  throw NotImplementedError(
99  "Multivariate Series not implemented");
100  }
101  return make_rcp<Series>(Poly(p_ + o.p_), var_, deg);
102  } else if (other.get_type_code() < Series::type_code_id) {
103  Poly p = Series::series(other.rcp_from_this(), var_, degree_)->p_;
104  return make_rcp<Series>(Poly(p_ + p), var_, degree_);
105  } else {
106  return other.add(*this);
107  }
108  }
109 
110  RCP<const Number> mul(const Number &other) const override
111  {
112  if (is_a<Series>(other)) {
113  const Series &o = down_cast<const Series &>(other);
114  auto deg = std::min(degree_, o.degree_);
115  if (var_ != o.var_) {
116  throw NotImplementedError(
117  "Multivariate Series not implemented");
118  }
119  return make_rcp<Series>(Series::mul(p_, o.p_, deg), var_, deg);
120  } else if (other.get_type_code() < Series::type_code_id) {
121  Poly p = Series::series(other.rcp_from_this(), var_, degree_)->p_;
122  return make_rcp<Series>(Series::mul(p_, p, degree_), var_, degree_);
123  } else {
124  return other.mul(*this);
125  }
126  }
127 
128  RCP<const Number> pow(const Number &other) const override
129  {
130  auto deg = degree_;
131  Poly p;
132  if (is_a<Series>(other)) {
133  const Series &o = down_cast<const Series &>(other);
134  deg = std::min(deg, o.degree_);
135  if (var_ != o.var_) {
136  throw NotImplementedError(
137  "Multivariate Series not implemented");
138  }
139  p = o.p_;
140  } else if (is_a<Integer>(other)) {
141  if (other.is_negative()) {
142  p = Series::pow(
143  p_,
144  (numeric_cast<int>(
145  down_cast<const Integer &>(other).neg()->as_int())),
146  deg);
147  p = Series::series_invert(p, Series::var(var_), deg);
148  return make_rcp<Series>(p, var_, deg);
149  }
150  p = Series::pow(
151  p_,
152  numeric_cast<int>((down_cast<const Integer &>(other).as_int())),
153  deg);
154  return make_rcp<Series>(p, var_, deg);
155  } else if (other.get_type_code() < Series::type_code_id) {
156  p = Series::series(other.rcp_from_this(), var_, degree_)->p_;
157  } else {
158  return other.rpow(*this);
159  }
160  p = Series::series_exp(
161  Poly(p * Series::series_log(p_, Series::var(var_), deg)),
162  Series::var(var_), deg);
163  return make_rcp<Series>(p, var_, deg);
164  }
165 
166  RCP<const Number> rpow(const Number &other) const override
167  {
168  if (other.get_type_code() < Series::type_code_id) {
169  Poly p = Series::series(other.rcp_from_this(), var_, degree_)->p_;
170  p = Series::series_exp(
171  Poly(p_ * Series::series_log(p, Series::var(var_), degree_)),
172  Series::var(var_), degree_);
173  return make_rcp<Series>(p, var_, degree_);
174  } else {
175  throw SymEngineException("Unknown type");
176  }
177  }
178 
179  static inline const std::list<unsigned int> &step_list(unsigned int prec)
180  {
181  static std::list<unsigned int> steps;
182  if (not steps.empty()) {
183  if (*(steps.rbegin()) == prec)
184  return steps;
185  else
186  steps.clear();
187  }
188 
189  unsigned int tprec = prec;
190  while (tprec > 4) {
191  tprec = 2 + tprec / 2;
192  steps.push_front(tprec);
193  }
194  steps.push_front(2);
195  steps.push_back(prec);
196  return steps;
197  }
198 
199  static inline Poly series_invert(const Poly &s, const Poly &var,
200  unsigned int prec)
201  {
202  if (s == 0)
203  throw DivisionByZeroError(
204  "Series::series_invert: Division By Zero");
205  if (s == 1)
206  return Poly(1);
207  const int ldeg = Series::ldegree(s);
208  const Coeff co = Series::find_cf(s, var, ldeg);
209  Poly p(1 / co), ss = s;
210  if (ldeg != 0) {
211  ss = s * Series::pow(var, -ldeg, prec);
212  }
213  auto steps = step_list(prec);
214  for (const auto step : steps) {
215  p = Series::mul(2 - Series::mul(p, ss, step), p, step);
216  }
217  if (ldeg != 0) {
218  return p * Series::pow(var, -ldeg, prec);
219  } else {
220  return p;
221  }
222  }
223 
224  static inline Poly series_reverse(const Poly &s, const Poly &var,
225  unsigned int prec)
226  {
227  const Coeff co = Series::find_cf(s, var, 0);
228  if (co != 0)
229  throw SymEngineException("reversion of series with constant term");
230  const Coeff a = Series::find_cf(s, var, 1);
231  if (a == 0)
232  throw SymEngineException(
233  "reversion of series with zero term of degree one");
234  Poly r(var);
235  r /= a;
236  for (unsigned int i = 2; i < prec; i++) {
237  Poly sp = Series::subs(s, var, r, i + 1);
238  r -= Series::pow(var, i, i + 1) * Series::find_cf(sp, var, i) / a;
239  }
240  return r;
241  }
242 
243  static inline Poly series_nthroot(const Poly &s, int n, const Poly &var,
244  unsigned int prec)
245  {
246  if (n == 0)
247  return Poly(1);
248  if (n == 1)
249  return s;
250  if (n == -1)
251  return Series::series_invert(s, var, prec);
252 
253  const int ldeg = Series::ldegree(s);
254  if (ldeg % n != 0) {
255  throw NotImplementedError("Puiseux series not implemented.");
256  }
257  Poly ss = s;
258  if (ldeg != 0) {
259  ss = s * Series::pow(var, -ldeg, prec);
260  }
261  Coeff ct = Series::find_cf(ss, var, 0);
262  bool do_inv = false;
263  if (n < 0) {
264  n = -n;
265  do_inv = true;
266  }
267 
268  Coeff ctroot = Series::root(ct, n);
269  Poly res_p(1), sn = ss / ct;
270  auto steps = step_list(prec);
271  for (const auto step : steps) {
272  Poly t = Series::mul(Series::pow(res_p, n + 1, step), sn, step);
273  res_p += (res_p - t) / n;
274  }
275  if (ldeg != 0) {
276  res_p *= Series::pow(var, ldeg / n, prec);
277  }
278  if (do_inv)
279  return res_p / ctroot;
280  else
281  return Series::series_invert(res_p, var, prec) * ctroot;
282  }
283 
284  static inline Poly series_atan(const Poly &s, const Poly &var,
285  unsigned int prec)
286  {
287  Poly res_p(0);
288  if (s == 0)
289  return res_p;
290 
291  if (s == var) {
293  int sign = 1;
294  Poly monom(var), vsquare(var * var);
295  for (unsigned int i = 1; i < prec; i += 2, sign *= -1) {
296  res_p += monom * (Coeff(sign) / Coeff(i));
297  monom *= vsquare;
298  }
299  return res_p;
300  }
301  const Coeff c(Series::find_cf(s, var, 0));
302  const Poly p(Series::pow(s, 2, prec - 1) + 1);
303  res_p = Series::mul(Series::diff(s, var),
304  Series::series_invert(p, var, prec - 1), prec - 1);
305 
306  if (c == 0) {
307  // atan(s) = integrate(diff(s)*(1+s**2))
308  return Series::integrate(res_p, var);
309  } else {
310  return Series::integrate(res_p, var) + Series::atan(c);
311  }
312  }
313 
314  static inline Poly series_tan(const Poly &s, const Poly &var,
315  unsigned int prec)
316  {
317  Poly res_p(0), ss = s;
318  const Coeff c(Series::find_cf(s, var, 0));
319  if (c != 0) {
320  ss = s - c;
321  }
322 
323  // IDEA: use this to get tan(x) coefficients:
324  // # n -> [0, a(1), a(2), ..., a(n)] for n > 0.
325  // def A000182_list(n):
326  // ....T = [0 for i in range(1, n+2)]
327  // ....T[1] = 1
328  // ....for k in range(2, n+1):
329  // ........T[k] = (k-1)*T[k-1]
330  // ....for k in range(2, n+1):
331  // ........for j in range(k, n+1):
332  // ............T[j] = (j-k)*T[j-1]+(j-k+2)*T[j]
333  // ....return T
334  // Ref.: https://oeis.org/A000182
335 
336  auto steps = step_list(prec);
337  for (const auto step : steps) {
338  Poly t = Series::pow(res_p, 2, step) + 1;
339  res_p += Series::mul(ss - Series::series_atan(res_p, var, step), t,
340  step);
341  }
342 
343  if (c == 0) {
344  return res_p;
345  } else {
346  return Series::mul(
347  res_p + Series::tan(c),
348  Series::series_invert(1 + res_p * (-Series::tan(c)), var, prec),
349  prec);
350  }
351  }
352 
353  static inline Poly series_cot(const Poly &s, const Poly &var,
354  unsigned int prec)
355  {
356  return Series::series_invert(Series::series_tan(s, var, prec), var,
357  prec);
358  }
359 
360  static inline Poly _series_sin(const Poly &s, unsigned int prec)
361  {
362  Poly res_p(0), monom(s);
363  Poly ssquare = Series::mul(s, s, prec);
364  Coeff prod(1);
365  for (unsigned int i = 0; i < prec / 2; i++) {
366  const int j = 2 * i + 1;
367  if (i != 0)
368  prod /= 1 - j;
369  prod /= j;
370  res_p += Series::mul(monom, Poly(prod), prec);
371  monom = Series::mul(monom, ssquare, prec);
372  }
373  return res_p;
374  }
375 
376  static inline Poly series_sin(const Poly &s, const Poly &var,
377  unsigned int prec)
378  {
379  const Coeff c(Series::find_cf(s, var, 0));
380  if (c != 0) {
381  const Poly t = s - c;
382  return Series::cos(c) * _series_sin(t, prec)
383  + Series::sin(c) * _series_cos(t, prec);
384  } else {
385  return _series_sin(s, prec);
386  }
387 
388  // if (c == 0) {
389  // // return 2*t/(1+t**2)
390  // const Poly t(Series::series_tan(s / 2, var, prec)); //
391  // t = tan(s/2);
392  // const Poly t2(Series::pow(t, 2, prec));
393  // return Series::series_invert(t2 + 1, var, prec) * t * 2;
394  // } else {
395  // const Poly t(Series::series_tan((s - c) / 2, var, prec));
396  // // t = tan(s/2);
397  // const Poly t2(Series::pow(t, 2, prec));
398  // // return sin(c)*cos(s) + cos(c)*sin(s)
399  // return (-Series::sin(c)) * (t2 - 1) *
400  // Series::series_invert(t2 + 1, var, prec)
401  // + (Series::cos(c) * 2) * t * Series::series_invert(t2
402  // + 1, var, prec);
403  // }
404  }
405 
406  static inline Poly series_csc(const Poly &s, const Poly &var,
407  unsigned int prec)
408  {
409  return Series::series_invert(Series::series_sin(s, var, prec), var,
410  prec);
411  }
412 
413  static inline Poly series_asin(const Poly &s, const Poly &var,
414  unsigned int prec)
415  {
416  const Coeff c(Series::find_cf(s, var, 0));
417 
418  // asin(s) = integrate(sqrt(1/(1-s**2))*diff(s))
419  const Poly t(1 - Series::pow(s, 2, prec - 1));
420  const Poly res_p(Series::integrate(
421  Series::diff(s, var) * Series::series_nthroot(t, -2, var, prec - 1),
422  var));
423 
424  if (c != 0) {
425  return res_p + Series::asin(c);
426  } else {
427  return res_p;
428  }
429  }
430 
431  static inline Poly series_acos(const Poly &s, const Poly &var,
432  unsigned int prec)
433  {
434  const Coeff c(Series::find_cf(s, var, 0));
435  return Series::acos(c) - series_asin(s - c, var, prec);
436  }
437 
438  static inline Poly _series_cos(const Poly &s, unsigned int prec)
439  {
440  Poly res_p(1);
441  Poly ssquare = Series::mul(s, s, prec);
442  Poly monom(ssquare);
443  Coeff prod(1);
444  for (unsigned int i = 1; i <= prec / 2; i++) {
445  const int j = 2 * i;
446  if (i != 0)
447  prod /= 1 - j;
448  prod /= j;
449  res_p += Series::mul(monom, Poly(prod), prec);
450  monom = Series::mul(monom, ssquare, prec);
451  }
452  return res_p;
453  }
454 
455  static inline Poly series_cos(const Poly &s, const Poly &var,
456  unsigned int prec)
457  {
458  const Coeff c(Series::find_cf(s, var, 0));
459  if (c != 0) {
460  const Poly t = s - c;
461  return Series::cos(c) * _series_cos(t, prec)
462  - Series::sin(c) * _series_sin(t, prec);
463  } else {
464  return _series_cos(s, prec);
465  }
466  //
467  // if (c == 0) {
468  // // return (1-t**2)/(1+t**2)
469  // const Poly t(Series::series_tan(s / 2, var, prec)); //
470  // t = tan(s/2);
471  // const Poly t2(Series::pow(t, 2, prec));
472  // return Series::series_invert(t2 + 1, var, prec) * ((t2 -
473  // 1) * -1);
474  // } else {
475  // const Poly t(Series::series_tan((s - c)/ 2, var, prec));
476  // // t = tan(s/2);
477  // const Poly t2(Series::pow(t, 2, prec));
478  // // return cos(c)*cos(s) - sin(c)*sin(s)
479  // return (-Series::cos(c)) * (t2 - 1) *
480  // Series::series_invert(t2 + 1, var, prec)
481  // - Series::sin(c) * 2 * t * Series::series_invert(t2 +
482  // 1, var, prec);
483  // }
484  }
485 
486  static inline Poly series_sec(const Poly &s, const Poly &var,
487  unsigned int prec)
488  {
489  return Series::series_invert(Series::series_cos(s, var, prec), var,
490  prec);
491  }
492 
493  static inline Poly series_log(const Poly &s, const Poly &var,
494  unsigned int prec)
495  {
496  Poly res_p(0);
497  if (s == 1)
498  return res_p;
499  if (s == var + 1) {
501  Poly monom(var);
502  for (unsigned int i = 1; i < prec; i++) {
503  res_p += monom * Coeff(((i % 2) == 0) ? -1 : 1) / Coeff(i);
504  monom *= var;
505  }
506  return res_p;
507  }
508 
509  const Coeff c(Series::find_cf(s, var, 0));
510  res_p = Series::mul(Series::diff(s, var),
511  Series::series_invert(s, var, prec), prec - 1);
512  res_p = Series::integrate(res_p, var);
513 
514  if (c != 1) {
515  res_p += Series::log(c);
516  }
517  return res_p;
518  }
519 
520  static inline Poly series_exp(const Poly &s, const Poly &var,
521  unsigned int prec)
522  {
523  Poly res_p(1);
524  if (s == 0)
525  return res_p;
526 
527  if (s == var) {
529  Coeff coef(1);
530  Poly monom(var);
531  for (unsigned int i = 1; i < prec; i++) {
532  coef /= i;
533  res_p += monom * coef;
534  monom *= var;
535  }
536  return res_p;
537  }
538 
539  const Coeff c(Series::find_cf(s, var, 0));
540  Poly t = s + 1;
541  if (c != 0) {
542  // exp(s) = exp(c)*exp(s-c)
543  t = s - c + 1;
544  }
545  auto steps = step_list(prec);
546  for (const auto step : steps) {
547  res_p = Series::mul(res_p, t - Series::series_log(res_p, var, step),
548  step);
549  }
550  if (c != 0) {
551  return res_p * Series::exp(c);
552  } else {
553  return res_p;
554  }
555  }
556 
557  static inline Poly series_lambertw(const Poly &s, const Poly &var,
558  unsigned int prec)
559  {
560  if (Series::find_cf(s, var, 0) != 0)
561  throw NotImplementedError("lambertw(const) not Implemented");
562 
563  Poly p1(0);
564 
565  auto steps = step_list(prec);
566  for (const auto step : steps) {
567  const Poly e(Series::series_exp(p1, var, step));
568  const Poly p2(Series::mul(e, p1, step) - s);
569  const Poly p3(Series::series_invert(Series::mul(e, (p1 + 1), step),
570  var, step));
571  p1 -= Series::mul(p2, p3, step);
572  }
573  return p1;
574  }
575 
576  static inline Poly series_sinh(const Poly &s, const Poly &var,
577  unsigned int prec)
578  {
579  const Coeff c(Series::find_cf(s, var, 0));
580  const Poly p1(Series::series_exp(s - c, var, prec));
581  const Poly p2(Series::series_invert(p1, var, prec));
582 
583  if (c == 0) {
584  return (p1 - p2) / 2;
585  } else {
586  return Series::cosh(c) * (p1 - p2) / 2
587  + Series::sinh(c) * (p1 + p2) / 2;
588  }
589  }
590 
591  static inline Poly series_cosh(const Poly &s, const Poly &var,
592  unsigned int prec)
593  {
594  const Coeff c(Series::find_cf(s, var, 0));
595  const Poly p1(Series::series_exp(s - c, var, prec));
596  const Poly p2(Series::series_invert(p1, var, prec));
597 
598  if (c == 0) {
599  return (p1 + p2) / 2;
600  } else {
601  return Series::cosh(c) * (p1 + p2) / 2
602  + Series::sinh(c) * (p1 - p2) / 2;
603  }
604  }
605 
606  static inline Poly series_atanh(const Poly &s, const Poly &var,
607  unsigned int prec)
608  {
609  const Coeff c(Series::find_cf(s, var, 0));
610  const Poly p(1 - Series::pow(s, 2, prec - 1));
611  const Poly res_p(Series::mul(Series::diff(s, var),
612  Series::series_invert(p, var, prec - 1),
613  prec - 1));
614 
615  if (c == 0) {
616  return Series::integrate(res_p, var);
617  } else {
618  return Series::integrate(res_p, var) + Series::atanh(c);
619  }
620  }
621 
622  static inline Poly series_asinh(const Poly &s, const Poly &var,
623  unsigned int prec)
624  {
625  const Coeff c(Series::find_cf(s, var, 0));
626 
627  const Poly p(Series::series_nthroot(Series::pow(s, 2, prec - 1) + 1, 2,
628  var, prec - 1));
629  const Poly res_p(Series::diff(s, var)
630  * Series::series_invert(p, var, prec - 1));
631 
632  if (c == 0) {
633  return Series::integrate(res_p, var);
634  } else {
635  return Series::integrate(res_p, var) + Series::asinh(c);
636  }
637  }
638 
639  static inline Poly series_tanh(const Poly &s, const Poly &var,
640  unsigned int prec)
641  {
642  const Coeff c(Series::find_cf(s, var, 0));
643  Poly res_p(s);
644  if (c != 0) {
645  res_p -= c;
646  }
647  Poly s_(res_p);
648  auto steps = step_list(prec);
649  for (const auto step : steps) {
650  const Poly p(s_ - Series::series_atanh(res_p, var, step));
651  res_p += Series::mul(-p, Series::pow(res_p, 2, step) - 1, step);
652  }
653  if (c != 0) {
654  return (res_p + Series::tanh(c))
655  * Series::series_invert(1 + Series::tanh(c) * res_p, var,
656  prec);
657  } else {
658  return res_p;
659  }
660  }
661 
662  static inline Coeff sin(const Coeff &c)
663  {
664  throw NotImplementedError("sin(const) not implemented");
665  }
666  static inline Coeff cos(const Coeff &c)
667  {
668  throw NotImplementedError("cos(const) not implemented");
669  }
670  static inline Coeff tan(const Coeff &c)
671  {
672  throw NotImplementedError("tan(const) not implemented");
673  }
674  static inline Coeff asin(const Coeff &c)
675  {
676  throw NotImplementedError("asin(const) not implemented");
677  }
678  static inline Coeff acos(const Coeff &c)
679  {
680  throw NotImplementedError("acos(const) not implemented");
681  }
682  static inline Coeff atan(const Coeff &c)
683  {
684  throw NotImplementedError("atan(const) not implemented");
685  }
686  static inline Coeff sinh(const Coeff &c)
687  {
688  throw NotImplementedError("sinh(const) not implemented");
689  }
690  static inline Coeff cosh(const Coeff &c)
691  {
692  throw NotImplementedError("cosh(const) not implemented");
693  }
694  static inline Coeff tanh(const Coeff &c)
695  {
696  throw NotImplementedError("tanh(const) not implemented");
697  }
698  static inline Coeff asinh(const Coeff &c)
699  {
700  throw NotImplementedError("asinh(const) not implemented");
701  }
702  static inline Coeff atanh(const Coeff &c)
703  {
704  throw NotImplementedError("atanh(const) not implemented");
705  }
706  static inline Coeff exp(const Coeff &c)
707  {
708  throw NotImplementedError("exp(const) not implemented");
709  }
710  static inline Coeff log(const Coeff &c)
711  {
712  throw NotImplementedError("log(const) not implemented");
713  }
714 };
715 
716 RCP<const SeriesCoeffInterface> series(const RCP<const Basic> &ex,
717  const RCP<const Symbol> &var,
718  unsigned int prec);
719 
720 RCP<const SeriesCoeffInterface> series_invfunc(const RCP<const Basic> &ex,
721  const RCP<const Symbol> &var,
722  unsigned int prec);
723 
724 } // namespace SymEngine
725 #endif
The lowest unit of symbolic representation.
Definition: basic.h:97
RCP< T > rcp_from_this()
Get RCP<T> pointer to self (it will cast the pointer to T)
virtual RCP< const Number > mul(const Number &other) const =0
Multiplication.
virtual RCP< const Number > add(const Number &other) const =0
Addition.
virtual bool is_negative() const =0
bool is_one() const override
Definition: series.h:60
RCP< const Number > mul(const Number &other) const override
Multiplication.
Definition: series.h:110
RCP< const Number > pow(const Number &other) const override
Power.
Definition: series.h:128
static Poly series_atan(const Poly &s, const Poly &var, unsigned int prec)
Definition: series.h:284
bool is_minus_one() const override
Definition: series.h:65
RCP< const Number > add(const Number &other) const override
Addition.
Definition: series.h:92
bool is_negative() const override
Definition: series.h:70
bool __eq__(const Basic &o) const override
Test equality.
Definition: series.h:85
bool is_positive() const override
Definition: series.h:75
static Poly series_exp(const Poly &s, const Poly &var, unsigned int prec)
Definition: series.h:520
static Poly series_log(const Poly &s, const Poly &var, unsigned int prec)
Definition: series.h:493
bool is_zero() const override
Definition: series.h:55
bool is_complex() const override
Definition: series.h:80
T clear(T... args)
T empty(T... args)
T min(T... args)
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
RCP< const Basic > sign(const RCP< const Basic > &arg)
Canonicalize Sign.
Definition: functions.cpp:527
RCP< const Basic > neg(const RCP< const Basic > &a)
Negation.
Definition: mul.cpp:443
T push_back(T... args)
T push_front(T... args)
T rbegin(T... args)