How to mutate the value (not binding) of a scalar?

Then I’d recommend implementing it like this:

function geman_mcclure!(w, d2, s)
    @. w = one(s) / (one(s) + d2 / s^2)^2
end
geman_mcclure(d2, s) = geman_cclure!(similar(d2), d2, s)

If d2 for the non-mutating version is also expected to be a Vector, as otherwise the method won’t work:

julia> gm1(d2, s) = one(s) / (one(s)+d2/s^2)^2
gm1 (generic function with 1 method)

julia> gm1(rand(Float64, 10), rand(Float64))
ERROR: MethodError: no method matching +(::Float64, ::Vector{Float64})
For element-wise addition, use broadcasting with dot syntax: scalar .+ array

Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...)
   @ Base operators.jl:578
  +(::T, ::T) where T<:Union{Float16, Float32, Float64}
   @ Base float.jl:406
  +(::Union{Float16, Float32, Float64}, ::BigFloat)
   @ Base mpfr.jl:414
  ...

Stacktrace:
 [1] gm1(d2::Vector{Float64}, s::Float64)
   @ Main ./REPL[7]:1
 [2] top-level scope
   @ REPL[8]:1

Though usually, we try to avoid writing an explicitly vectorized function like geman_mcclure! and just directly use broadcasting inline, to allow for loop fusion to occur in longer chains (in which case your original scalar version is perfect already, and no other methods would be needed). It’s just a question of what you’d expect users to pass in.

1 Like