fyi SafeInt32 is type stable, as are all the SaferInteger types
julia> using SaferIntegers
julia> safe32 = SafeInt32(31); safe32 += 1; safe32, typeof(safe32)
(32, SafeInt32)
fyi SafeInt32 is type stable, as are all the SaferInteger types
julia> using SaferIntegers
julia> safe32 = SafeInt32(31); safe32 += 1; safe32, typeof(safe32)
(32, SafeInt32)
or just 10.0^N
If you mean to check arithmetic operations syntactically present in user’s code, I guess it can be done already with a module exporting checked version of these operations? You can put using CheckedArithmetics
(say) in the beginning of the module (maybe with if ENV["CHECK_ARITHMETICS"] == "true" ... end
so that it’s easier to turn on/off). I used the same trick to change the associativity of *
.
That’s probably not an unreasonable comment. Maybe that adding a note about integer overflow to common Julia 101 tutorials would be useful. I’ve just made a PR to learn x in y minutes for this.
As a couple tests, first a dead-simple function to vectorize (dot product):
julia> using SaferIntegers, BenchmarkTools
julia> function my_dot(x, y)
out = zero(promote_type(eltype(x), eltype(y)))
@inbounds @simd ivdep for i in eachindex(x, y)
out += x[i] * y[i]
end
out
end
my_dot (generic function with 1 method)
julia> function my_dot_safeint(x, y)
out = zero(promote_type(eltype(x), eltype(y)))
N = SafeInt64(min(length(x),length(y)))
@inbounds @simd ivdep for i in 1:N
out += x[i] * y[i]
end
out
end
my_dot_safeint (generic function with 1 method)
julia> x = rand(Float32, 512);
julia> y = rand(Float32, 512);
julia> @btime $x' * $y
24.058 ns (0 allocations: 0 bytes)
125.47223f0
julia> @btime my_dot($x, $y)
13.664 ns (0 allocations: 0 bytes)
125.47223f0
julia> @btime my_dot_safeint($x, $y)
14.930 ns (0 allocations: 0 bytes)
125.47223f0
And the compiler can still vectorize.
Make things just a little more complicated:
julia> using SLEEF #I am currently on the SIMDPirates branch
julia> function my_exp!(x, y)
@inbounds for i in eachindex(x, y)
x[i] = SLEEF.exp(y[i])
end
end
my_exp! (generic function with 1 method)
julia> function my_exp_safeint!(x, y)
N = SafeInt64(min(length(x),length(y)))
@inbounds for i in 1:N
x[i] = SLEEF.exp(y[i])
end
end
my_exp_safeint! (generic function with 1 method)
julia> @btime my_exp!($x, $y)
146.227 ns (0 allocations: 0 bytes)
julia> all(x .≈ exp.(y))
true
julia> @btime my_exp_safeint!($x, $y)
1.953 μs (0 allocations: 0 bytes)
julia> all(x .≈ exp.(y))
true
julia> 1.953 / 146.227 * 1e3
13.355946576213695
and it does not, and we see an > 13-fold regression.
The computer I tested on has avx512, which means 16 Float32 per SIMD unit.
Did you file an issue? Please link it!