Opened 9 years ago

Last modified 4 years ago

asin(2.0) should not return NaN

Reported by: Owned by: davidamadore major sage-6.4 symbolics functions N/A

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).

comment:1 Changed 8 years ago by vbraun_spam

• Milestone changed from sage-6.1 to sage-6.2

comment:2 Changed 8 years ago by vbraun_spam

• Milestone changed from sage-6.2 to sage-6.3

comment:3 Changed 8 years ago by vbraun_spam

• Milestone changed from sage-6.3 to sage-6.4

comment:4 Changed 5 years ago by rws

• 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 5 years ago by rws

This touches several issues. Maybe we should agree for now to get different results with a `float` and a `complex`/`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)` and `asin(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 made `asin((1.+1.*I)*(1.-1.*I))` return `NaN` as well. Adapting this to the above numeric changes would be easy. I think `asin(2)` should then also return `1/2*pi - I*arccosh(2)` instead of `arcsin(2)`.

comment:6 in reply to: ↑ 5 ; follow-up: ↓ 7 Changed 5 years ago by vdelecroix

Replying to rws:

Maybe we should agree for now to get different results with a `float` and a `complex`/`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 5 years ago by 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))
False
```

Or provide custom formal sets representing the reals/complexes.

comment:8 in reply to: ↑ 7 Changed 5 years ago by rws

Replying to rws:

```sage: from sage.sets.set import is_Set
sage: is_Set(RealSet(-oo,oo))
True
```

Oh my I totally forgot that I already implemented that as part of #24171. I'll extract it and make a separate ticket right now.

comment:9 Changed 5 years ago by rws

Please review #24443.

comment:10 in reply to: ↑ 7 ; follow-up: ↓ 11 Changed 5 years ago by vdelecroix

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))
False
```

Or 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 5 years ago by 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.

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

That shows that the documentation of `is_Set` is incomplete.

comment:12 Changed 5 years ago by vdelecroix

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 5 years ago by 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.

comment:14 in reply to: ↑ 13 Changed 4 years ago by rws

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 4 years ago by rws

`asin(2.0)` would be fixed in #24428.

Note: See TracTickets for help on using tickets.