Defining function that accepts both FP32 and FP64

Hi, I’m just starting out with Julia and ran into a weird issue. I defined a function that can take float values (fp32 or fp64, but strictly no int) as follows

function elim(A::Array{float},b::Array{float})
    #=
    Function which transforms matrix
    A into upper triangular matrix U
    =#
    n = size(b)[1]
    
    # Pick a pivot row
    for k in 1:n-1
        for i in k+1:n
            if A[i,k] != 0
                lambda = A[i,k]/A[k,k]
                A[i,k+1:n] -= lambda*A[k,k+1:n]
                b[i,:] -= lambda*b[k,:]
            end
        end
    end
    return A, b
end

Now when I call this function and give inputs as Float32

A = [[6, -4, 1] [-4, 6, -4] [1, -4, 6]]
b = [[-14, 36, 6] [22, -18, 7]];
A = Float32.(A)
b = Float32.(b);

U, b_t = elim(A,b)
show(stdout, "text/plain", U)
println()
show(stdout, "text/plain", b_t)

I get an error saying

MethodError: no method matching elim(::Array{Float32,2}, ::Array{Float32,2})

Stacktrace:
 [1] top-level scope at In[3]:1
 [2] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

I get the same error when I input Float64. Is there any way that I can define a function that takes both Float32 and Float64? I don’t want to define two separate functions as it’ll just clutter everything for no reason.

elim(A::Array{<:Union{Float32,Float64}},b::Array{<:Union{Float32,Float64}})
2 Likes

It is best practice to make the type signature as loose as possible to have generic and reusable code.

elim(A:: Matrix{<: AbstractFloat},...) # for accepting all Floats

or even

elim(A:: Matrix,...) # for all element types

Note that Matrix is a 2-dim array, which is probably a restriction that you want (1d or 3d arrays will not work in your code/ do not make sense).

Or is there a specific reason why you want to exclude integer element types?

6 Likes

I am using AbstractFLoat now but as elim(A::Array{<:AbstractFloat},b::Array{<:AbstractFloat}). I hope this doesn’t make any difference.

I don’t want to use Integers because I get an error

InexactError: Int64(3.3333333333333335)

Stacktrace:
 [1] Int64 at ./float.jl:710 [inlined]
 [2] convert at ./number.jl:7 [inlined]
 [3] setindex! at ./array.jl:849 [inlined]
 [4] macro expansion at ./multidimensional.jl:802 [inlined]
 [5] macro expansion at ./cartesian.jl:64 [inlined]
 [6] macro expansion at ./multidimensional.jl:797 [inlined]
 [7] _unsafe_setindex!(::IndexLinear, ::Array{Int64,2}, ::Array{Float64,1}, ::Int64, ::UnitRange{Int64}) at ./multidimensional.jl:789
 [8] _setindex! at ./multidimensional.jl:785 [inlined]
 [9] setindex! at ./abstractarray.jl:1153 [inlined]
 [10] elim(::Array{Int64,2}, ::Array{Int64,2}) at ./In[1]:13
 [11] top-level scope at In[3]:1
 [12] include_string(::Function, ::Module, ::String, ::String) at ./loading.jl:1091

I think I’m getting this error because I’m reusing the input matrices to store my solution (solution is float and when input is int, it’s giving some error). I might be wrong here, but I would like to know the exact reason of this error.

Dividing two integers gives a float in Julia:

julia> 4 / 3
1.3333333333333333
2 Likes

The InexactError is because you are trying to convert a float to an integer:

julia> Int(4/3)
ERROR: InexactError: Int64(1.3333333333333333)
Stacktrace:
 [1] Int64(::Float64) at ./float.jl:710
 [2] top-level scope at REPL[12]:1
 [3] run_repl(::REPL.AbstractREPL, ::Any) at /build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288

You need to perform a truncation or rounding before Julia will let you do that.

2 Likes

Note that if you want C-like (or Python2-like) truncating integer division you should use div(a,b) (or equivalently a ÷ b) rather than a / b.

1 Like