From cded82c98a16a805c917b658809a10dc9fd8f17f Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Tue, 14 Jan 2025 23:30:31 +0100 Subject: [PATCH 1/3] use CheckedSizeProduct.jl for implementing checked_dims Fixes #89 --- Project.toml | 4 ++++ src/FixedSizeArray.jl | 37 ++++++++++++++----------------------- src/FixedSizeArrays.jl | 2 ++ 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/Project.toml b/Project.toml index 7df4fd2..f8c69a3 100644 --- a/Project.toml +++ b/Project.toml @@ -3,5 +3,9 @@ uuid = "3821ddf9-e5b5-40d5-8e25-6813ab96b5e2" authors = ["Mosè Giordano "] version = "0.1.0" +[deps] +CheckedSizeProduct = "1b2cc9da-92e3-4b71-9788-30fc110eefda" + [compat] +CheckedSizeProduct = "1" julia = "1.10" diff --git a/src/FixedSizeArray.jl b/src/FixedSizeArray.jl index c197726..2e71190 100644 --- a/src/FixedSizeArray.jl +++ b/src/FixedSizeArray.jl @@ -96,32 +96,23 @@ Base.isassigned(a::FixedSizeArray, i::Int) = isassigned(a.mem, i) # safe product of a tuple of integers, for calculating dimensions size -checked_dims_impl(a::Int, ::Tuple{}, have_overflow::Bool) = (a, have_overflow) -function checked_dims_impl(a::Int, t::Tuple{Int,Vararg{Int,N}}, have_overflow::Bool) where {N} - b = first(t) - (m, o) = Base.Checked.mul_with_overflow(a, b) - r = Base.tail(t)::NTuple{N,Int} - checked_dims_impl(m, r, have_overflow | o)::Tuple{Int,Bool} -end - checked_dims(::Tuple{}) = 1 function checked_dims(t::Tuple{Int,Vararg{Int,N}}) where {N} - any_is_zero = any(iszero, t)::Bool - any_is_negative = any((x -> x < false), t)::Bool - any_is_typemax = any((x -> x == typemax(x)), t)::Bool - a = first(t) - r = Base.tail(t)::NTuple{N,Int} - (product, have_overflow) = checked_dims_impl(a, r, false)::Tuple{Int,Bool} - if any_is_negative - throw(ArgumentError("array dimension size can't be negative")) - end - if any_is_typemax - throw(ArgumentError("array dimension size can't be the maximum representable value")) - end - if have_overflow & !any_is_zero - throw(ArgumentError("array dimensions too great, can't represent length")) + product = checked_size_product(t) + if product isa Int + product + else + if product.any_is_negative + throw(ArgumentError("array dimension size can't be negative")) + end + if product.any_is_typemax + throw(ArgumentError("array dimension size can't be the maximum representable value")) + end + if product.is_not_representable + throw(ArgumentError("array dimensions too great, can't represent length")) + end + throw(ArgumentError("unexpected")) end - product end # broadcasting diff --git a/src/FixedSizeArrays.jl b/src/FixedSizeArrays.jl index 7470cd7..a84cdea 100644 --- a/src/FixedSizeArrays.jl +++ b/src/FixedSizeArrays.jl @@ -1,5 +1,7 @@ module FixedSizeArrays +using CheckedSizeProduct + const default_underlying_storage_type = (@isdefined Memory) ? Memory : Vector const optional_memory = (@isdefined Memory) ? (Memory,) : () From bb7b62b413a214de8a0b80285c0373309f19c02d Mon Sep 17 00:00:00 2001 From: Neven Sajko <4944410+nsajko@users.noreply.github.com> Date: Wed, 15 Jan 2025 11:02:28 +0100 Subject: [PATCH 2/3] update --- src/FixedSizeArray.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/FixedSizeArray.jl b/src/FixedSizeArray.jl index 2e71190..b275518 100644 --- a/src/FixedSizeArray.jl +++ b/src/FixedSizeArray.jl @@ -108,10 +108,7 @@ function checked_dims(t::Tuple{Int,Vararg{Int,N}}) where {N} if product.any_is_typemax throw(ArgumentError("array dimension size can't be the maximum representable value")) end - if product.is_not_representable - throw(ArgumentError("array dimensions too great, can't represent length")) - end - throw(ArgumentError("unexpected")) + throw(ArgumentError("array dimensions too great, can't represent length")) end end From eb697a889c3da5dcfe7db093581516072ba2b88d Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Fri, 17 Jan 2025 15:07:44 +0100 Subject: [PATCH 3/3] update again --- src/FixedSizeArray.jl | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/FixedSizeArray.jl b/src/FixedSizeArray.jl index b275518..85c6a0c 100644 --- a/src/FixedSizeArray.jl +++ b/src/FixedSizeArray.jl @@ -102,11 +102,8 @@ function checked_dims(t::Tuple{Int,Vararg{Int,N}}) where {N} if product isa Int product else - if product.any_is_negative - throw(ArgumentError("array dimension size can't be negative")) - end - if product.any_is_typemax - throw(ArgumentError("array dimension size can't be the maximum representable value")) + if product isa CheckedSizeProduct.StatusInvalidValue + throw(ArgumentError("invalid array dimension size, can't be negative or the maximum representable value")) end throw(ArgumentError("array dimensions too great, can't represent length")) end