# How to cast function input parameters

**URL:** <https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910>\
**Category:** General Usage\
**Tags:** type, convert\
**Created:** [November 22, 2021, 7:37pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910 "2021-11-22T19:37:52Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [November 22, 2021, 7:37pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/1 "2021-11-22T19:37:52Z")

</div>

In the code below, I have a `Float32` vector to which I would like to add a number. To ensure that computation happens at single precision, I force the input parameters to be `Float32`. Is it possible to allow the function to take also `Int` or `Float64` as argument, but at the same time directly cast them to `Float32` without having to write explicit `converts` in the function?

```julia
function add_float32!(v::Vector{Float32}, f::Float32)
    v .+= f
end

a = rand(Float32, 10) 
b = 123.
c = 4

add_float32!(a, b)
add_float32!(a, c)

```

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [November 22, 2021, 8:53pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/2 "2021-11-22T20:53:47Z")

</div>

You can do it with an explicit `convert` without adding any complexity to your code.

```julia
function add_float32!(v::Vector{Float32}, f)
    v .+= convert(Float32, f)
end

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [November 22, 2021, 9:36pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/3 "2021-11-22T21:36:49Z")

</div>

You don’t need this. Since you are assigning into a `Vector{Float32}`, convert happens automatically. Just write

```julia
function add_float32!(v::Vector{Float32}, f)
    v .+= f
end
a = rand(Float32, 10) 
b = 123.0
add_float32!(a, b)
10-element Vector{Float32}:
 123.8254
 123.764946
 123.354645
 123.38994
 123.01592
 123.38142
 123.62168
 123.07243
 123.63172
 123.220024

```

**Edit:** It does seem though that there is a performance difference. Converting the second input to `Float32` is faster if it is a ‘wider’ type, like `Float64`.

A more generic solution could be

```julia
function add_all!(v::AbstractArray{T}, f) where {T}
    v .+= T(f)
end

```

This works for most number types, and for several array types as well.

---

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [November 22, 2021, 10:34pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/4 "2021-11-22T22:34:42Z")

</div>

It is still a bit unclear to me. I wrote a benchmark with a very large array, and I do not see performance difference between a `Float32` and `Float64` `f` argument if I use a code without casting. When is Julia casting the computation to `Float64` and then back to `Float32` and when not?

With code without casting I meant:

```julia
unction add_float32!(v::Vector{Float32}, f)
    v .+= f
end

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [November 23, 2021, 12:05am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/5 "2021-11-23T00:05:00Z")

</div>

if you leave it like that (btw, you should), then Julia will use the promotion rule for whatever `f` ends up being, for example:

```julia
julia> a = Float32[1,2,3]

julia> a .+= Float64(1)
3-element Vector{Float32}:
 2.0
 3.0
 4.0

julia> a .+= 1
3-element Vector{Float32}:
 3.0
 4.0
 5.0

julia> a .+= UInt(1)
3-element Vector{Float32}:
 4.0
 5.0
 6.0

```

it all works because Julia knows how to add a `Float32` to a `Float64/Int/UInt` etc.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [November 23, 2021, 12:09am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/6 "2021-11-23T00:09:22Z")

</div>

I misread this sentence initially, thinking you were saying you _were_ seeing the performance drop, hence the edit.

> [@Chiil](#):
>
> I wrote a benchmark with a very large array, and I do not see performance difference between a `Float32` and `Float64` `f` argument if I use a code without casting.

Strange, I do also see the performance difference mentioned by @DNF

```julia
julia> function add_all_noconvert!(v::AbstractArray{T}, f) where {T}
           v .+= f
       end
add_all_noconvert! (generic function with 1 method)

julia> function add_all!(v::AbstractArray{T}, f) where {T}
           v .+= T(f)
       end
add_all! (generic function with 1 method)

julia> a = rand(Float32, 10000); @btime add_all_noconvert!(a, 1.0);
  1.971 μs (0 allocations: 0 bytes)

julia> a = rand(Float32, 10000); @btime add_all!(a, 1.0);
  1.255 μs (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [November 23, 2021, 12:42am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/7 "2021-11-23T00:42:09Z")

</div>

I want to point out that this is not a (generally) legal optimization because rounding could be different:

```julia
julia> a = rand(Float32, 10^5); b = rand(Float64, 10^5);

julia> foldl(+, a .+ b)
100169.7271276231

julia> foldl(+, a .+ Float32.(b))
100170.37f0

```

although in this case using `sum()` which does adding in better order (paired?) mitigate the issue, but this should convince you that rounding before adding could lead to different result in general.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 23, 2021, 1:46am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/8 "2021-11-23T01:46:30Z")

</div>

> [@jling](#):
>
> `sum()` which does adding in better order (paired?)

Yes, it uses [pairwise summation](https://en.wikipedia.org/wiki/Pairwise_summation).

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [November 23, 2021, 7:30am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/9 "2021-11-23T07:30:18Z")

</div>

The difference in performance compared to raw broadcast is, I guess, because of SIMD opportunities: with just `a .+= x`, if `a` is an array of single-precision floats and `x` is double-precision, the sum is done in double precision and converted to single on write. With `a .+= T(x)`, the sum is computed in single precision meaning more array elements can be updated in parallel using SIMD operations.

> [@Chiil](#):
>
> I wrote a benchmark with a very large array, and I do not see performance difference between a `Float32` and `Float64` `f` argument if I use a code without casting.

If the difference is due to SIMD, then it depends on whether or not the data can be fetched from memory at high enough rate. With large arrays, you may be benchmarking the memory speed rather than computation. On my computer, there’s a difference with an array of 1M `Float32`s which vanishes on 10M.

---

<div class="post-metadata">

**Author:** ![Chiil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chiil/32/27474_2.png) [@Chiil](https://discourse.julialang.org/u/Chiil)\
**Post date:** [November 23, 2021, 8:11am UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/10 "2021-11-23T08:11:55Z")

</div>

I see this drop in my actual code (not the minimal example), therefore I got confused.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [November 23, 2021, 8:32pm UTC](https://discourse.julialang.org/t/how-to-cast-function-input-parameters/71910/11 "2021-11-23T20:32:27Z")

</div>

Indeed! I meant strange that we don’t both see the difference. My initial reply (that I edited away) was explaining exactly this!
