Skip to content

Commit f468e6c

Browse files
authored
Add saturating array methods, which was overlooked by #7 (#15)
* Add saturating array methods and broadcast tests * Bonus - add saturating test for SaferIntegers
1 parent 068b66b commit f468e6c

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

src/abstractarraymath_ext.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ checked_mul(A::AbstractArray, B::AbstractArray) = error("Checked matrix multipli
1919

2020
checked_pow(A::AbstractArray, B::Number) = error("Checked matrix multiplication is not available")
2121

22+
saturating_neg(A::AbstractArray) = broadcast_preserving_zero_d(saturating_neg, A)
23+
for f in (:saturating_add, :saturating_sub)
24+
@eval function ($f)(A::AbstractArray, B::AbstractArray)
25+
promote_shape(A, B) # check size compatibility
26+
broadcast_preserving_zero_d($f, A, B)
27+
end
28+
end
29+
saturating_mul(A::Number, B::AbstractArray) = broadcast_preserving_zero_d(saturating_mul, B, A)
30+
saturating_mul(A::AbstractArray, B::Number) = broadcast_preserving_zero_d(saturating_mul, A, B)
31+
saturating_mul(A::AbstractArray, B::AbstractArray) = error("Saturating matrix multiplication is not available")
32+
33+
saturating_pow(A::AbstractArray, B::Number) = error("Saturating matrix multiplication is not available")
34+
2235
# Compatibility with Julia 1.0 and 1.1
2336
if VERSION < v"1.2"
2437
if VERSION < v"1.1"

test/runtests.jl

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -413,68 +413,105 @@ using SaferIntegers
413413

414414
@testset "Ensure SaferIntegers are still safer" begin
415415
@test_throws OverflowError typemax(SafeInt) + 1
416+
416417
@test_throws OverflowError @unchecked typemax(SafeInt) + 1
418+
@test_throws OverflowError @saturating typemax(SafeInt) + 1
419+
417420
(@__MODULE__).eval(:(
418421
module UncheckedDefaultSaferIntStillChecksModule
419422
using OverflowContexts, SaferIntegers, Test
420423
@default_unchecked
421424
@test_throws OverflowError typemax(SafeInt) + 1
422425
end))
426+
(@__MODULE__).eval(:(
427+
module SaturatingDefaultSaferIntStillChecksModule
428+
using OverflowContexts, SaferIntegers, Test
429+
@default_saturating
430+
@test_throws OverflowError typemax(SafeInt) + 1
431+
end))
423432
end
424433

425434
@testset "Broadcasted operators replaced" begin
426435
aa = fill(typemax(Int), 2)
427436
bb = fill(2, 2)
428437
cc = fill(typemin(Int), 2)
429-
@unchecked(.+cc) == cc
430-
@unchecked(.-cc) == cc
438+
431439
@checked(.+cc) == cc
432440
@test_throws OverflowError @checked(.-cc)
433-
@unchecked(aa .+ bb) == fill(typemin(Int) + 1, 2)
434441
@test_throws OverflowError @checked aa .+ bb
435-
@unchecked(cc .- bb) == fill(typemax(Int) - 1, 2)
436442
@test_throws OverflowError @checked cc .- bb
437-
@unchecked(aa .* bb) == fill(-2, 2)
438443
@test_throws OverflowError @checked aa .* bb
439-
@unchecked(aa .^ bb) == fill(1, 2)
440444
@test_throws OverflowError @checked aa .^ bb
441-
@unchecked(abs.(cc)) == cc
442445
@test_throws OverflowError @checked abs.(cc)
446+
447+
@unchecked(.+cc) == cc
448+
@unchecked(.-cc) == cc
449+
@unchecked(aa .+ bb) == fill(typemin(Int) + 1, 2)
450+
@unchecked(cc .- bb) == fill(typemax(Int) - 1, 2)
451+
@unchecked(aa .* bb) == fill(-2, 2)
452+
@unchecked(aa .^ bb) == fill(1, 2)
453+
@unchecked(abs.(cc)) == cc
454+
455+
@saturating(.+cc) == cc
456+
@saturating(.-cc) == aa
457+
@saturating(aa .+ bb) == aa
458+
@saturating(cc .- bb) == cc
459+
@saturating(aa .* bb) == aa
460+
@saturating(aa .^ bb) == aa
461+
@saturating(abs.(cc)) == aa
443462
end
444463

445464
@testset "Broadcasted assignment operators replaced" begin
446465
aa = fill(typemax(Int), 2)
447466
bb = fill(2, 2)
448467
cc = fill(typemin(Int), 2)
449-
@unchecked(copy(aa) .+= bb) == fill(typemin(Int) + 1, 2)
468+
450469
@test_throws OverflowError @checked aa .+ bb
451-
@unchecked(copy(cc) .-= bb) == fill(typemax(Int) - 1, 2)
470+
@test_throws OverflowError @checked aa .^ bb
452471
@test_throws OverflowError @checked cc .- bb
453-
@unchecked(copy(aa) .* bb) == fill(-2, 2)
454472
@test_throws OverflowError @checked aa .* bb
473+
474+
@unchecked(copy(aa) .+= bb) == fill(typemin(Int) + 1, 2)
475+
@unchecked(copy(cc) .-= bb) == fill(typemax(Int) - 1, 2)
476+
@unchecked(copy(aa) .* bb) == fill(-2, 2)
455477
@unchecked(copy(aa) .^ bb) == fill(1, 2)
456-
@test_throws OverflowError @checked aa .^ bb
478+
479+
@saturating(copy(aa) .+= bb) == aa
480+
@saturating(copy(cc) .-= bb) == cc
481+
@saturating(copy(aa) .* bb) == aa
482+
@saturating(copy(aa) .^ bb) == aa
457483
end
458484

459485
@testset "Elementwise array methods are replaced, and others throw" begin
460486
aa = fill(typemax(Int), 2)
461487
bb = fill(2, 2)
462488
cc = fill(typemin(Int), 2)
463489
dd = fill(typemax(Int), 2, 2)
464-
@unchecked(+cc) == cc
465-
@unchecked(-cc) == cc
490+
466491
@checked(+cc) == cc
467492
@test_throws OverflowError @checked(-cc)
468-
@unchecked(aa + bb) == fill(typemin(Int) + 1, 2)
469493
@test_throws OverflowError @checked aa + bb
470-
@unchecked(cc - bb) == fill(typemax(Int) - 1, 2)
471494
@test_throws OverflowError @checked cc - bb
472-
@unchecked(2aa) == fill(-2, 2)
473495
@test_throws OverflowError @checked 2aa
474-
@unchecked(aa * 2) == fill(-2, 2)
475496
@test_throws OverflowError @checked aa * 2
476-
@unchecked(aa * bb') == fill(-2, 2, 2)
477497
@test_throws ErrorException @checked aa * bb'
478-
@unchecked(dd ^ 2) == fill(2, 2, 2)
479498
@test_throws ErrorException @checked dd ^ 2
499+
500+
@unchecked(+cc) == cc
501+
@unchecked(-cc) == cc
502+
@unchecked(aa + bb) == fill(typemin(Int) + 1, 2)
503+
@unchecked(cc - bb) == fill(typemax(Int) - 1, 2)
504+
@unchecked(2aa) == fill(-2, 2)
505+
@unchecked(aa * 2) == fill(-2, 2)
506+
@unchecked(aa * bb') == fill(-2, 2, 2)
507+
@unchecked(dd ^ 2) == fill(2, 2, 2)
508+
509+
@saturating(+cc) == cc
510+
@saturating(-cc) == aa
511+
@saturating(aa + bb) == aa
512+
@saturating(cc - bb) == cc
513+
@saturating(2aa) == aa
514+
@saturating(aa * 2) == aa
515+
@test_throws ErrorException @saturating aa * bb'
516+
@test_throws ErrorException @saturating dd ^ 2
480517
end

0 commit comments

Comments
 (0)