## Complex Issues

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?

### 6 Responses to “Complex Issues”

1. colomon Says:

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

2. cjm Says:

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

3. salva Says:

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

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

4. sorear Says:

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.

5. jamarier Says:

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 )

• cjm Says:

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.