Sorry for the long silence here, it’s been a busy summer with far too little Perl 6. But I did squeeze in some work on trig, both on nom and niecza. And I ran into a very interesting issue.

My local copy of niecza has S32-trig/sin.t almost working. A few needed skips, but all the core numeric types work. Except…

> is_approx(asin(0.785398163404734 + 2i), 0.341338918259482 + 1.49709293866352i
# got: 2.80025373533031-1.49709293866352i
# expected: 0.341338918259482+1.49709293866352i
niecza> asin(0.785398163404734 + 2i)
2.80025373533031-1.49709293866352i
rakudo> asin(0.785398163404734 + 2i)
0.341338918259481 + 1.49709293866352i

Woah, what’s up with that? Well, it turns out both answers are right in some sense:

niecza> sin(asin(0.785398163404734 + 2i))
0.785398163404734+2i
rakudo> sin(asin(0.785398163404734 + 2i))
0.785398163404734 + 2i

The thing here is that `sin`

is periodic; there are an infinite number of complex numbers it maps to the same result value. That means when you call `asin`

, there are an infinite number of possible results for each input value, and you must somehow choose one of them.

But let’s take a step back from that and look at why I got different results, because I used the exact same formula for `asin`

in both Rakudo and Niecza. That formula is `-1i * log(($x)i + sqrt(1 - $x * $x))`

. Let’s look at the `sqrt`

first:

niecza> my $x = 0.785398163404734 + 2i; sqrt(1 - $x * $x)
-2.21086930051619+0.710488099157523i
rakudo> my $x = 0.785398163404734 + 2i; sqrt(1 - $x * $x)
2.21086930051619 - 0.710488099157523i

As you can see, one answer is the negative of the other. Of course, when you square the results, that additional factor of `-1`

just goes away, so these are both valid results.

So this leads me to two questions:

1) Should we define one of these two answers as being correct, as far as Perl 6 is concerned? (Or should they both be considered valid results?)

2) If so, which one? And how do we coherently specify that branch?

I thought at first it might be as simple as saying “The branch where the complex result of `sqrt`

for complex numbers with an imaginary value of 0 agrees with the real `sqrt`

result.” But in fact both Rakudo and Niecza already seem to agree for the `sqrt`

s of real-valued Complex numbers.

Anyone else out there have a notion?

### Like this:

Like Loading...

*Related*

This entry was posted on August 31, 2011 at 3:43 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

August 31, 2011 at 4:00 pm |

http://www.ida.liu.se/imported/cltl/clm/node129.html looks to have some interesting info…

August 31, 2011 at 7:26 pm |

1) Yes, there should be one “correct” answer for all Perl 6 implementations.

2) Let’s just follow Common Lisp. They’ve got the experience, and they’ve already written the definitions. Just make sure we get the current definitions. (I’m not a Lisp expert, so I’m not sure if the link you mention is up-to-date.)

Here’s another link to look at:

http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/fun_asincm_acoscm_atan.html

September 1, 2011 at 9:09 am |

follow C and POSIX (that AFAIK is similar to Common Lisp behavior):

http://pubs.opengroup.org/onlinepubs/009695399/functions/csqrt.html

September 1, 2011 at 2:51 pm |

The Perl 6 specs already specify “principal” square root, which apparently means the same thing that POSIX and Common Lisp specify. Niecza has now been fixed to do that too.

September 8, 2011 at 5:11 pm |

It’s a bad test because both answers are correct.

(sqrt 1)^3 can be 1 or -1. and both are ok answers.

Maybe a best test is something like ( asin(sin(asin x)) == asin x )

September 8, 2011 at 6:38 pm |

jamarier, I strongly disagree. You’re correct that in the mathematical sense, sqrt(x) has two answers, and asin(x) has an infinite number of answers.

But in a computer programming language, the range of the sqrt and asin functions should be defined such that there is only 1 correct answer for each possible input. Programming is hard enough as it is; any surprises that can be removed should be removed.