From 4f166b0dd262464648e7bdb484f8431dda724c50 Mon Sep 17 00:00:00 2001 From: Erik Schnetter Date: Mon, 11 May 2020 14:10:06 -0400 Subject: [PATCH 1/5] Implement cispi --- base/complex.jl | 34 ++++++++++++++++++++++++++++++++++ base/exports.jl | 1 + base/number.jl | 5 +++++ doc/src/base/math.md | 1 + test/complex.jl | 17 +++++++++++++++++ 5 files changed, 58 insertions(+) diff --git a/base/complex.jl b/base/complex.jl index 8aec9cf1301ee..8836995c44b55 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -541,6 +541,40 @@ function cis(z::Complex) Complex(v * c, v * s) end +cispi(sign::Bool) = sign ? -1 : 1 +cispi(sign::Integer) = oftype(sign, cispi(isodd(sign))) +cispi(theta::Real) = Complex(cospi(theta), sinpi(theta)) + +""" + cispi(z) + +Return ``\\exp(iπz)``. + +This function also accepts integer or boolean arguments, and then +returns integer results. This allows calculating ``(-1)^s`` +conveniently and efficiently. + +`cispi` is related to [`signbit`](@ref), and allows decomposing +integers into sign bit and absolute value: ``cispi(signbit(n)) * +abs(n) == n``. For boolean values, it is also, ``signbit(cispi(b)) == +b``. + +# Examples +```jldoctest +julia> cispi(1) == -1 +true + +julia> cispi(0) == 1 +true +``` + +!!! compat "Julia 1.6" + This function requires Julia 1.6 or later. +""" +function cispi(z::Complex) + cospi(z) + im*sinpi(z) +end + """ angle(z) diff --git a/base/exports.jl b/base/exports.jl index 3e7e6ce7647e4..0c157c45d2052 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -229,6 +229,7 @@ export cbrt, ceil, cis, + cispi, clamp, cld, cmp, diff --git a/base/number.jl b/base/number.jl index 142796d3903ac..da0b122fc65b9 100644 --- a/base/number.jl +++ b/base/number.jl @@ -110,6 +110,11 @@ copy(x::Number) = x # some code treats numbers as collection-like Returns `true` if the value of the sign of `x` is negative, otherwise `false`. +Related to `signbit` is [`cispi`](@ref) (which calculates `(-1)^n`). +This allows decomposing integers into sign bit and absolute value: +``cispi(signbit(n)) * abs(n) == n``. For boolean values, it is also, +``signbit(cispi(b)) == b``. + # Examples ```jldoctest julia> signbit(-4) diff --git a/doc/src/base/math.md b/doc/src/base/math.md index 600b88efb5546..e0f094572a398 100644 --- a/doc/src/base/math.md +++ b/doc/src/base/math.md @@ -162,6 +162,7 @@ Base.reim Base.conj Base.angle Base.cis +Base.cispi Base.binomial Base.factorial Base.gcd diff --git a/test/complex.jl b/test/complex.jl index f02c931ebdda7..27fbcee370460 100644 --- a/test/complex.jl +++ b/test/complex.jl @@ -123,6 +123,8 @@ end @test atanh(x) ≈ atanh(big(x)) @test cis(real(x)) ≈ cis(real(big(x))) @test cis(x) ≈ cis(big(x)) + @test cispi(real(x)) ≈ cispi(real(big(x))) + @test cispi(x) ≈ cispi(big(x)) @test cos(x) ≈ cos(big(x)) @test cosh(x) ≈ cosh(big(x)) @test exp(x) ≈ exp(big(x)) @@ -918,6 +920,21 @@ end @test cis(1.0+0.0im) ≈ 0.54030230586813971740093660744297660373231042061+0.84147098480789650665250232163029899962256306079im @test cis(pi) ≈ -1.0+0.0im @test cis(pi/2) ≈ 0.0+1.0im + @test cispi(false) == 1 + @test cispi(true) == -1 + @test cispi(-1) == -1 + @test cispi(0) == 1 + @test cispi(1) == -1 + @test cispi(2) == 1 + @test cispi(0.0) == cispi(0) + @test cispi(1.0) == cispi(1) + @test cispi(2.0) == cispi(2) + @test cispi(0.5) == im + @test cispi(1.5) == -im + @test cispi(0.25) ≈ cis(π/4) + @test cispi(0.0+0.0im) == cispi(0) + @test cispi(1.0+0.0im) == cispi(1) + @test cispi(2.0+0.0im) == cispi(2) end @testset "exp2" begin From 3a6d7a0fc5f9f91e64fe0b1f5924ee395473e888 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Tue, 23 Jun 2020 12:42:55 -0500 Subject: [PATCH 2/5] Review comments in #35792 --- base/complex.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 8836995c44b55..2c42ece40da23 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -541,9 +541,7 @@ function cis(z::Complex) Complex(v * c, v * s) end -cispi(sign::Bool) = sign ? -1 : 1 -cispi(sign::Integer) = oftype(sign, cispi(isodd(sign))) -cispi(theta::Real) = Complex(cospi(theta), sinpi(theta)) +cispi(theta::Real) = Complex(reverse(sincospi(theta))...) """ cispi(z) @@ -572,7 +570,8 @@ true This function requires Julia 1.6 or later. """ function cispi(z::Complex) - cospi(z) + im*sinpi(z) + sipi, copi = sincospi(z) + return complex(real(copi) - imag(sipi), imag(copi) + real(sipi)) end """ From 53ca775b102b66c98c3e197aa4d6d6a8e19fe601 Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Sun, 15 Nov 2020 11:47:30 -0600 Subject: [PATCH 3/5] Remove docs relating cispi and signbit --- base/complex.jl | 9 --------- base/number.jl | 5 ----- 2 files changed, 14 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 2c42ece40da23..cf89a328a53cf 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -548,15 +548,6 @@ cispi(theta::Real) = Complex(reverse(sincospi(theta))...) Return ``\\exp(iπz)``. -This function also accepts integer or boolean arguments, and then -returns integer results. This allows calculating ``(-1)^s`` -conveniently and efficiently. - -`cispi` is related to [`signbit`](@ref), and allows decomposing -integers into sign bit and absolute value: ``cispi(signbit(n)) * -abs(n) == n``. For boolean values, it is also, ``signbit(cispi(b)) == -b``. - # Examples ```jldoctest julia> cispi(1) == -1 diff --git a/base/number.jl b/base/number.jl index da0b122fc65b9..142796d3903ac 100644 --- a/base/number.jl +++ b/base/number.jl @@ -110,11 +110,6 @@ copy(x::Number) = x # some code treats numbers as collection-like Returns `true` if the value of the sign of `x` is negative, otherwise `false`. -Related to `signbit` is [`cispi`](@ref) (which calculates `(-1)^n`). -This allows decomposing integers into sign bit and absolute value: -``cispi(signbit(n)) * abs(n) == n``. For boolean values, it is also, -``signbit(cispi(b)) == b``. - # Examples ```jldoctest julia> signbit(-4) From da83b9c2afdbe57521b49014c5fafcd760534543 Mon Sep 17 00:00:00 2001 From: jmert <2965436+jmert@users.noreply.github.com> Date: Sun, 15 Nov 2020 14:20:31 -0600 Subject: [PATCH 4/5] Review comment, more expressive function doc. Co-authored-by: Simeon Schaub --- base/complex.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/complex.jl b/base/complex.jl index cf89a328a53cf..0ed5c332b7bd9 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -546,7 +546,7 @@ cispi(theta::Real) = Complex(reverse(sincospi(theta))...) """ cispi(z) -Return ``\\exp(iπz)``. +Compute ``\\exp(i\\pi x)`` more accurately than `cis(pi*x)`, especially for large `x`. # Examples ```jldoctest From 7973276efb74e0c71d3e8671562d53b25e01d4b4 Mon Sep 17 00:00:00 2001 From: Justin Willmert Date: Sun, 15 Nov 2020 14:34:07 -0600 Subject: [PATCH 5/5] Switch examples to show complex outputs --- base/complex.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/complex.jl b/base/complex.jl index 0ed5c332b7bd9..884632d5fc453 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -550,11 +550,11 @@ Compute ``\\exp(i\\pi x)`` more accurately than `cis(pi*x)`, especially for larg # Examples ```jldoctest -julia> cispi(1) == -1 -true +julia> cispi(1) +-1.0 + 0.0im -julia> cispi(0) == 1 -true +julia> cispi(0.25 + 1im) +0.030556854645952924 + 0.030556854645952924im ``` !!! compat "Julia 1.6"