Loading...
Searching...
No Matches
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
14namespace SymEngine
15{
16
18{
19public:
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
27template <typename Poly, typename Coeff, typename Series>
29{
30protected:
31 const Poly p_;
32 const std::string var_;
33 const unsigned degree_;
34
35public:
36 inline SeriesBase(Poly p, std::string var, unsigned degree)
37 : p_(std::move(p)), var_(var), degree_(degree)
38 {
39 }
40 inline virtual unsigned get_degree() const
41 {
42 return degree_;
43 }
44
45 inline virtual const std::string &get_var() const
46 {
47 return var_;
48 }
49
50 inline const Poly &get_poly() const
51 {
52 return p_;
53 }
54
55 inline virtual bool is_zero() const
56 {
57 return false;
58 }
59
60 inline virtual bool is_one() const
61 {
62 return false;
63 }
64
65 inline virtual bool is_minus_one() const
66 {
67 return false;
68 }
69
70 inline virtual bool is_negative() const
71 {
72 return false;
73 }
74
75 inline virtual bool is_positive() const
76 {
77 return false;
78 }
79
80 inline virtual bool is_complex() const
81 {
82 return false;
83 }
84
85 inline virtual bool __eq__(const Basic &o) const
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 virtual RCP<const Number> add(const Number &other) const
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 virtual RCP<const Number> mul(const Number &other) const
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 virtual RCP<const Number> pow(const Number &other) const
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 virtual RCP<const Number> rpow(const Number &other) const
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
716RCP<const SeriesCoeffInterface> series(const RCP<const Basic> &ex,
717 const RCP<const Symbol> &var,
718 unsigned int prec);
719
720RCP<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 > add(const Number &other) const =0
Addition.
virtual bool is_negative() const =0
virtual RCP< const Number > mul(const Number &other) const =0
Multiplication.
virtual bool __eq__(const Basic &o) const
Test equality.
Definition: series.h:85
virtual RCP< const Number > mul(const Number &other) const
Multiplication.
Definition: series.h:110
virtual bool is_minus_one() const
Definition: series.h:65
static Poly series_atan(const Poly &s, const Poly &var, unsigned int prec)
Definition: series.h:284
virtual RCP< const Number > pow(const Number &other) const
Power.
Definition: series.h:128
virtual bool is_negative() const
Definition: series.h:70
virtual bool is_positive() const
Definition: series.h:75
virtual bool is_zero() const
Definition: series.h:55
virtual bool is_complex() const
Definition: series.h:80
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
virtual RCP< const Number > add(const Number &other) const
Addition.
Definition: series.h:92
virtual bool is_one() const
Definition: series.h:60
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)