Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

represent the error info with singleton types instead of NamedTuple #11

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions src/CheckedSizeProduct.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
module CheckedSizeProduct
export checked_size_product

"""
StatusInvalidValue::DataType

Singleton type. Returned by [`checked_size_product`](@ref) in case its input
contained an invalid value. An invalid value is either:
* less than zero
* equal to `typemax(T)`

See also: [`StatusOverflow`](@ref)
"""
struct StatusInvalidValue end

"""
StatusOverflow::DataType

Singleton type. Returned by [`checked_size_product`](@ref) in case the product
is not representable in the element type of the input.

See also: [`StatusInvalidValue`](@ref)
"""
struct StatusOverflow end

"""
checked_size_product(size_tuple)

Expand All @@ -22,12 +44,11 @@ module CheckedSizeProduct
* `==`
2. Calculate the product. In case no element is negative, no element is
`typemax(T)` and the product is representable as `T`, return the product.
Otherwise, return a `NamedTuple` containing two Boolean properties:
* `any_is_negative`: at least one element is negative
* `any_is_typemax`: at least one element is the maximum value representable
in the given type, as given by `typemax`
If a `NamedTuple` is returned with both fields `false`, the product is not
representable as `T`.
Otherwise return:
* a value of type [`StatusInvalidValue`]: the input contains a negative
element, or an element equal to `typemax(T)`
* a value of type [`StatusOverflow`]: the product is not representable as
`T`

Throws when given an empty tuple to avoid having to choose a default return
type arbitrarily.
Expand Down Expand Up @@ -106,7 +127,11 @@ module CheckedSizeProduct
if !(any_is_negative | any_is_typemax | is_not_representable)
product
else
(; any_is_negative = any_is_negative, any_is_typemax = any_is_typemax)
if any_is_negative | any_is_typemax
StatusInvalidValue()
else
StatusOverflow()
end
end
end
end
14 changes: 6 additions & 8 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ using .ExampleInts: ExampleInt
(-1, typemax(Int)), (typemax(Int), -1),
(0, -4, -4), (-4, 1, 0), (-4, -4, 1),
)
@test (checked_size_product(t)).any_is_negative
@test checked_size_product(t) isa CheckedSizeProduct.StatusInvalidValue
s = map(ExampleInt, t)
@test (checked_size_product(s)).any_is_negative
@test checked_size_product(s) isa CheckedSizeProduct.StatusInvalidValue
end
end
@testset "input includes `typemax(T)`" begin
Expand All @@ -89,9 +89,9 @@ using .ExampleInts: ExampleInt
for t ∈ (
(m,), (m, m), (1, m), (m, 1), (0, m), (m, 0), (-1, m), (m, -1),
)
@test (checked_size_product(t)).any_is_typemax
@test checked_size_product(t) isa CheckedSizeProduct.StatusInvalidValue
s = map(ExampleInt, t)
@test (checked_size_product(s)).any_is_typemax
@test checked_size_product(s) isa CheckedSizeProduct.StatusInvalidValue
end
end
@testset "overflows" begin
Expand All @@ -101,11 +101,9 @@ using .ExampleInts: ExampleInt
(m, m), (15, m), (m, 15), (m, m, m), (1, m, m), (m, 1, m), (m, m, 1),
(b, b), (1, b, b),
)
@test !(checked_size_product(t)).any_is_negative
@test !(checked_size_product(t)).any_is_typemax
@test checked_size_product(t) isa CheckedSizeProduct.StatusOverflow
s = map(ExampleInt, t)
@test !(checked_size_product(s)).any_is_negative
@test !(checked_size_product(s)).any_is_typemax
@test checked_size_product(s) isa CheckedSizeProduct.StatusOverflow
end
end
@testset "overflows, but OK because of multiplication with zero" begin
Expand Down
Loading