Loading...
Searching...
No Matches
infinity.cpp
1#include <symengine/complex.h>
2#include <symengine/complex_double.h>
6#include <symengine/symengine_exception.h>
7#include <symengine/complex_mpc.h>
8
10
11namespace SymEngine
12{
13
14Infty::Infty(const RCP<const Number> &direction)
15{
16 SYMENGINE_ASSIGN_TYPEID()
17 _direction = direction;
18 SYMENGINE_ASSERT(is_canonical(_direction));
19}
20
22{
23 SYMENGINE_ASSIGN_TYPEID()
24 _direction = inf.get_direction();
25 SYMENGINE_ASSERT(is_canonical(_direction))
26}
27
28RCP<const Infty> Infty::from_direction(const RCP<const Number> &direction)
29{
30 return make_rcp<Infty>(direction);
31}
32
33RCP<const Infty> Infty::from_int(const int val)
34{
35 SYMENGINE_ASSERT(val >= -1 && val <= 1)
36 return make_rcp<Infty>(integer(val));
37}
38
40bool Infty::is_canonical(const RCP<const Number> &num) const
41{
42 if (is_a<Complex>(*num) || is_a<ComplexDouble>(*num))
43 throw NotImplementedError("Not implemented for all directions");
44
45 if (num->is_one() || num->is_zero() || num->is_minus_one())
46 return true;
47
48 return false;
49}
50
51hash_t Infty::__hash__() const
52{
53 hash_t seed = SYMENGINE_INFTY;
54 hash_combine<Basic>(seed, *_direction);
55 return seed;
56}
57
58bool Infty::__eq__(const Basic &o) const
59{
60 if (is_a<Infty>(o)) {
61 const Infty &s = down_cast<const Infty &>(o);
62 return eq(*_direction, *(s.get_direction()));
63 }
64
65 return false;
66}
67
68int Infty::compare(const Basic &o) const
69{
70 SYMENGINE_ASSERT(is_a<Infty>(o))
71 const Infty &s = down_cast<const Infty &>(o);
72 return _direction->compare(*(s.get_direction()));
73}
74
75bool Infty::is_unsigned_infinity() const
76{
77 return _direction->is_zero();
78}
79
80bool Infty::is_positive_infinity() const
81{
82 return _direction->is_positive();
83}
84
85bool Infty::is_negative_infinity() const
86{
87 return _direction->is_negative();
88}
89
90RCP<const Basic> Infty::conjugate() const
91{
92 if (is_positive_infinity() or is_negative_infinity()) {
93 return infty(_direction);
94 }
95 return make_rcp<const Conjugate>(ComplexInf);
96}
97
98RCP<const Number> Infty::add(const Number &other) const
99{
100 if (not is_a<Infty>(other))
101 return rcp_from_this_cast<Number>();
102
103 const Infty &s = down_cast<const Infty &>(other);
104
105 if (not eq(*s.get_direction(), *_direction))
106 return Nan;
107 else if (is_unsigned_infinity())
108 return Nan;
109 else
110 return rcp_from_this_cast<Number>();
111}
112
113RCP<const Number> Infty::mul(const Number &other) const
114{
115 if (is_a<Complex>(other))
116 throw NotImplementedError(
117 "Multiplication with Complex not implemented");
118
119 if (is_a<Infty>(other)) {
120 const Infty &s = down_cast<const Infty &>(other);
121 return make_rcp<const Infty>(this->_direction->mul(*(s._direction)));
122 } else {
123 if (other.is_positive())
124 return rcp_from_this_cast<Number>();
125 else if (other.is_negative())
126 return make_rcp<const Infty>(this->_direction->mul(*minus_one));
127 else
128 return Nan;
129 }
130}
131
132RCP<const Number> Infty::div(const Number &other) const
133{
134 if (is_a<Infty>(other)) {
135 return Nan;
136 } else {
137 if (other.is_positive())
138 return rcp_from_this_cast<Number>();
139 else if (other.is_zero())
140 return infty(0);
141 else
142 return infty(this->_direction->mul(*minus_one));
143 }
144}
145
146RCP<const Number> Infty::pow(const Number &other) const
147{
148 if (is_a<Infty>(other)) {
149 if (is_positive_infinity()) {
150 if (other.is_negative()) {
151 return zero;
152 } else if (other.is_positive()) {
153 return rcp_from_this_cast<Number>();
154 } else {
155 return Nan;
156 }
157 } else if (is_negative_infinity()) {
158 return Nan;
159 } else {
160 if (other.is_positive()) {
161 return infty(0);
162 } else if (other.is_negative()) {
163 return zero;
164 } else {
165 return Nan;
166 }
167 }
168 } else if (is_a<Complex>(other)) {
169 throw NotImplementedError(
170 "Raising to the Complex powers not yet implemented");
171 } else {
172 if (other.is_negative()) {
173 return zero;
174 } else if (other.is_zero()) {
175 return one;
176 } else {
177 if (is_positive_infinity()) {
178 return rcp_from_this_cast<Number>();
179 } else if (is_negative_infinity()) {
180 throw NotImplementedError("Raising Negative Infty to the "
181 "Positive Real powers not yet "
182 "implemented");
183 } else {
184 return infty(0);
185 }
186 }
187 }
188}
189
190RCP<const Number> Infty::rpow(const Number &other) const
191{
192 if (is_a_Complex(other)) {
193 throw NotImplementedError(
194 "Raising Complex powers to Infty not yet implemented");
195 } else {
196 if (other.is_negative()) {
197 throw NotImplementedError("Raising Negative numbers to infinite "
198 "powers not yet implemented");
199 } else if (other.is_zero()) {
200 throw SymEngineException("Indeterminate Expression: `0 ** +- "
201 "unsigned Infty` encountered");
202 } else {
203 const Number &s = down_cast<const Number &>(other);
204 if (s.is_one()) {
205 return Nan;
206 } else if (is_positive_infinity()) {
207 if (s.sub(*one)->is_negative()) {
208 return zero;
209 } else {
210 return rcp_from_this_cast<Number>();
211 }
212 } else if (is_negative_infinity()) {
213 if (s.sub(*one)->is_negative()) {
214 return infty(0);
215 } else {
216 return zero;
217 }
218 } else {
219 throw SymEngineException("Indeterminate Expression: `Positive "
220 "Real Number ** unsigned Infty` "
221 "encountered");
222 }
223 }
224 }
225}
226
227inline RCP<const Infty> infty(const RCP<const Number> &direction)
228{
229 return make_rcp<Infty>(direction);
230}
231
233{
234 virtual RCP<const Basic> sin(const Basic &x) const override
235 {
236 SYMENGINE_ASSERT(is_a<Infty>(x))
237 throw DomainError("sin is not defined for infinite values");
238 }
239 virtual RCP<const Basic> cos(const Basic &x) const override
240 {
241 SYMENGINE_ASSERT(is_a<Infty>(x))
242 throw DomainError("cos is not defined for infinite values");
243 }
244 virtual RCP<const Basic> tan(const Basic &x) const override
245 {
246 SYMENGINE_ASSERT(is_a<Infty>(x))
247 throw DomainError("tan is not defined for infinite values");
248 }
249 virtual RCP<const Basic> cot(const Basic &x) const override
250 {
251 SYMENGINE_ASSERT(is_a<Infty>(x))
252 throw DomainError("cot is not defined for infinite values");
253 }
254 virtual RCP<const Basic> sec(const Basic &x) const override
255 {
256 SYMENGINE_ASSERT(is_a<Infty>(x))
257 throw DomainError("sec is not defined for infinite values");
258 }
259 virtual RCP<const Basic> csc(const Basic &x) const override
260 {
261 SYMENGINE_ASSERT(is_a<Infty>(x))
262 throw DomainError("csc is not defined for infinite values");
263 }
264 virtual RCP<const Basic> asin(const Basic &x) const override
265 {
266 SYMENGINE_ASSERT(is_a<Infty>(x))
267 throw DomainError("asin is not defined for infinite values");
268 }
269 virtual RCP<const Basic> acos(const Basic &x) const override
270 {
271 SYMENGINE_ASSERT(is_a<Infty>(x))
272 throw DomainError("acos is not defined for infinite values");
273 }
274 virtual RCP<const Basic> acsc(const Basic &x) const override
275 {
276 SYMENGINE_ASSERT(is_a<Infty>(x))
277 throw DomainError("acsc is not defined for infinite values");
278 }
279 virtual RCP<const Basic> asec(const Basic &x) const override
280 {
281 SYMENGINE_ASSERT(is_a<Infty>(x))
282 throw DomainError("asec is not defined for infinite values");
283 }
284 virtual RCP<const Basic> atan(const Basic &x) const override
285 {
286 SYMENGINE_ASSERT(is_a<Infty>(x))
287 const Infty &s = down_cast<const Infty &>(x);
288 if (s.is_positive()) {
289 return div(pi, integer(2));
290 } else if (s.is_negative()) {
291 return mul(minus_one, (div(pi, integer(2))));
292 } else {
293 throw DomainError("atan is not defined for Complex Infinity");
294 }
295 }
296 virtual RCP<const Basic> acot(const Basic &x) const override
297 {
298 SYMENGINE_ASSERT(is_a<Infty>(x))
299 const Infty &s = down_cast<const Infty &>(x);
300 if (s.is_positive() or s.is_negative()) {
301 return zero;
302 } else {
303 throw DomainError("acot is not defined for Complex Infinity");
304 }
305 }
306 virtual RCP<const Basic> sinh(const Basic &x) const override
307 {
308 SYMENGINE_ASSERT(is_a<Infty>(x))
309 const Infty &s = down_cast<const Infty &>(x);
310 if (s.is_positive() or s.is_negative()) {
311 return infty(s.get_direction());
312 } else {
313 throw DomainError("sinh is not defined for Complex Infinity");
314 }
315 }
316 virtual RCP<const Basic> csch(const Basic &x) const override
317 {
318 SYMENGINE_ASSERT(is_a<Infty>(x))
319 const Infty &s = down_cast<const Infty &>(x);
320 if (s.is_positive() or s.is_negative()) {
321 return zero;
322 } else {
323 throw DomainError("csch is not defined for Complex Infinity");
324 }
325 }
326 virtual RCP<const Basic> cosh(const Basic &x) const override
327 {
328 SYMENGINE_ASSERT(is_a<Infty>(x))
329 const Infty &s = down_cast<const Infty &>(x);
330 if (s.is_positive() or s.is_negative()) {
331 return Inf;
332 } else {
333 throw DomainError("cosh is not defined for Complex Infinity");
334 }
335 }
336 virtual RCP<const Basic> sech(const Basic &x) const override
337 {
338 SYMENGINE_ASSERT(is_a<Infty>(x))
339 const Infty &s = down_cast<const Infty &>(x);
340 if (s.is_positive() or s.is_negative()) {
341 return zero;
342 } else {
343 throw DomainError("sech is not defined for Complex Infinity");
344 }
345 }
346 virtual RCP<const Basic> tanh(const Basic &x) const override
347 {
348 SYMENGINE_ASSERT(is_a<Infty>(x))
349 const Infty &s = down_cast<const Infty &>(x);
350 if (s.is_positive()) {
351 return one;
352 } else if (s.is_negative()) {
353 return minus_one;
354 } else {
355 throw DomainError("tanh is not defined for Complex Infinity");
356 }
357 }
358 virtual RCP<const Basic> coth(const Basic &x) const override
359 {
360 SYMENGINE_ASSERT(is_a<Infty>(x))
361 const Infty &s = down_cast<const Infty &>(x);
362 if (s.is_positive()) {
363 return one;
364 } else if (s.is_negative()) {
365 return minus_one;
366 } else {
367 throw DomainError("coth is not defined for Complex Infinity");
368 }
369 }
370 virtual RCP<const Basic> asinh(const Basic &x) const override
371 {
372 SYMENGINE_ASSERT(is_a<Infty>(x))
373 const Infty &s = down_cast<const Infty &>(x);
374 if (s.is_positive() or s.is_negative()) {
375 return infty(s.get_direction());
376 } else {
377 throw DomainError("asinh is not defined for Complex Infinity");
378 }
379 }
380 virtual RCP<const Basic> acosh(const Basic &x) const override
381 {
382 SYMENGINE_ASSERT(is_a<Infty>(x))
383 const Infty &s = down_cast<const Infty &>(x);
384 if (s.is_positive() or s.is_negative()) {
385 return Inf;
386 } else {
387 throw DomainError("acosh is not defined for Complex Infinity");
388 }
389 }
390 virtual RCP<const Basic> acsch(const Basic &x) const override
391 {
392 SYMENGINE_ASSERT(is_a<Infty>(x))
393 const Infty &s = down_cast<const Infty &>(x);
394 if (s.is_positive() or s.is_negative()) {
395 return zero;
396 } else {
397 throw DomainError("acsch is not defined for Complex Infinity");
398 }
399 }
400 virtual RCP<const Basic> asech(const Basic &x) const override
401 {
402 SYMENGINE_ASSERT(is_a<Infty>(x))
403 const Infty &s = down_cast<const Infty &>(x);
404 if (s.is_positive() or s.is_negative()) {
405 return mul(mul(I, pi), div(one, integer(2)));
406 } else {
407 throw DomainError("asech is not defined for Complex Infinity");
408 }
409 }
410 virtual RCP<const Basic> atanh(const Basic &x) const override
411 {
412 SYMENGINE_ASSERT(is_a<Infty>(x))
413 const Infty &s = down_cast<const Infty &>(x);
414 if (s.is_positive()) {
415 return mul(minus_one, div(mul(pi, I), integer(2)));
416 } else if (s.is_negative()) {
417 return div(mul(pi, I), integer(2));
418 } else {
419 throw DomainError("atanh is not defined for Complex Infinity");
420 }
421 }
422 virtual RCP<const Basic> acoth(const Basic &x) const override
423 {
424 SYMENGINE_ASSERT(is_a<Infty>(x))
425 const Infty &s = down_cast<const Infty &>(x);
426 if (s.is_positive() or s.is_negative()) {
427 return zero;
428 } else {
429 throw DomainError("acoth is not defined for Complex Infinity");
430 }
431 }
432 virtual RCP<const Basic> abs(const Basic &x) const override
433 {
434 SYMENGINE_ASSERT(is_a<Infty>(x))
435 return Inf;
436 }
437 virtual RCP<const Basic> log(const Basic &x) const override
438 {
439 SYMENGINE_ASSERT(is_a<Infty>(x))
440 const Infty &s = down_cast<const Infty &>(x);
441 if (s.is_positive() or s.is_negative()) {
442 return Inf;
443 } else {
444 return ComplexInf;
445 }
446 }
447 virtual RCP<const Basic> gamma(const Basic &x) const override
448 {
449 SYMENGINE_ASSERT(is_a<Infty>(x))
450 const Infty &s = down_cast<const Infty &>(x);
451 if (s.is_positive()) {
452 return Inf;
453 } else {
454 return ComplexInf;
455 }
456 }
457 virtual RCP<const Basic> exp(const Basic &x) const override
458 {
459 SYMENGINE_ASSERT(is_a<Infty>(x))
460 const Infty &s = down_cast<const Infty &>(x);
461 if (s.is_positive()) {
462 return Inf;
463 } else if (s.is_negative()) {
464 return zero;
465 } else {
466 throw DomainError("exp is not defined for Complex Infinity");
467 }
468 }
469 virtual RCP<const Basic> floor(const Basic &x) const override
470 {
471 SYMENGINE_ASSERT(is_a<Infty>(x))
472 const Infty &s = down_cast<const Infty &>(x);
473 if (s.is_positive()) {
474 return Inf;
475 } else if (s.is_negative()) {
476 return NegInf;
477 } else {
478 throw DomainError("floor is not defined for Complex Infinity");
479 }
480 }
481 virtual RCP<const Basic> ceiling(const Basic &x) const override
482 {
483 SYMENGINE_ASSERT(is_a<Infty>(x))
484 const Infty &s = down_cast<const Infty &>(x);
485 if (s.is_positive()) {
486 return Inf;
487 } else if (s.is_negative()) {
488 return NegInf;
489 } else {
490 throw DomainError("ceiling is not defined for Complex Infinity");
491 }
492 }
493 virtual RCP<const Basic> truncate(const Basic &x) const override
494 {
495 SYMENGINE_ASSERT(is_a<Infty>(x))
496 const Infty &s = down_cast<const Infty &>(x);
497 if (s.is_positive()) {
498 return Inf;
499 } else if (s.is_negative()) {
500 return NegInf;
501 } else {
502 throw DomainError("truncate is not defined for Complex Infinity");
503 }
504 }
505 virtual RCP<const Basic> erf(const Basic &x) const override
506 {
507 SYMENGINE_ASSERT(is_a<Infty>(x))
508 const Infty &s = down_cast<const Infty &>(x);
509 if (s.is_positive()) {
510 return one;
511 } else if (s.is_negative()) {
512 return minus_one;
513 } else {
514 throw DomainError("erf is not defined for Complex Infinity");
515 }
516 }
517 virtual RCP<const Basic> erfc(const Basic &x) const override
518 {
519 SYMENGINE_ASSERT(is_a<Infty>(x))
520 const Infty &s = down_cast<const Infty &>(x);
521 if (s.is_positive()) {
522 return zero;
523 } else if (s.is_negative()) {
524 return integer(2);
525 } else {
526 throw DomainError("erfc is not defined for Complex Infinity");
527 }
528 }
529};
530
532{
533 static EvaluateInfty evaluate_infty;
534 return evaluate_infty;
535}
536
537} // namespace SymEngine
The lowest unit of symbolic representation.
Definition: basic.h:97
A class that will evaluate functions numerically.
Definition: number.h:200
RCP< const Number > div(const Number &other) const
Division.
Definition: infinity.cpp:132
bool is_canonical(const RCP< const Number > &num) const
Canonical when the direction is -1, 0 or 1.
Definition: infinity.cpp:40
bool __eq__(const Basic &o) const
Definition: infinity.cpp:58
virtual RCP< const Basic > conjugate() const
Definition: infinity.cpp:90
bool is_negative() const
Definition: infinity.h:90
static RCP< const Infty > from_int(const int val)
Constructs Infty using sign of val
Definition: infinity.cpp:33
RCP< const Number > pow(const Number &other) const
Power.
Definition: infinity.cpp:146
bool is_positive() const
Definition: infinity.h:85
Infty(const RCP< const Number > &direction)
Constructs Infty using the sign of _direction
Definition: infinity.cpp:14
RCP< const Number > add(const Number &other) const
Addition.
Definition: infinity.cpp:98
hash_t __hash__() const
Definition: infinity.cpp:51
int compare(const Basic &o) const
Definition: infinity.cpp:68
virtual Evaluate & get_eval() const
Get Evaluate singleton to evaluate numerically.
Definition: infinity.cpp:531
RCP< const Number > mul(const Number &other) const
Multiplication.
Definition: infinity.cpp:113
virtual bool is_negative() const =0
virtual bool is_positive() const =0
virtual bool is_zero() const =0
Main namespace for SymEngine package.
Definition: add.cpp:19
RCP< const Basic > div(const RCP< const Basic > &a, const RCP< const Basic > &b)
Division.
Definition: mul.cpp:431
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
Definition: mul.cpp:352
bool is_a_Complex(const Basic &b)
Definition: complex.h:24
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)
Definition: integer.h:200