Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Array type promotion in Julia

In Julia, I can use promote to make various types of objects compatible. For example:

>promote(1, 1.0)
(1.0,1.0)
>typeof(promote(1, 1.0))
(Float64, Float64)

However, if I use promote on arrays, it doesn't give me what I want:

>promote([1], [1.0])
([1],[1.0])
>typeof(promote([1], [1.0]))
(Array{Int64,1},Array{Float64,1})

What I want is for the Int64 array to be converted to a Float64 array, so I get something like:

>promote_array([1], [1.0])
([1.0],[1.0])
>typeof(promote_array([1], [1.0]))
(Array{Float64,1},Array{Float64,1})

Here promote_array is a hypothetical function I made up. I'm looking for a real function that does the same. Is there a function in Julia that does what promote_array does above?

like image 321
jcrudy Avatar asked Jul 05 '15 22:07

jcrudy


People also ask

What is Float64 in Julia?

In Julia, 1 and 1.0 are different values, because they have different types: @show typeof(1); @show typeof(1.0); typeof(1) = Int64 typeof(1.0) = Float64. The standard choice for floating-point values is Float64 , which is double precision using 64 binary bits.

How do you define a type of variable in Julia?

Declaring and Initializing Variables: This can be done by simply assigning a value to the named variable. variable_name = value. These variable values can be of any datatype: String, Integer, float, array, etc. as per user needs. Julia will assign the datatype automatically to the variable.

How do you convert to float in Julia?

The string input is taken from the user using the readline() method of Julia. Next, the parse() method is used to convert the String into Float datatype. The typeof() method outputs the datatype of the resulting float value.

What is :: In Julia?

A return type can be specified in the function declaration using the :: operator. This converts the return value to the specified type. This function will always return an Int8 regardless of the types of x and y .


2 Answers

I found the function Base.promote_eltype, which I can use to get what I want:

function promote_array(arrays...)
  eltype = Base.promote_eltype(arrays...)
  tuple([convert(Array{eltype}, array) for array in arrays]...)
end

This promote_array function then gives me the output I'm looking for:

>promote_array([1], [1.0])
([1.0],[1.0])
>typeof(promote_array([1], [1.0]))
(Array{Float64,1},Array{Float64,1})

The above solves my problem, although the existence of Base.promote_eltype suggests there may be an already built solution that I don't know about yet.

like image 69
jcrudy Avatar answered Oct 19 '22 10:10

jcrudy


Here is what I would do:

function promote_array{S,T}(x::Vector{S},y::Vector{T})
    U = promote_type(S,T)
    convert(Vector{U},x), convert(Vector{U},y)
end

I'm not sure what your use case is exactly, but the following pattern is something I see as being fairly commonly required for code that has the tightest typing possible while being general:

function foo{S<:Real, T<:Real}(x::Vector{S},y::Vector{T})
    length(x) != length(y) && error("Length mismatch")
    result = zeros(promote_type(S,T), length(x))
    for i in 1:length(x)
        # Do some fancy foo-work here
        result[i] = x[i] + y[i]
    end
    return result
end
like image 30
IainDunning Avatar answered Oct 19 '22 10:10

IainDunning