Skip to content

Commit 6e7fc8e

Browse files
committed
Add assert_floating_point
1 parent 2b18b37 commit 6e7fc8e

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

NEWS.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ This page describes the most important changes in `TypeUtils`. The format is bas
44
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
55
[Semantic Versioning](https://semver.org/spec).
66

7+
## Unreleased
8+
9+
## Added
10+
11+
- Macro `@assert_floating_point` to assert whether arguments or variables of a function
12+
do use floating-point for storing their value(s).
13+
14+
- New function `assert_floating_point` to assert whether an object does use floating-point
15+
for storing its value(s). This method is a *trait*: its result only depend on the type
16+
of its argument and this type may be directly specified.
17+
18+
719
## Version 1.5.1 (2025-04-12)
820

921
### Changed

src/TypeUtils.jl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module TypeUtils
22

33
export
4+
@assert_floating_point,
45
ArrayAxes,
56
ArrayAxis,
67
ArrayShape,
@@ -15,6 +16,7 @@ export
1516
as_array_size,
1617
as_eltype,
1718
as_return,
19+
assert_floating_point,
1820
bare_type,
1921
convert_bare_type,
2022
convert_eltype,
@@ -54,6 +56,22 @@ macro public(args::Union{Symbol,Expr}...)
5456
end
5557
VERSION v"1.11.0-DEV.469" && eval(Expr(:public, Symbol("@public")))
5658

59+
"""
60+
@assert_floating_point A B ...
61+
62+
throws an `ArgumentError` exception if any of the variables `A`, `B`, etc. does not use
63+
floating-point to store its value(s).
64+
65+
See also [`assert_floating_point`](@ref).
66+
67+
"""
68+
macro assert_floating_point(args::Symbol...)
69+
code = [:(assert_floating_point($(QuoteNode(arg)), $(esc(arg)))) for arg in args]
70+
return quote
71+
$(code...)
72+
end
73+
end
74+
5775
"""
5876
c = TypeUtils.Converter(f, T::Type)
5977
@@ -878,6 +896,52 @@ for any `x`.
878896
convert_floating_point_type(::Type{T}) where {T} =
879897
Converter(convert_floating_point_type, floating_point_type(T))
880898

899+
"""
900+
assert_floating_point(Bool, x) -> bool
901+
902+
yields whether `x` uses floating-point to store its value(s). For n-tuples, the same
903+
floating-point type must be used for all values.
904+
905+
"""
906+
assert_floating_point(::Type{Bool}, x) =
907+
assert_floating_point(Bool, typeof(x))
908+
909+
assert_floating_point(::Type{Bool}, ::Type{<:AbstractArray{T}}) where {T} =
910+
assert_floating_point(Bool, T)
911+
912+
assert_floating_point(::Type{Bool}, ::Type{<:NTuple{N,T}}) where {N,T} =
913+
assert_floating_point(Bool, T)
914+
915+
assert_floating_point(::Type{Bool}, ::DataType) = false
916+
917+
assert_floating_point(::Type{Bool}, ::Type{T}) where {T<:Number} =
918+
_assert_floating_point(Bool, real_type(T))
919+
920+
_assert_floating_point(::Type{Bool}, ::Type{T}) where {T<:AbstractFloat} = isconcretetype(T)
921+
_assert_floating_point(::Type{Bool}, ::Type{T}) where {T<:Number} = false
922+
923+
"""
924+
assert_floating_point([name,] x)
925+
926+
throws an exception if `x` does not use floating-point to store its value(s). Optional
927+
`name` argument is to specify the name to use for the error message.
928+
929+
See also [`@assert_floating_point`](@ref).
930+
931+
"""
932+
assert_floating_point(x) = assert_floating_point(typeof(x))
933+
assert_floating_point(::Type{T}) where {T} =
934+
assert_floating_point(Bool, T) ? nothing : throw_not_floating_point(T)
935+
936+
assert_floating_point(name::Union{Symbol,AbstractString}, x) = assert_floating_point(name, typeof(x))
937+
assert_floating_point(name::Union{Symbol,AbstractString}, ::Type{T}) where {T} =
938+
assert_floating_point(Bool, T) ? nothing : throw_not_floating_point(name, T)
939+
940+
@noinline throw_not_floating_point(::Type{T}) where {T} =
941+
throw(ArgumentError("type `$T` is not floating-point"))
942+
@noinline throw_not_floating_point(name::Union{Symbol,AbstractString}, ::Type{T}) where {T} =
943+
throw(ArgumentError("argument or variable `$name` of type `$T` is not floating-point"))
944+
881945
"""
882946
promote_eltype(args...)
883947

test/runtests.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,36 @@ same_value_and_type(x::T, y::T) where {T} = (x === y) || (x == y)
669669
@test map(x -> convert_floating_point_type(Float32, x), vals) === @inferred map(convert_floating_point_type(Float32), vals)
670670
end
671671

672+
# assert_floating_point
673+
@test !assert_floating_point(Bool, 1)
674+
@test !assert_floating_point(Bool, π)
675+
@test !assert_floating_point(Bool, 1//2)
676+
@test !assert_floating_point(Bool, "hello")
677+
@test !assert_floating_point(Bool, [0x1, 0x2])
678+
@test !assert_floating_point(Bool, (0x1, -1))
679+
@test assert_floating_point(Bool, 1.0)
680+
@test assert_floating_point(Bool, complex(-2f0,3f0))
681+
@test assert_floating_point(Bool, [0.0f0, 2.0f0])
682+
@test !assert_floating_point(Bool, Int)
683+
@test !assert_floating_point(Bool, AbstractFloat)
684+
@test assert_floating_point(Bool, Float16)
685+
@test assert_floating_point(Bool, Float32)
686+
@test assert_floating_point(Bool, Float64)
687+
@test assert_floating_point(Bool, Complex{Float32})
688+
@test assert_floating_point(Bool, AbstractRange{Float64})
689+
# only ok for homogeneous tuples
690+
@test !assert_floating_point(Bool, (-1.0, 2.0f0))
691+
@test assert_floating_point(Bool, (-1.0, 2.0))
692+
@test !assert_floating_point(Bool, Tuple{Float64,Float32})
693+
@test assert_floating_point(Bool, Tuple{Float32,Float32})
694+
#
695+
x, y = 2, 3.0
696+
@test assert_floating_point(y) === nothing
697+
@test assert_floating_point("y", y) === nothing
698+
@test_throws Exception assert_floating_point(x)
699+
@test_throws Exception assert_floating_point(:x, x)
700+
@test_throws Exception @assert_floating_point x y
701+
672702
# unitless
673703
@test bare_type(Real) === @inferred unitless(Real)
674704
@test bare_type(Integer) === @inferred unitless(Integer)

0 commit comments

Comments
 (0)