From 3494ae70001bc7c19b4b87d76f3bbee2ab519c62 Mon Sep 17 00:00:00 2001 From: Nathan Smith Date: Thu, 25 May 2017 12:40:13 -0400 Subject: [PATCH] Add complex randn (#21973) * Add complex randn --- NEWS.md | 5 ++++- base/random.jl | 9 ++++++++- base/sysimg.jl | 6 +++--- test/random.jl | 13 ++++++++++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6795618411d01..923c7dcbdbdad 100644 --- a/NEWS.md +++ b/NEWS.md @@ -33,9 +33,12 @@ This section lists changes that do not have deprecation warnings. Library improvements -------------------- - * the functions `base` and `digits` digits now accept a negative + * The functions `base` and `digits` digits now accept a negative base (like `ndigits` did) ([#21692]). + * The function `randn` now accepts complex arguments (`Complex{T <: AbstractFloat}`) + ([#21973]). + * Method lists are now printed as a numbered list. In addition, the source code of a method can be opened in an editor by entering the corresponding number in the REPL and pressing `^Q` ([#22007]). diff --git a/base/random.jl b/base/random.jl index f4b86f3d353ab..3697302a05153 100644 --- a/base/random.jl +++ b/base/random.jl @@ -1181,7 +1181,9 @@ const ziggurat_exp_r = 7.6971174701310497140446280481 Generate a normally-distributed random number of type `T` with mean 0 and standard deviation 1. Optionally generate an array of normally-distributed random numbers. The `Base` module currently provides an implementation for the types -`Float16`, `Float32`, and `Float64` (the default). +`Float16`, `Float32`, and `Float64` (the default), and their `Complex` counterparts. +When the type argument is complex, the values are drawn from the circularly symmetric +complex normal distribution. """ @inline function randn(rng::AbstractRNG=GLOBAL_RNG) @inbounds begin @@ -1284,6 +1286,11 @@ let Floats = Union{Float16,Float32,Float64} end end +# complex randn +Base.@irrational SQRT_HALF 0.7071067811865475244008 sqrt(big(0.5)) +randn(rng::AbstractRNG, ::Type{Complex{T}}) where {T <: AbstractFloat} = + Complex{T}(SQRT_HALF * randn(rng, T), SQRT_HALF * randn(rng, T)) + ## random UUID generation struct UUID diff --git a/base/sysimg.jl b/base/sysimg.jl index a35f38ef2e423..11a239a5f93bd 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -297,6 +297,9 @@ include("combinatorics.jl") # more hashing definitions include("hashing2.jl") +# irrational mathematical constants +include("irrationals.jl") + # random number generation include("dSFMT.jl") include("random.jl") @@ -357,9 +360,6 @@ const × = cross # statistics include("statistics.jl") -# irrational mathematical constants -include("irrationals.jl") - # signal processing include("dft.jl") importall .DFT diff --git a/test/random.jl b/test/random.jl index 1be9333d7ecd7..0d54f0a426cc4 100644 --- a/test/random.jl +++ b/test/random.jl @@ -13,6 +13,7 @@ srand(0); rand(); x = rand(384) @test typeof(rand(false:true)) === Bool @test typeof(rand(Char)) === Char @test length(randn(4, 5)) == 20 +@test length(randn(Complex128, 4, 5)) == 20 @test length(bitrand(4, 5)) == 20 @test rand(MersenneTwister(0)) == 0.8236475079774124 @@ -65,6 +66,11 @@ randn!(MersenneTwister(42), A) @test A == [-0.5560268761463861 0.027155338009193845; -0.444383357109696 -0.29948409035891055] +B = zeros(Complex128, 2) +randn!(MersenneTwister(42), B) +@test B == [Complex128(-0.5560268761463861,-0.444383357109696), + Complex128(0.027155338009193845,-0.29948409035891055)] * 0.7071067811865475244008 + for T in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, BigInt, Float16, Float32, Float64, Rational{Int}) r = rand(convert(T, 97):convert(T, 122)) @@ -306,8 +312,9 @@ end # test all rand APIs for rng in ([], [MersenneTwister(0)], [RandomDevice()]) - types = [Base.BitInteger_types..., Bool, Float16, Float32, Float64, Char] ftypes = [Float16, Float32, Float64] + cftypes = [Complex32, Complex64, Complex128, ftypes...] + types = [Bool, Char, Base.BitInteger_types..., ftypes...] b2 = big(2) u3 = UInt(3) for f in [rand, randn, randexp] @@ -316,7 +323,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) f(rng..., 2, 3) ::Array{Float64, 2} f(rng..., b2, u3) ::Array{Float64, 2} f(rng..., (2, 3)) ::Array{Float64, 2} - for T in (f === rand ? types : ftypes) + for T in (f === rand ? types : f === randn ? cftypes : ftypes) a0 = f(rng..., T) ::T a1 = f(rng..., T, 5) ::Vector{T} a2 = f(rng..., T, 2, 3) ::Array{T, 2} @@ -330,7 +337,7 @@ for rng in ([], [MersenneTwister(0)], [RandomDevice()]) end end for f! in [rand!, randn!, randexp!] - for T in (f! === rand! ? types : ftypes) + for T in (f! === rand! ? types : f! === randn! ? cftypes : ftypes) X = T == Bool ? T[0,1] : T[0,1,2] for A in (Array{T}(5), Array{T}(2, 3)) f!(rng..., A) ::typeof(A)