# `cispi` is not accurate

In a package of mine, I replaced every occurrence of `exp(1im*pi*z)` with `cispi(z)`. Then one of my unit tests has failed, and this test is a comparison of the evaluation of a special function to the exact value. There were differences after the sixth or seventh decimal digit. Then I believe that `cispi` is not accurate.

An example, but this is less striking on this example:

``````julia> cispi(1im)
0.04321391826377052 + 0.0im

julia> exp(-pi)
0.04321391826377226
``````

The second one is closer to Wolfram:

`0.04321391826377224977...`

3 Likes

`cis` may not as accurate as `exp(im*z)`, in `circstats.jl`, `cis` could make `acos` domain error.

Interestingly, you get the Wolfram figure if you work with BigFloat. Not sure if the pi digits are right, didn’t find unspaced text for comparison.
Round 2 per @longemen3000’s fix:

``````julia> typeof(pi), typeof(-pi)  # need to watch out for conversions
(Irrational{:π}, Float64)

julia> setprecision(1000) # must do this to avoid precision loss in methods
1000

julia> bigpi = BigFloat(pi) # prints only 302 digits
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412736

julia> exp(-bigpi) # prints only 305 digits
0.0432139182637722497744177371717280112757281098106330829807196874010507657570179676981399599619010843870168069645976620563265198317796586642654589470487654217430533893968290178108479426940587436021700979589304669505133081686070687502355832976249027608734841817238797966968412751519595753314335315085890095

julia> precision(bigpi), precision(-bigpi), precision(exp(-bigpi))
(1000, 1000, 1000)

Wolfram Alpha> N[Exp[-Pi], 143] # evaluates expression with 143-digit precision
0.0432139182637722497744177371717280112757281098106330829807196874010507657570179676981399599619010843870168069645976620563265198

julia> cis(pi*im) # real part is exp(-pi)
0.04321391826377226 + 0.0im

julia> cispi(1im)
0.04321391826377052 + 0.0im
``````

the precision on `BigFloat` needs to be set on a global level, via `setprecision`:

``````julia> setprecision(1000)
1000
julia> bigpi = big(pi)
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412736
julia> precision(-bigpi)
1000
``````
2 Likes

Indeed, cis and cispi don’t match in how they’re computed for complex z. cis(z) factors out the imaginary part and calls cis on real(z), while cispi(z) calls `sincospi` on the complex z directly, which here incurs a loss of precision by cancellation. I’ve submitted a fix here: Better precision for cispi(::Complex) by antoine-levitt · Pull Request #45945 · JuliaLang/julia · GitHub

9 Likes

I thought `cis`/`cispi` was only supposed to be an advantage for `Real` inputs. Why use them on complex data?

1 Like

Should be faster as it computes sines and cosines at the same time.

1 Like