Opened 6 years ago
Last modified 18 months ago
#15344 new defect
asin(2.0) should not return NaN
Reported by: | davidamadore | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-6.4 |
Component: | symbolics | Keywords: | functions |
Cc: | Merged in: | ||
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description
Currently, asin(2.0) returns NaN, whereas asin(CC(2.0)) returns the more expected value of 1.57079632679490 - 1.31695789692482*I (that's π/2 − acosh(2)·I).
I can understand the logic of not wanting to return a complex value for a real argument, but since sqrt(-1.0) already returns 1.0*I, there are already parts of Sage which break that logic.
Conversely, this convention of returning NaN causes many difficulties when plotting functions. For example, plot(imag(asin(x)),(x,0,3)) does not at all return what is expected. And, of course, plot(imag(asin(CC(x))),(x,0,3)) does not work, so one has to write plot(lambda t: imag(asin(CC(t))),(0,3)), which, in this simple example, might be a very minor inconvenience, but can become a great annoyance when dealing with more complicated situations.
The fact that Sage sometimes considers values as reals even though they were obtained by complex computations adds insult to injury:
sage: N(asin((1+I)*(1-I))) NaN sage: asin((1.+1.*I)*(1.-1.*I)) 1.57079632679490 - 1.31695789692482*I
(if asin(2) persists in returning NaN, then at least (1+I)*(1-I) should refrain from looking too much like an integer until it is explicitly coerced as such).
Change History (15)
comment:1 Changed 6 years ago by
- Milestone changed from sage-6.1 to sage-6.2
comment:2 Changed 5 years ago by
- Milestone changed from sage-6.2 to sage-6.3
comment:3 Changed 5 years ago by
- Milestone changed from sage-6.3 to sage-6.4
comment:4 Changed 2 years ago by
- Component changed from numerical to symbolics
- Summary changed from asin(2.0) shound not return NaN to asin(2.0) should not return NaN
comment:5 follow-up: ↓ 6 Changed 2 years ago by
comment:6 in reply to: ↑ 5 ; follow-up: ↓ 7 Changed 20 months ago by
Replying to rws:
Maybe we should agree for now to get different results with a
float
and acomplex
/CC
type. The same difference exists with real/complex ball arguments.
Indeed, asin: RR -> RR
(inverse of sin) is different from asin: CC -> CC
(a principal value). In the same veine, the real logarithm is not defined for negative inputs
sage: import math, cmath sage: math.log(-1r) Traceback (most recent call last): ... ValueError: math domain error sage: cmath.log(-1r) 3.141592653589793j
To my mind, Sage is doing wrong here
sage: RR(-1).log() 3.14159265358979*I sage: RDF(-1).log() 3.141592653589793*I
It's not good that there is no easy way to specify argument type when plotting, [...]
I do not think that this is the real problem. As explained before, acosh
, log
, etc mean different things (with various domains and ranges). This information should be known by the function (aka it should be a polymorphic function). It should also be possible to bind a well defined mathematical function from the polymorphic one such as
sage: log.bind(domain=RR, range=RR) The real logarithm on Real Field with 53 bits of precision sage: log.bind(domain=CC, range=CC) The principal value of logarithm on Complex Field with 53 bits of precision
The above binded functions should know about there domain, range, singularities, etc.
comment:7 in reply to: ↑ 6 ; follow-ups: ↓ 8 ↓ 10 Changed 20 months ago by
Replying to vdelecroix:
The above binded functions should know about there domain, range, singularities, etc.
All nice but before even thinking about that this should be fixed:
sage: from sage.sets.set import is_Set sage: is_Set(RR) False sage: is_Set(RealSet(-oo,oo)) False
Or provide custom formal sets representing the reals/complexes.
comment:8 in reply to: ↑ 7 Changed 20 months ago by
comment:9 Changed 20 months ago by
Please review #24443.
comment:10 in reply to: ↑ 7 ; follow-up: ↓ 11 Changed 20 months ago by
Replying to rws:
Replying to vdelecroix:
The above binded functions should know about there domain, range, singularities, etc.
All nice but before even thinking about that this should be fixed:
sage: from sage.sets.set import is_Set sage: is_Set(RR) False sage: is_Set(RealSet(-oo,oo)) FalseOr provide custom formal sets representing the reals/complexes.
You did a double mistake here. In Sage RR
is not the set of real numbers but of floating point numbers with mantissa on 53 bits.
sage: RR Real Field with 53 bits of precision
Next, is_Set
checks whether the type of RR
inherits from Set
which is not what you want to check here. You should rather rely on categories
sage: RR in Sets() True
comment:11 in reply to: ↑ 10 ; follow-up: ↓ 13 Changed 20 months ago by
Replying to vdelecroix:
You did a double mistake here. In Sage
RR
is not the set of real numbers but of floating point numbers with mantissa on 53 bits.
What good does it to have that domain on a symbolic function versus having a formal real set domain? Having a domain affects not only FP evaluation but also normal immediate evaluation of symbolic argument, and only a formal domain has useful implications.
Next,
is_Set
checks whether the type ofRR
inherits fromSet
which is not what you want to check here. You should rather rely on categories
That shows that the documentation of is_Set
is incomplete.
comment:12 Changed 20 months ago by
I don't even see the point of having is_Set
in the global namespace...
comment:13 in reply to: ↑ 11 ; follow-up: ↓ 14 Changed 20 months ago by
Replying to rws:
Replying to vdelecroix:
You did a double mistake here. In Sage
RR
is not the set of real numbers but of floating point numbers with mantissa on 53 bits.What good does it to have that domain on a symbolic function versus having a formal real set domain? Having a domain affects not only FP evaluation but also normal immediate evaluation of symbolic argument, and only a formal domain has useful implications.
It is good because a formal real set has a lot of concrete implementations RealField(prec)
, RealBallField(prec)
, RealIntervalField(prec)
and possibly in the future some more symbolic ones.
comment:14 in reply to: ↑ 13 Changed 19 months ago by
Replying to vdelecroix:
Replying to rws:
Replying to vdelecroix:
You did a double mistake here. In Sage
RR
is not the set of real numbers but of floating point numbers with mantissa on 53 bits.What good does it to have that domain on a symbolic function versus having a formal real set domain? Having a domain affects not only FP evaluation but also normal immediate evaluation of symbolic argument, and only a formal domain has useful implications.
It is good because a formal real set has a lot of concrete implementations
RealField(prec)
,RealBallField(prec)
,RealIntervalField(prec)
and possibly in the future some more symbolic ones.
I don't mind other symbolic domains that are subsets of the formal reals---again, what good is it to have a purely floating-point domain like RealField(53)
on a symbolic function?
comment:15 Changed 18 months ago by
asin(2.0)
would be fixed in #24428.
This touches several issues. Maybe we should agree for now to get different results with a
float
and acomplex
/CC
type. The same difference exists with real/complex ball arguments. It's not good that there is no easy way to specify argument type when plotting, a better workaround however IMHO is to add epsilon*I, e.g.plot(imag(asin(x+I*1e-10)),(x,0,3))
. This should be addressed (complex() symbolic function?) but not here.There are already other parts where complex is returned on float input, right. However changing the output of
asin(2.0)
andasin(RBF(2.0))
would mean changing the interface to the mpfr and arb packages that are used here. This is possible.Now
(1+I)*(1-I)
and(1.+1.*I)*(1.-1.*I)
are completely differently handled than the above because they are symbolic expressions. There were recent changes in Pynac that madeasin((1.+1.*I)*(1.-1.*I))
returnNaN
as well. Adapting this to the above numeric changes would be easy. I thinkasin(2)
should then also return1/2*pi - I*arccosh(2)
instead ofarcsin(2)
.