Convert arrays to single precision

question

#1

Hello, I was wondering if there exists a function to convert objects, e.g. Array, SparseMatrix, special matrix types like Diagonal, etc…) to single precision.

It should also handle converting objects of complex numbers (e.g. Matrix{Complex{Float64}} -> Matrix{Complex{Float32}}).

Thanks,
Jeremy


#2
julia> A = rand(Complex128, 2, 2)
2×2 Array{Complex{Float64},2}:
 0.675516+0.723924im  0.599831+0.998357im
 0.526924+0.509325im  0.223859+0.164175im

julia> convert(Matrix{Complex64}, A)
2×2 Array{Complex{Float32},2}:
 0.675516+0.723924im  0.599831+0.998357im
 0.526924+0.509325im  0.223859+0.164175im

#3

I know about convert, but I am looking for something that will preserve the container type…


#4

i don’t believe such a function exists, but Julia provides all the tools to construct one.

julia> singlify(x::Float64) = Float32(x)
singlify (generic function with 1 method)

julia> singlify(x::Complex{Float64}) = Complex{Float32}(x)
singlify (generic function with 2 methods)

Broadcasting works quite nicely for applying the function elementwise to various different kinds of arrays:

julia> x = rand(2, 2)
2×2 Array{Float64,2}:
 0.689747  0.539186
 0.607853  0.858326

julia> singlify.(x)
2×2 Array{Float32,2}:
 0.689747  0.539186
 0.607853  0.858326

julia> x = sprand(2, 2, 0.5)
2×2 SparseMatrixCSC{Float64,Int64} with 4 stored entries:
  [1, 1]  =  0.0518641
  [2, 1]  =  0.896834
  [1, 2]  =  0.0067949
  [2, 2]  =  0.57429

julia> singlify.(x)
2×2 SparseMatrixCSC{Float32,Int64} with 4 stored entries:
  [1, 1]  =  0.0518641
  [2, 1]  =  0.896834
  [1, 2]  =  0.0067949
  [2, 2]  =  0.57429

Unfortunately, Diagonals aren’t handled perfectly:

julia> x = Diagonal([1., 2])
2×2 Diagonal{Float64}:
 1.0   ⋅ 
  ⋅   2.0

julia> singlify.(x)
2×2 SparseMatrixCSC{Float32,Int64} with 2 stored entries:
  [1, 1]  =  1.0
  [2, 2]  =  2.0

The fact that broadcasting over a Diagonal returns a plain sparse matrix is, fortunately, resolved in the latest nightly builds of Julia, so in the future, you should get a Diagonal out.


#5

I see, thanks!


#6

Note that the broadcasting solution above makes a copy even in cases where the data is already of single precision.
Another solution is to convert to an AbstractArray

julia> x = sprand(2, 2, 0.5)
2×2 SparseMatrixCSC{Float64,Int64} with 1 stored entry:
  [1, 2]  =  0.897311

julia> convert(AbstractArray{Float32}, x)
2×2 SparseMatrixCSC{Float32,Int64} with 1 stored entry:
  [1, 2]  =  0.897311

julia> x = Diagonal([1., 2])
2×2 Diagonal{Float64}:
 1.0   ⋅ 
  ⋅   2.0

julia> convert(AbstractArray{Float32}, x)
2×2 Diagonal{Float32}:
 1.0   ⋅ 
  ⋅   2.0

#7

Even better!