Skip to content

Commit

Permalink
add missing clamp function for IOBuffer (#55424)
Browse files Browse the repository at this point in the history
The `clamp` function was defined in Base.Math, but required to be in
Base now, so move it to intfuncs with other similar functions

Fixes #55279
  • Loading branch information
KristofferC authored Aug 9, 2024
2 parents ac9558c + fc6047b commit 3db1d19
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 104 deletions.
99 changes: 99 additions & 0 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1237,3 +1237,102 @@ function binomial(x::Number, k::Integer)
# and instead divide each term by i, to avoid spurious overflow.
return prod(i -> (x-(i-1))/i, OneTo(k), init=oneunit(x)/one(k))
end

"""
clamp(x, lo, hi)
Return `x` if `lo <= x <= hi`. If `x > hi`, return `hi`. If `x < lo`, return `lo`. Arguments
are promoted to a common type.
See also [`clamp!`](@ref), [`min`](@ref), [`max`](@ref).
!!! compat "Julia 1.3"
`missing` as the first argument requires at least Julia 1.3.
# Examples
```jldoctest
julia> clamp.([pi, 1.0, big(10)], 2.0, 9.0)
3-element Vector{BigFloat}:
3.141592653589793238462643383279502884197169399375105820974944592307816406286198
2.0
9.0
julia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi
3-element Vector{Int64}:
6
6
10
```
"""
function clamp(x::X, lo::L, hi::H) where {X,L,H}
T = promote_type(X, L, H)
return (x > hi) ? convert(T, hi) : (x < lo) ? convert(T, lo) : convert(T, x)
end

"""
clamp(x, T)::T
Clamp `x` between `typemin(T)` and `typemax(T)` and convert the result to type `T`.
See also [`trunc`](@ref).
# Examples
```jldoctest
julia> clamp(200, Int8)
127
julia> clamp(-200, Int8)
-128
julia> trunc(Int, 4pi^2)
39
```
"""
function clamp(x, ::Type{T}) where {T<:Integer}
# delegating to clamp(x, typemin(T), typemax(T)) would promote types
# this way, we avoid unnecessary conversions
# think of, e.g., clamp(big(2) ^ 200, Int16)
lo = typemin(T)
hi = typemax(T)
return (x > hi) ? hi : (x < lo) ? lo : convert(T, x)
end


"""
clamp!(array::AbstractArray, lo, hi)
Restrict values in `array` to the specified range, in-place.
See also [`clamp`](@ref).
!!! compat "Julia 1.3"
`missing` entries in `array` require at least Julia 1.3.
# Examples
```jldoctest
julia> row = collect(-4:4)';
julia> clamp!(row, 0, Inf)
1×9 adjoint(::Vector{Int64}) with eltype Int64:
0 0 0 0 0 1 2 3 4
julia> clamp.((-4:4)', 0, Inf)
1×9 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0
```
"""
function clamp!(x::AbstractArray, lo, hi)
@inbounds for i in eachindex(x)
x[i] = clamp(x[i], lo, hi)
end
x
end

"""
clamp(x::Integer, r::AbstractUnitRange)
Clamp `x` to lie within range `r`.
!!! compat "Julia 1.6"
This method requires at least Julia 1.6.
"""
clamp(x::Integer, r::AbstractUnitRange{<:Integer}) = clamp(x, first(r), last(r))
8 changes: 4 additions & 4 deletions base/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,8 @@ julia> rm("my_file.txt")
```
"""
readuntil(filename::AbstractString, delim; kw...) = open(io->readuntil(io, delim; kw...), convert(String, filename)::String)
readuntil(stream::IO, delim::UInt8; kw...) = _unsafe_take!(copyuntil(IOBuffer(sizehint=70), stream, delim; kw...))
readuntil(stream::IO, delim::Union{AbstractChar, AbstractString}; kw...) = String(_unsafe_take!(copyuntil(IOBuffer(sizehint=70), stream, delim; kw...)))
readuntil(stream::IO, delim::UInt8; kw...) = _unsafe_take!(copyuntil(IOBuffer(sizehint=16), stream, delim; kw...))
readuntil(stream::IO, delim::Union{AbstractChar, AbstractString}; kw...) = String(_unsafe_take!(copyuntil(IOBuffer(sizehint=16), stream, delim; kw...)))
readuntil(stream::IO, delim::T; keep::Bool=false) where T = _copyuntil(Vector{T}(), stream, delim, keep)


Expand Down Expand Up @@ -617,7 +617,7 @@ Logan
readline(filename::AbstractString; keep::Bool=false) =
open(io -> readline(io; keep), filename)
readline(s::IO=stdin; keep::Bool=false) =
String(_unsafe_take!(copyline(IOBuffer(sizehint=70), s; keep)))
String(_unsafe_take!(copyline(IOBuffer(sizehint=16), s; keep)))

"""
copyline(out::IO, io::IO=stdin; keep::Bool=false)
Expand Down Expand Up @@ -1111,7 +1111,7 @@ function copyuntil(out::IO, io::IO, target::AbstractString; keep::Bool=false)
end

function readuntil(io::IO, target::AbstractVector{T}; keep::Bool=false) where T
out = (T === UInt8 ? resize!(StringVector(70), 0) : Vector{T}())
out = (T === UInt8 ? resize!(StringVector(16), 0) : Vector{T}())
readuntil_vector!(io, target, keep, out)
return out
end
Expand Down
101 changes: 1 addition & 100 deletions base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import .Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin,
using .Base: sign_mask, exponent_mask, exponent_one,
exponent_half, uinttype, significand_mask,
significand_bits, exponent_bits, exponent_bias,
exponent_max, exponent_raw_max
exponent_max, exponent_raw_max, clamp, clamp!

using Core.Intrinsics: sqrt_llvm

Expand Down Expand Up @@ -69,104 +69,6 @@ end
return Txy, T(xy-Txy)
end

"""
clamp(x, lo, hi)
Return `x` if `lo <= x <= hi`. If `x > hi`, return `hi`. If `x < lo`, return `lo`. Arguments
are promoted to a common type.
See also [`clamp!`](@ref), [`min`](@ref), [`max`](@ref).
!!! compat "Julia 1.3"
`missing` as the first argument requires at least Julia 1.3.
# Examples
```jldoctest
julia> clamp.([pi, 1.0, big(10)], 2.0, 9.0)
3-element Vector{BigFloat}:
3.141592653589793238462643383279502884197169399375105820974944592307816406286198
2.0
9.0
julia> clamp.([11, 8, 5], 10, 6) # an example where lo > hi
3-element Vector{Int64}:
6
6
10
```
"""
function clamp(x::X, lo::L, hi::H) where {X,L,H}
T = promote_type(X, L, H)
return (x > hi) ? convert(T, hi) : (x < lo) ? convert(T, lo) : convert(T, x)
end

"""
clamp(x, T)::T
Clamp `x` between `typemin(T)` and `typemax(T)` and convert the result to type `T`.
See also [`trunc`](@ref).
# Examples
```jldoctest
julia> clamp(200, Int8)
127
julia> clamp(-200, Int8)
-128
julia> trunc(Int, 4pi^2)
39
```
"""
function clamp(x, ::Type{T}) where {T<:Integer}
# delegating to clamp(x, typemin(T), typemax(T)) would promote types
# this way, we avoid unnecessary conversions
# think of, e.g., clamp(big(2) ^ 200, Int16)
lo = typemin(T)
hi = typemax(T)
return (x > hi) ? hi : (x < lo) ? lo : convert(T, x)
end


"""
clamp!(array::AbstractArray, lo, hi)
Restrict values in `array` to the specified range, in-place.
See also [`clamp`](@ref).
!!! compat "Julia 1.3"
`missing` entries in `array` require at least Julia 1.3.
# Examples
```jldoctest
julia> row = collect(-4:4)';
julia> clamp!(row, 0, Inf)
1×9 adjoint(::Vector{Int64}) with eltype Int64:
0 0 0 0 0 1 2 3 4
julia> clamp.((-4:4)', 0, Inf)
1×9 Matrix{Float64}:
0.0 0.0 0.0 0.0 0.0 1.0 2.0 3.0 4.0
```
"""
function clamp!(x::AbstractArray, lo, hi)
@inbounds for i in eachindex(x)
x[i] = clamp(x[i], lo, hi)
end
x
end

"""
clamp(x::Integer, r::AbstractUnitRange)
Clamp `x` to lie within range `r`.
!!! compat "Julia 1.6"
This method requires at least Julia 1.6.
"""
clamp(x::Integer, r::AbstractUnitRange{<:Integer}) = clamp(x, first(r), last(r))

"""
evalpoly(x, p)
Expand Down Expand Up @@ -1690,7 +1592,6 @@ end

exp2(x::AbstractFloat) = 2^x
exp10(x::AbstractFloat) = 10^x
clamp(::Missing, lo, hi) = missing
fourthroot(::Missing) = missing

end # module
1 change: 1 addition & 0 deletions base/missing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ min(::Any, ::Missing) = missing
max(::Missing, ::Missing) = missing
max(::Missing, ::Any) = missing
max(::Any, ::Missing) = missing
clamp(::Missing, lo, hi) = missing

missing_conversion_msg(@nospecialize T) =
LazyString("cannot convert a missing value to type ", T, ": use Union{", T, ", Missing} instead")
Expand Down

0 comments on commit 3db1d19

Please sign in to comment.