Is there a function to clip an array to a maximum value? e.g. set values in an arr

Is there a function to clip an array to a maximum value? e.g. set values in an array greater than 1.0 to 1.0

Note that the original poster on Slack cannot see your response here on Discourse. Consider transcribing the appropriate answer back to Slack, or pinging the poster here on Discourse so they can follow this thread.
(Original message :slack:) (More Info)

Yup, it’s called clamp!:

help?> clamp!
search: clamp! clamp

  clamp!(array::AbstractArray, lo, hi)

  Restrict values in array to the specified range, in-place. See also clamp.

Just for clamping the maximum, and not the minimum, you can use

x .= min.(x, hi) 

I wonder why we kept the clamp! function, given that it seems equivalent to

array .= clamp.(array, lo, hi)

Probably it was just an oversight that it didn’t get removed when we removed the other vectorized functions in favor of dot calls?

2 Likes

Yeah, I was actually surprised to find it as well–it does feel like a vestige from the era before broadcasting.

1 Like

The redundancy has been mentioned before in stackoverflow.

Curiously, I get different timing for clamp vs. clamp!:

using BenchmarkTools
X0 = randn(100,100); X = copy(X0);
@btime clamp!($X, -0.5, 0.5);
#  1.803 μs (0 allocations: 0 bytes)
clampme!(X, lo, hi) = X .= clamp.(X, lo, hi)
X = copy(X0);
@btime clampme!($X, -0.5, 0.5);
#  9.515 μs (0 allocations: 0 bytes)

It seems that clamp! does an @inbounds loop, and perhaps broadcasting fails to do it automatically. Or perhaps this is user benchmarking error.

I think slowness may be related to this issue

I don’t think so, since that issue is for 1d arrays, but in this case it’s almost the same speed for 1d arrays:

julia> X = randn(100*100);

julia> @btime clamp!($X, -0.5, 0.5);
  1.723 μs (0 allocations: 0 bytes)

julia> @btime clampme!($X, -0.5, 0.5);
  1.721 μs (0 allocations: 0 bytes)

It seems to be specific to broadcast loops for 2d (or more) arrays.