Skip to content

Commit

Permalink
add docs, tests
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbyrne committed Oct 7, 2016
1 parent 752ea51 commit 27edb42
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 8 deletions.
8 changes: 4 additions & 4 deletions base/checked.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
module Checked

export checked_neg, checked_abs, checked_add, checked_sub, checked_mul,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld
checked_div, checked_rem, checked_fld, checked_mod, checked_cld,
add_with_overflow, sub_with_overflow, mul_with_overflow

import Core.Intrinsics: box, unbox,
checked_sadd_int, checked_ssub_int, checked_smul_int, checked_sdiv_int,
Expand All @@ -26,7 +27,6 @@ checked_cld(x::Integer, y::Integer) = checked_cld(promote(x,y)...)

# fallback catchall rules to prevent infinite recursion if promotion succeeds,
# but no method exists to handle those types
checked_neg{T<:Integer}(x::T) = no_op_err("checked_neg", T)
checked_abs{T<:Integer}(x::T) = no_op_err("checked_abs", T)

typealias SignedInt Union{Int8,Int16,Int32,Int64,Int128}
Expand Down Expand Up @@ -184,7 +184,7 @@ checked_add{T}(x1::T, x2::T, x3::T, x4::T, x5::T, x6::T, x7::T, x8::T) =


"""
Base.sub_with_overflow(x, y) -> (r,f)
Base.sub_with_overflow(x, y) -> (r, f)
Calculates `r = x-y`, with the flag `f` indicating whether overflow has occurred.
"""
Expand Down Expand Up @@ -223,7 +223,7 @@ end


"""
Base.mul_with_overflow(x, y) -> (r,f)
Base.mul_with_overflow(x, y) -> (r, f)
Calculates `r = x*y`, with the flag `f` indicating whether overflow has occurred.
"""
Expand Down
18 changes: 18 additions & 0 deletions doc/stdlib/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1364,6 +1364,24 @@ Mathematical Functions

The overflow protection may impose a perceptible performance penalty.

.. function:: Base.add_with_overflow(x, y) -> (r, f)

.. Docstring generated from Julia source
Calculates ``r = x+y``\ , with the flag ``f`` indicating whether overflow has occurred.

.. function:: Base.sub_with_overflow(x, y) -> (r, f)

.. Docstring generated from Julia source
Calculates ``r = x-y``\ , with the flag ``f`` indicating whether overflow has occurred.

.. function:: Base.mul_with_overflow(x, y) -> (r, f)

.. Docstring generated from Julia source
Calculates ``r = x*y``\ , with the flag ``f`` indicating whether overflow has occurred.

.. function:: abs2(x)

.. Docstring generated from Julia source
Expand Down
77 changes: 73 additions & 4 deletions test/checked.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# Checked integer arithmetic

import Base: checked_abs, checked_neg, checked_add, checked_sub, checked_mul,
checked_div, checked_rem, checked_fld, checked_mod, checked_cld
checked_div, checked_rem, checked_fld, checked_mod, checked_cld,
add_with_overflow, sub_with_overflow, mul_with_overflow

# checked operations

Expand All @@ -27,7 +28,7 @@ for T in (Int8, Int16, Int32, Int64, Int128)

# corner cases
@test_throws OverflowError checked_abs(typemin(T))
# @test_throws OverflowError checked_neg(typemin(T))
@test_throws OverflowError checked_neg(typemin(T))

# regular cases
for s1 in (-1, +1), s2 in (-1, +1)
Expand Down Expand Up @@ -67,6 +68,23 @@ for T in (Int8, Int16, Int32, Int64, Int128)
@test_throws OverflowError checked_add(halfmax_plus1, halfmax_plus1)
@test_throws OverflowError checked_add(halfmin, halfmin_minus1)

@test add_with_overflow(typemax(T), T(-1)) === (T(typemax(T) - 1), false)
@test add_with_overflow(typemin(T), T(-1)) === (T(typemax(T)), true)
@test add_with_overflow(typemax(T), T(0)) === (typemax(T), false)
@test add_with_overflow(typemin(T), T(0)) === (typemin(T), false)
@test add_with_overflow(typemax(T), T(1)) === (typemin(T), true)
@test add_with_overflow(typemin(T), T(1)) === (T(typemin(T) + 1), false)
@test add_with_overflow(T(-1), typemax(T)) === (T(typemax(T) - 1), false)
@test add_with_overflow(T(-1), typemin(T)) === (typemax(T), true)
@test add_with_overflow(T(0), typemax(T)) === (typemax(T), false)
@test add_with_overflow(T(0), typemin(T)) === (typemin(T), false)
@test add_with_overflow(T(1), typemax(T)) === (typemin(T), true)
@test add_with_overflow(T(1), typemin(T)) === (T(typemin(T) + 1), false)
@test add_with_overflow(typemax(T), typemin(T)) === (T(-1), false)
@test add_with_overflow(typemin(T), typemax(T)) === (T(-1), false)
@test add_with_overflow(halfmax_plus1, halfmax_plus1) === (typemin(T), true)
@test add_with_overflow(halfmin, halfmin_minus1) === (typemax(T), true)

@test_throws OverflowError checked_sub(typemax(T), T(-1))
@test checked_sub(typemax(T), T(0)) === typemax(T)
@test checked_sub(typemax(T), T(1)) === T(typemax(T) - 1)
Expand All @@ -82,6 +100,21 @@ for T in (Int8, Int16, Int32, Int64, Int128)
@test checked_sub(halfmax, T(-halfmin)) === T(-1)
@test_throws OverflowError checked_sub(halfmin, T(-halfmin_minus1))

@test sub_with_overflow(typemax(T), T(-1)) === (typemin(T), true)
@test sub_with_overflow(typemax(T), T(0)) === (typemax(T), false)
@test sub_with_overflow(typemax(T), T(1)) === (T(typemax(T) - 1), false)
@test sub_with_overflow(typemin(T), T(-1)) === (T(typemin(T) + 1), false)
@test sub_with_overflow(typemin(T), T(0)) === (typemin(T), false)
@test sub_with_overflow(typemin(T), T(1)) === (typemax(T), true)
@test sub_with_overflow(T(0), typemax(T)) === (T(typemin(T) + 1), false)
@test sub_with_overflow(T(1), typemax(T)) === (T(typemin(T) + 2), false)
@test sub_with_overflow(T(-1), typemin(T)) === (typemax(T), false)
@test sub_with_overflow(T(0), typemin(T)) === (typemin(T), true)
@test sub_with_overflow(typemax(T), typemax(T)) === (T(0), false)
@test sub_with_overflow(typemin(T), typemin(T)) === (T(0), false)
@test sub_with_overflow(halfmax, T(-halfmin)) === (T(-1), false)
@test sub_with_overflow(halfmin, T(-halfmin_minus1)) === (typemax(T), true)

@test checked_mul(typemax(T), T(0)) === T(0)
@test checked_mul(typemin(T), T(0)) === T(0)
@test checked_mul(typemax(T), T(1)) === typemax(T)
Expand All @@ -93,6 +126,17 @@ for T in (Int8, Int16, Int32, Int64, Int128)
@test_throws OverflowError checked_mul(-sqrtmax, half_sqrtmax_plus1)
@test_throws OverflowError checked_mul(-sqrtmax, -half_sqrtmax)

@test mul_with_overflow(typemax(T), T(0)) === (T(0), false)
@test mul_with_overflow(typemin(T), T(0)) === (T(0), false)
@test mul_with_overflow(typemax(T), T(1)) === (typemax(T), false)
@test mul_with_overflow(typemin(T), T(1)) === (typemin(T), false)
@test mul_with_overflow(sqrtmax, half_sqrtmax) === (typemin(T), true)
@test mul_with_overflow(sqrtmax, -half_sqrtmax) === (T(sqrtmax * -half_sqrtmax), false)
@test mul_with_overflow(sqrtmax, -half_sqrtmax_plus1) === (T(sqrtmax * -half_sqrtmax_plus1), true)
@test mul_with_overflow(-sqrtmax, half_sqrtmax) === (T(-sqrtmax * half_sqrtmax), false)
@test mul_with_overflow(-sqrtmax, half_sqrtmax_plus1) === (T(-sqrtmax * half_sqrtmax_plus1), true)
@test mul_with_overflow(-sqrtmax, -half_sqrtmax) === (T(-sqrtmax * -half_sqrtmax), true)

@test checked_div(typemax(T), T(1)) === typemax(T)
@test_throws DivideError checked_div(typemax(T), T(0))
@test checked_div(typemax(T), T(-1)) === T(-typemax(T))
Expand Down Expand Up @@ -158,6 +202,18 @@ for T in (UInt8, UInt16, UInt32, UInt64, UInt128)
@test checked_add(T(0), typemax(T)) === typemax(T)
@test_throws OverflowError checked_add(halfmax_plus1, halfmax_plus1)

@test add_with_overflow(typemax(T), T(0)) === (typemax(T), false)
@test add_with_overflow(T(0), T(0)) === (T(0), false)
@test add_with_overflow(typemax(T), T(1)) === (T(0), true)
@test add_with_overflow(T(0), T(1)) === (T(T(0) + 1), false)
@test add_with_overflow(T(0), typemax(T)) === (typemax(T), false)
@test add_with_overflow(T(0), T(0)) === (T(0), false)
@test add_with_overflow(T(1), typemax(T)) === (T(0), true)
@test add_with_overflow(T(1), T(0)) === (T(T(0) + 1), false)
@test add_with_overflow(typemax(T), T(0)) === (typemax(T), false)
@test add_with_overflow(T(0), typemax(T)) === (typemax(T), false)
@test add_with_overflow(halfmax_plus1, halfmax_plus1) === (T(0), true)

@test checked_sub(typemax(T), T(0)) === typemax(T)
@test checked_sub(typemax(T), T(1)) === T(typemax(T) - 1)
@test checked_sub(T(0), T(0)) === T(0)
Expand All @@ -167,12 +223,27 @@ for T in (UInt8, UInt16, UInt32, UInt64, UInt128)
@test checked_sub(T(0), T(0)) === T(0)
@test checked_sub(typemax(T), typemax(T)) === T(0)

@test sub_with_overflow(typemax(T), T(0)) === (typemax(T), false)
@test sub_with_overflow(typemax(T), T(1)) === (T(typemax(T) - 1), false)
@test sub_with_overflow(T(0), T(0)) === (T(0), false)
@test sub_with_overflow(T(0), T(1)) === (typemax(T), true)
@test sub_with_overflow(T(0), typemax(T)) === (T(1), true)
@test sub_with_overflow(T(1), typemax(T)) === (T(2), true)
@test sub_with_overflow(T(0), T(0)) === (T(0), false)
@test sub_with_overflow(typemax(T), typemax(T)) === (T(0), false)

@test checked_mul(typemax(T), T(0)) === T(0)
@test checked_mul(T(0), T(0)) === T(0)
@test checked_mul(typemax(T), T(1)) === typemax(T)
@test checked_mul(T(0), T(1)) === T(0)
@test_throws OverflowError checked_mul(sqrtmax, sqrtmax)

@test mul_with_overflow(typemax(T), T(0)) === (T(0), false)
@test mul_with_overflow(T(0), T(0)) === (T(0), false)
@test mul_with_overflow(typemax(T), T(1)) === (typemax(T), false)
@test mul_with_overflow(T(0), T(1)) === (T(0), false)
@test mul_with_overflow(sqrtmax, sqrtmax) === (T(0), true)

@test checked_div(typemax(T), T(1)) === typemax(T)
@test_throws DivideError checked_div(typemax(T), T(0))
@test checked_rem(typemax(T), T(1)) === T(0)
Expand All @@ -188,8 +259,6 @@ end
# Boolean
@test checked_add(false) === 0
@test checked_add(true) === 1
# @test checked_sub(false) === 0
# @test checked_sub(true) === -1
@test checked_neg(false) === 0
@test checked_neg(true) === -1
@test checked_abs(true) === true
Expand Down

0 comments on commit 27edb42

Please sign in to comment.