Calculating n-roots of unity in Julia - julia

I would like to have an algorithm in Julia depending on $n$, such that it generates the n-roots of unity.
(1,w^{1}, w^{2}, ..., w^{n-1}. Such that for every 1\leq i\leq n, we have that (w^{i})^{n}-1=0 )
Thank you so much for your collaboration,

julia> roots(n) = map(cispi, range(0, 2, length=n+1)[1:end-1])
roots (generic function with 1 method)
julia> roots(8)
8-element Vector{ComplexF64}:
1.0 + 0.0im
0.7071067811865476 + 0.7071067811865476im
0.0 + 1.0im
-0.7071067811865476 + 0.7071067811865476im
-1.0 + 0.0im
-0.7071067811865476 - 0.7071067811865476im
0.0 - 1.0im
0.7071067811865476 - 0.7071067811865476im
You could write roots_exp(n) = exp.(im .* range(0, 2pi, length=n+1)[1:end-1]), but for a pure imaginary argument, cis is slightly more efficient than exp. And cispi is slightly more accurate, or at least, more likely to give you nice round numbers when you expect them, as shown above.

Related

How to narrow element type of a Vector or Array in Julia?

Consider a situation where I first create a Vector with eltype of Any incrementally; after that, I want to narrow the element type of it. How can I do that?
julia> vec = Any[1, 2, 3.]
3-element Vector{Any}:
1
2
3.0
I can use something like convert(Vector{Real}, vec). But in this case, I'm specifying the type manually while I want Julia to decide the best suitable eltype for it.
This can be achieved by broadcasting the identity function on each element of the given container (either an Array or a Vector):
julia> narrowed = identity.(vec)
3-element Vector{Real}:
1
2
3.0
Note that this doesn't lead to promoting (or demoting) the type of each individual element of the given container:
julia> typeof(narrowed[1]), typeof(narrowed[3])
(Int64, Float64)
Additional Point
However, in the case of acquainting with related functions in Julia, This can be done verbosely by using the typejoin function to achieve the type join of the container's elements. According to the concise doc of the function:
typejoin(T, S)
Return the closest common ancestor of T and S, i.e. the narrowest type from which they both inherit.
The argument of the typejoin should be a subtype of Core.Type{T} (However, it seems more sensible to define it as typejoin(T...) since it can get an indefinite number of positional arguments, not just two.)
julia> typeof.(vec)
3-element Vector{DataType}:
Int64
Int64
Float64
julia> typejoin(typeof.(vec)...)
Real
julia> convert(Vector{typejoin(typeof.(vec)...)}, vec)
3-element Vector{Real}:
1
2
3.0
Small type unions (such as Union{Int, Float64} are handled in Julia much faster and than abstract types and hence you should avoid vectors of abstract elements such as Vector{Real} in favor of unions of concrete types such as Union{Int, Float64}.
Having that said here is a code that makes such union:
julia> Vector{Union{Set(typeof.(vec))...}}(vec)
3-element Vector{Union{Float64, Int64}}:
1
2
3.0
And here is a simple test that shows that for a 100 element vector the performance difference is 4x:
julia> a1 = Vector{Union{Int, Float64}}(rand(100));
julia> a2 = Vector{Real}(rand(100));
julia> #btime minimum($a1);
428.643 ns (0 allocations: 0 bytes)
julia> #btime minimum($a2);
2.000 μs (102 allocations: 1.59 KiB)
You can use promote like this:
v = Any[1, 2, 3.0]
first.(promote.(v))
3-element Vector{Real}:
1
2
3.0000
v = Any[1, 2, 3.0, 3 + 2im]
first.(promote.(v))
4-element Vector{Number}:
1
2
3.0000
3 + 2im
But, you might be interested more in getting a vector of concrete supertypes of the elements, especially for performance purposes. So, you can use this:
v = Any[1, 2, 3.0]
reduce(vcat, promote(v...))
3-element Vector{Float64}:
1.0
2.0
3.0
v = Any[1, 2, 3.0, 3 + 2im]
reduce(vcat, promote(v...))
4-element Vector{ComplexF64}:
1.0 + 0.0im
2.0 + 0.0im
3.0 + 0.0im
3.0 + 2.0im
Or, simply:
v = Any[1, 2, 3.0];
[v...]
3-element Vector{Float64}:
1.0
2.0
3.0
v = Any[1, 2, 3.0, 3+2im];
[v...]
4-element Vector{ComplexF64}:
1.0 + 0.0im
2.0 + 0.0im
3.0 + 0.0im
3.0 + 2.0im

Julia equivalent of Python numpy "arange"

In Python, I can create an array of evenly spaced values using
xi2 = np.arange(0, np.sqrt(6), 1e-3)
How do I write this in Julia? I tried,
xi2 = range(0,sqrt(6),step=1e-3)
but this returns 0.0:0.001:2.449
The result, 0.0:0.001:2.449 is indeed a range of evenly spaced values, and can be indexed, sliced, broadcasted on, and generally used just like any other AbstractArray. For example:
julia> xi2 = range(0,sqrt(6),step=1e-3)
0.0:0.001:2.449
julia> xi2[1]
0.0
julia> xi2[100]
0.099
julia> length(xi2)
2450
julia> isa(xi2, AbstractArray)
true
julia> sin.(xi2)
2450-element Vector{Float64}:
0.0
0.0009999998333333417
0.0019999986666669333
0.002999995500002025
⋮
0.6408405168240852
0.6400725224915994
0.6393038880866445
0.6385346143778549
If for any reason you want to turn xi2 into a full Array preemptively, you can do that with collect
julia> collect(xi2)
2450-element Vector{Float64}:
0.0
0.001
0.002
0.003
⋮
2.446
2.447
2.448
2.449
which will "materialize" the range, so to speak. This uses a lot more memory than the Range though, and is less often necessary than you might expect.

upsample complex matrix in julia

I have a complex matrix (i.e. Array{Complex{Float64},2}) in julia that I would like to upsample in one dimension.
My equivalent python code is:
data_package['time_series'] = sp.signal.resample(data_package['time_series'] .astype('complex64'), data_package['time_series'].shape[1]*upsample_factor, axis=1)
A resample() function can be found in DSP.jl. But it only works on Vectors, so one has to apply it manually along the desired dimension. One possible way looks like this (resampling along the second dimension, with a new rate of 2):
julia> using DSP
julia> test = reshape([1.0im, 2.0im, 3.0im, 4., 5., 6.], 3, 2)
3×2 Matrix{ComplexF64}:
0.0+1.0im 4.0+0.0im
0.0+2.0im 5.0+0.0im
0.0+3.0im 6.0+0.0im
julia> newRate = 2
2
julia> up = [resample(test[:, i], newRate) for i in 1:size(test, 2)] # gives a vector of vectors
2-element Vector{Vector{ComplexF64}}:
[0.0 + 0.9999042566881922im, 0.0 + 1.2801955476665785im, 0.0 + 1.9998085133763843im, 0.0 + 2.968204475861045im, 0.0 + 2.9997127700645763im]
[3.9996170267527686 + 0.0im, 4.466495565312296 + 0.0im, 4.999521283440961 + 0.0im, 6.154504493506763 + 0.0im, 5.9994255401291525 + 0.0im]
julia> cat(up..., dims = 2) # fuse to matrix
5×2 Matrix{ComplexF64}:
0.0+0.999904im 3.99962+0.0im
0.0+1.2802im 4.4665+0.0im
0.0+1.99981im 4.99952+0.0im
0.0+2.9682im 6.1545+0.0im
0.0+2.99971im 5.99943+0.0im
Please consider the package FFTResampling.jl
The method is based on the FFT, assuming periodic and band-limited input.

Julia - console behaving differently than include("myfile.jl")

I would like to execute the following code, which works perfectly well when I type every line into my Julia console on Windows 10, but throws an error because of the mismatching type LinearAlgebra.Adjoint{Float64,Array{Float64,2}} (my subsequent code expects Array{Float64,2}).
This is the code:
x = [0.2, 0.1, 0.2]
y = [-0.5 0.0 0.5]
fx = x * y
fy = fx'
return fx::Array{Float64,2}, fy::Array{Float64,2}
There is a TypeError, because fy seems to be of type LinearAlgebra.Adjoint{Float64,Array{Float64,2}} instead of Array{Float64,2}.
How can I do a transpose and get a "normal" Array{Float64,2} object ?
And why does this work when I type every line into my Julia console, but does not when I run the file via include("myfile.jl") ?
Use collect to have a copy of actual data rather than a transformed view of the original (note that this rule applies to many other similar situations):
julia> x = [0.2, 0.1, 0.2];
julia> y = [-0.5 0.0 0.5];
julia> fx = x * y
3×3 Array{Float64,2}:
-0.1 0.0 0.1
-0.05 0.0 0.05
-0.1 0.0 0.1
julia> fy = fx'
3×3 LinearAlgebra.Adjoint{Float64,Array{Float64,2}}:
-0.1 -0.05 -0.1
0.0 0.0 0.0
0.1 0.05 0.1
julia> fy = collect(fx')
3×3 Array{Float64,2}:
-0.1 -0.05 -0.1
0.0 0.0 0.0
0.1 0.05 0.1
To get a normal Matrix{Float64} use:
fy = permutedims(fx)
or
fy = Matrix(fx')
Those two are not 100% equivalent in general as fx' is a recursive adjoint operation (conjugate transpose), while permutedims is a non-recursive transpose, but in your case they will give the same result.
What does recursive adjoint mean exactly?
recursive: the conjugate transpose is applied recursively to all entries of the array (in your case you have array of numbers and transpose of a number is the same number so this does not change anything);
adjoint: if you would have complex numbers then the operation would return their complex conjugates (in your case you have real numbers so this does not change anything);
Here is an example when both things matter:
julia> x = [[im, -im], [1-im 1+im]]
2-element Array{Array{Complex{Int64},N} where N,1}:
[0+1im, 0-1im]
[1-1im 1+1im]
julia> permutedims(x)
1×2 Array{Array{Complex{Int64},N} where N,2}:
[0+1im, 0-1im] [1-1im 1+1im]
julia> Matrix(x')
1×2 Array{AbstractArray{Complex{Int64},N} where N,2}:
[0-1im 0+1im] [1+1im; 1-1im]
However, unless you really need to you do not have to do it if you really need to get a conjugate transpose of your data. It is enough to change type assertion to
return fx::Array{Float64,2}, fy::AbstractArray{Float64,2}
or
return fx::Matrix{Float64}, fy::AbstractMatrix{Float64}
Conjugate transpose was designed to avoid unnecessary allocation of data and most of the time this will be more efficient for you (especially with large matrices).
Finally the line:
return fx::Array{Float64,2}, fy::Array{Float64,2}
throws an error also in the Julia command line (not only when run from a script).

What's Julia's equivalent of R's seq(..., length.out = n)

I can see from this link that R's equivalent of seq is n:m in (http://www.johnmyleswhite.com/notebook/2012/04/09/comparing-julia-and-rs-vocabularies/).
But the case of seq(a,b, length.out = n) is not covered.
For example seq(1, 6, length.out=3) gives c(1.0, 3.5, 6.0). It is a really nice way to specify the number of outputs.
What's its equivalent in Julia?
As of Julia 1.0:
linspace has been deprecated. You can still use range:
julia> range(0, stop = 5, length = 3)
0.0:2.5:5.0
As #TasosPapastylianou noted, if you want this to be a vector of values, you can use collect:
julia> collect( range(0, stop = 5, length = 3) )
3-element Array{Float64,1}:
0.0
2.5
5.0
You are looking for the linspace function. Note this is synonymous to the equivalent function in matlab / octave.
Also note that this returns a "steprange" type object:
julia> a = linspace(1,5,9)
1.0:0.5:5.0
julia> typeof(a)
StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}}
julia> collect(a)
9-element Array{Float64,1}:
1.0
1.5
2.0
2.5
3.0
3.5
4.0
4.5
5.0
PS: similarly, there exists a range function which is equivalent to the start:step:stop syntax, similar to the seq(from=, to=, by=) syntax in R.

Resources