From e1690fce86701d24614cc999ec49c34f5531f698 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Thu, 18 Sep 2014 18:45:23 -0400 Subject: [PATCH] check signed<->unsigned conversions this would be a bit cleaner without the code in intfuncs that dispatches on Unsigned. signed() and unsigned() are convenient for testing bit patterns in the test suite. for now replace with assigned() and asunsigned(). uint8(x) is convenient for moving bytes around, so it remains unchecked. we should perhaps rename this to byte(), and either eliminate uint8() entirely, or make it checked. --- base/boot.jl | 2 +- base/dict.jl | 2 +- base/int.jl | 19 +++++--- base/intfuncs.jl | 18 ++++---- base/number.jl | 4 +- src/intrinsics.cpp | 13 +++++- test/core.jl | 18 ++++---- test/numbers.jl | 112 +++++++++++++++++++++++---------------------- 8 files changed, 104 insertions(+), 84 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index d054fad583e06..e34d15354e379 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -151,7 +151,7 @@ export #ccall, cglobal, llvmcall, abs_float, add_float, add_int, and_int, ashr_int, #box, bswap_int, checked_fptosi, checked_fptoui, checked_sadd, #checked_smul, checked_ssub, checked_uadd, checked_umul, checked_usub, - #checked_trunc_sint, checked_trunc_uint, + #checked_trunc_sint, checked_trunc_uint, check_top_bit, #nan_dom_err, copysign_float, ctlz_int, ctpop_int, cttz_int, #div_float, eq_float, eq_int, eqfsi64, eqfui64, flipsign_int, select_value, #sqrt_llvm, powi_llvm, diff --git a/base/dict.jl b/base/dict.jl index 44008c39f6962..5381a97770d6c 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -288,7 +288,7 @@ end empty!(t::ObjectIdDict) = (t.ht = cell(length(t.ht)); t) -_oidd_nextind(a, i) = int(ccall(:jl_eqtable_nextind, Csize_t, (Any, Csize_t), a, i)) +_oidd_nextind(a, i) = reinterpret(Int,ccall(:jl_eqtable_nextind, Csize_t, (Any, Csize_t), a, i)) start(t::ObjectIdDict) = _oidd_nextind(t.ht, 0) done(t::ObjectIdDict, i) = (i == -1) diff --git a/base/int.jl b/base/int.jl index 69cb22a4f875c..85760b852cd2d 100644 --- a/base/int.jl +++ b/base/int.jl @@ -43,17 +43,17 @@ abs(x::Signed) = flipsign(x,x) ~(n::Integer) = -n-1 -div(x::Signed, y::Unsigned) = flipsign(signed(div(unsigned(abs(x)),y)),x) -div(x::Unsigned, y::Signed) = unsigned(flipsign(signed(div(x,unsigned(abs(y)))),y)) +div(x::Signed, y::Unsigned) = flipsign(assigned(div(asunsigned(abs(x)),y)),x) +div(x::Unsigned, y::Signed) = asunsigned(flipsign(assigned(div(x,asunsigned(abs(y)))),y)) -rem(x::Signed, y::Unsigned) = flipsign(signed(rem(unsigned(abs(x)),y)),x) -rem(x::Unsigned, y::Signed) = rem(x,unsigned(abs(y))) +rem(x::Signed, y::Unsigned) = flipsign(assigned(rem(asunsigned(abs(x)),y)),x) +rem(x::Unsigned, y::Signed) = rem(x,asunsigned(abs(y))) fld(x::Signed, y::Unsigned) = div(x,y)-(signbit(x)&(rem(x,y)!=0)) fld(x::Unsigned, y::Signed) = div(x,y)-(signbit(y)&(rem(x,y)!=0)) -mod(x::Signed, y::Unsigned) = rem(y+unsigned(rem(x,y)),y) -mod(x::Unsigned, y::Signed) = rem(y+signed(rem(x,y)),y) +mod(x::Signed, y::Unsigned) = rem(y+asunsigned(rem(x,y)),y) +mod(x::Unsigned, y::Signed) = rem(y+assigned(rem(x,y)),y) cld(x::Signed, y::Unsigned) = div(x,y)+(!signbit(x)&(rem(x,y)!=0)) cld(x::Unsigned, y::Signed) = div(x,y)+(!signbit(y)&(rem(x,y)!=0)) @@ -133,6 +133,7 @@ for T in IntTypes end asunsigned(x) = reinterpret(typeof(unsigned(zero(x))), x) +assigned(x) = reinterpret(typeof(signed(zero(x))), x) ==(x::Signed, y::Unsigned) = (x >= 0) & (asunsigned(x) == y) ==(x::Unsigned, y::Signed ) = (y >= 0) & (x == asunsigned(y)) @@ -158,6 +159,9 @@ for to in tuple(IntTypes...,Char), from in tuple(IntTypes...,Char,Bool) else @eval convert(::Type{$to}, x::($from)) = box($to,zext_int($to,unbox($from,x))) end + elseif !(issubtype(from,Signed) === issubtype(to,Signed)) + # raise InexactError if x's top bit is set + @eval convert(::Type{$to}, x::($from)) = box($to,check_top_bit(unbox($from,x))) else @eval convert(::Type{$to}, x::($from)) = box($to,unbox($from,x)) end @@ -223,7 +227,8 @@ int32(x) = convert(Int32,x) int64(x) = convert(Int64,x) int128(x) = convert(Int128,x) -uint8(x) = convert(Uint8,x) +uint8(x) = itrunc(Uint8,x) +uint8(x::Int8) = box(Uint8,unbox(Int8,x)) uint16(x) = convert(Uint16,x) uint32(x) = convert(Uint32,x) uint64(x) = convert(Uint64,x) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 077b363eed90b..37592d98fecec 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -109,10 +109,10 @@ end # smallest power of 2 >= x nextpow2(x::Unsigned) = one(x)<<((sizeof(x)<<3)-leading_zeros(x-1)) -nextpow2(x::Integer) = oftype(x,x < 0 ? -nextpow2(unsigned(-x)) : nextpow2(unsigned(x))) +nextpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -nextpow2(unsigned(-x)) : nextpow2(unsigned(x))) prevpow2(x::Unsigned) = (one(x)>>(x==0)) << ((sizeof(x)<<3)-leading_zeros(x)-1) -prevpow2(x::Integer) = oftype(x,x < 0 ? -prevpow2(unsigned(-x)) : prevpow2(unsigned(x))) +prevpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -prevpow2(unsigned(-x)) : prevpow2(unsigned(x))) ispow2(x::Integer) = count_ones(x)==1 @@ -154,7 +154,7 @@ function ndigits0z(x::Uint128) end return n + ndigits0z(uint64(x)) end -ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x))) +ndigits0z(x::Integer) = ndigits0z(asunsigned(abs(x))) const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000 @@ -175,13 +175,13 @@ function ndigits0z(n::Unsigned, b::Int) end return d end -ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b)) +ndigits0z(x::Integer, b::Integer) = ndigits0z(asunsigned(abs(x)),int(b)) ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b)) ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x) -ndigits(x::Integer, b::Integer) = ndigits(unsigned(abs(x)),int(b)) -ndigits(x::Integer) = ndigits(unsigned(abs(x))) +ndigits(x::Integer, b::Integer) = ndigits(asunsigned(abs(x)),int(b)) +ndigits(x::Integer) = ndigits(asunsigned(abs(x))) ## integer to string functions ## @@ -252,7 +252,7 @@ function base(b::Int, x::Unsigned, pad::Int, neg::Bool) if neg; a[1]='-'; end ASCIIString(a) end -base(b::Integer, n::Integer, pad::Integer=1) = base(int(b), unsigned(abs(n)), pad, n<0) +base(b::Integer, n::Integer, pad::Integer=1) = base(int(b), asunsigned(abs(n)), pad, n<0) for sym in (:bin, :oct, :dec, :hex) @eval begin @@ -260,8 +260,8 @@ for sym in (:bin, :oct, :dec, :hex) ($sym)(x::Unsigned) = ($sym)(x,1,false) ($sym)(x::Char, p::Int) = ($sym)(unsigned(x),p,false) ($sym)(x::Char) = ($sym)(unsigned(x),1,false) - ($sym)(x::Integer, p::Int) = ($sym)(unsigned(abs(x)),p,x<0) - ($sym)(x::Integer) = ($sym)(unsigned(abs(x)),1,x<0) + ($sym)(x::Integer, p::Int) = ($sym)(asunsigned(abs(x)),p,x<0) + ($sym)(x::Integer) = ($sym)(asunsigned(abs(x)),1,x<0) end end diff --git a/base/number.jl b/base/number.jl index a0b641346e040..350418e75da18 100644 --- a/base/number.jl +++ b/base/number.jl @@ -39,11 +39,11 @@ done(x::Number, state) = state isempty(x::Number) = false in(x::Number, y::Number) = x == y -function reinterpret{T}(::Type{T}, x) +function reinterpret{T,S}(::Type{T}, x::S) if !isbits(T) error("cannot reinterpret to type ", T) end - box(T,x) + box(T,unbox(S,x)) end map(f::Callable, x::Number) = f(x) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 1a6a4518adf01..8f0b0b22b25c9 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -28,7 +28,7 @@ namespace JL_I { fptrunc, fpext, // checked conversion fpsiround, fpuiround, checked_fptosi, checked_fptoui, - checked_trunc_sint, checked_trunc_uint, + checked_trunc_sint, checked_trunc_uint, check_top_bit, // checked arithmetic checked_sadd, checked_uadd, checked_ssub, checked_usub, checked_smul, checked_umul, @@ -1089,6 +1089,16 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs, return builder.CreateExtractValue(res, ArrayRef(0)); } + HANDLE(check_top_bit,1) + // raise InexactError if argument's top bit is set + x = JL_INT(x); + raise_exception_if(builder. + CreateTrunc(builder. + CreateLShr(x, ConstantInt::get(t, t->getPrimitiveSizeInBits()-1)), + T_int1), + prepare_global(jlinexacterr_var), ctx); + return x; + HANDLE(eq_int,2) return builder.CreateICmpEQ(JL_INT(x), JL_INT(y)); HANDLE(ne_int,2) return builder.CreateICmpNE(JL_INT(x), JL_INT(y)); HANDLE(slt_int,2) return builder.CreateICmpSLT(JL_INT(x), JL_INT(y)); @@ -1503,6 +1513,7 @@ extern "C" void jl_init_intrinsic_functions(void) ADD_I(checked_fptosi); ADD_I(checked_fptoui); ADD_I(checked_trunc_sint); ADD_I(checked_trunc_uint); + ADD_I(check_top_bit); ADD_I(nan_dom_err); ADD_I(ccall); ADD_I(cglobal); ADD_I(jl_alloca); diff --git a/test/core.jl b/test/core.jl index cc5c712be1f31..d545b222be4d5 100644 --- a/test/core.jl +++ b/test/core.jl @@ -243,31 +243,31 @@ end # conversions function fooo() local x::Int8 - x = 1000 + x = 100 x end -@test int32(fooo()) == -24 +@test fooo() === convert(Int8,100) function fooo_2() local x::Int8 - x = 1000 + x = 100 end -@test fooo_2() == 1000 +@test fooo_2() === 100 function fooo_3() local x::Int8 - y = x = 1000 - @test x == -24 + y = x = 100 + @test isa(x,Int8) y end -@test fooo_3() == 1000 +@test fooo_3() === 100 function foo() local x::Int8 function bar() - x = 1000 + x = 100 end bar() x end -@test int32(foo()) == -24 +@test foo() === convert(Int8,100) function bar{T}(x::T) local z::Complex{T} diff --git a/test/numbers.jl b/test/numbers.jl index 0c6473cd3a747..5d3620fd7d8b2 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -802,15 +802,15 @@ end for T in {Int8,Int16,Int32,Int64,Int128} @test abs(typemin(T)) == -typemin(T) - for x in {typemin(T),convert(T,-1),zero(T),one(T),typemax(T)} - @test signed(unsigned(x)) == x - end + #for x in {typemin(T),convert(T,-1),zero(T),one(T),typemax(T)} + # @test signed(unsigned(x)) == x + #end end -for T in {Uint8,Uint16,Uint32,Uint64,Uint128}, - x in {typemin(T),one(T),typemax(T)} - @test unsigned(signed(x)) == x -end +#for T in {Uint8,Uint16,Uint32,Uint64,Uint128}, +# x in {typemin(T),one(T),typemax(T)} +# @test unsigned(signed(x)) == x +#end for S = {Int8, Int16, Int32, Int64}, U = {Uint8, Uint16, Uint32, Uint64} @@ -1133,19 +1133,21 @@ end @test cld(typemin(Int64)+3,-2) == 4611686018427387903 @test cld(typemin(Int64)+3,-7) == 1317624576693539401 +import Base.asunsigned + for x={typemin(Int64), -typemax(Int64), -typemax(Int64)+1, -typemax(Int64)+2, typemax(Int64)-2, typemax(Int64)-1, typemax(Int64), typemax(Uint64)-1, typemax(Uint64)-2, typemax(Uint64)}, y={-7,-2,-1,1,2,7} if x >= 0 - @test div(unsigned(x),y) == unsigned(div(x,y)) - @test fld(unsigned(x),y) == unsigned(fld(x,y)) - @test cld(unsigned(x),y) == unsigned(cld(x,y)) + @test div(asunsigned(x),y) == asunsigned(div(x,y)) + @test fld(asunsigned(x),y) == asunsigned(fld(x,y)) + @test cld(asunsigned(x),y) == asunsigned(cld(x,y)) end if isa(x,Signed) && y >= 0 - @test div(x,unsigned(y)) == div(x,y) - @test fld(x,unsigned(y)) == fld(x,y) - @test cld(x,unsigned(y)) == cld(x,y) + @test div(x,asunsigned(y)) == div(x,y) + @test fld(x,asunsigned(y)) == fld(x,y) + @test cld(x,asunsigned(y)) == cld(x,y) end end @@ -1153,19 +1155,19 @@ for x=0:5, y=1:5 @test div(uint(x),uint(y)) == div(x,y) @test div(uint(x),y) == div(x,y) @test div(x,uint(y)) == div(x,y) - @test div(uint(x),-y) == uint(div(x,-y)) + @test div(uint(x),-y) == reinterpret(Uint,div(x,-y)) @test div(-x,uint(y)) == div(-x,y) @test fld(uint(x),uint(y)) == fld(x,y) @test fld(uint(x),y) == fld(x,y) @test fld(x,uint(y)) == fld(x,y) - @test fld(uint(x),-y) == uint(fld(x,-y)) + @test fld(uint(x),-y) == reinterpret(Uint,fld(x,-y)) @test fld(-x,uint(y)) == fld(-x,y) @test cld(uint(x),uint(y)) == cld(x,y) @test cld(uint(x),y) == cld(x,y) @test cld(x,uint(y)) == cld(x,y) - @test cld(uint(x),-y) == uint(cld(x,-y)) + @test cld(uint(x),-y) == reinterpret(Uint,cld(x,-y)) @test cld(-x,uint(y)) == cld(-x,y) @test rem(uint(x),uint(y)) == rem(x,y) @@ -1188,20 +1190,22 @@ end @test div(typemax(Uint64)-2, 1) == typemax(Uint64)-2 @test div(typemax(Uint64)-2,-1) == -typemax(Uint64)+2 -@test signed(div(unsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 -@test signed(div(unsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 -@test signed(div(unsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 -@test signed(div(unsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 -@test signed(div(unsigned(typemax(Int64)) , 1)) == typemax(Int64) -@test signed(div(unsigned(typemax(Int64)) ,-1)) == -typemax(Int64) - -@test signed(div(typemax(Uint),typemax(Int))) == 2 -@test signed(div(typemax(Uint),(typemax(Int)>>1)+1)) == 3 -@test signed(div(typemax(Uint),typemax(Int)>>1)) == 4 -@test signed(div(typemax(Uint),typemin(Int))) == -1 -@test signed(div(typemax(Uint),typemin(Int)+1)) == -2 -@test signed(div(typemax(Uint),typemin(Int)>>1)) == -3 -@test signed(div(typemax(Uint),(typemin(Int)>>1)+1)) == -4 +using Base.assigned + +@test assigned(div(asunsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 +@test assigned(div(asunsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 +@test assigned(div(asunsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 +@test assigned(div(asunsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 +@test assigned(div(asunsigned(typemax(Int64)) , 1)) == typemax(Int64) +@test assigned(div(asunsigned(typemax(Int64)) ,-1)) == -typemax(Int64) + +@test assigned(div(typemax(Uint),typemax(Int))) == 2 +@test assigned(div(typemax(Uint),(typemax(Int)>>1)+1)) == 3 +@test assigned(div(typemax(Uint),typemax(Int)>>1)) == 4 +@test assigned(div(typemax(Uint),typemin(Int))) == -1 +@test assigned(div(typemax(Uint),typemin(Int)+1)) == -2 +@test assigned(div(typemax(Uint),typemin(Int)>>1)) == -3 +@test assigned(div(typemax(Uint),(typemin(Int)>>1)+1)) == -4 @test fld(typemax(Uint64) , 1) == typemax(Uint64) @test fld(typemax(Uint64) ,-1) == -typemax(Uint64) @@ -1210,20 +1214,20 @@ end @test fld(typemax(Uint64)-2, 1) == typemax(Uint64)-2 @test fld(typemax(Uint64)-2,-1) == -typemax(Uint64)+2 -@test signed(fld(unsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 -@test signed(fld(unsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 -@test signed(fld(unsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 -@test signed(fld(unsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 -@test signed(fld(unsigned(typemax(Int64)) , 1)) == typemax(Int64) -@test signed(fld(unsigned(typemax(Int64)) ,-1)) == -typemax(Int64) - -@test signed(fld(typemax(Uint),typemax(Int))) == 2 -@test signed(fld(typemax(Uint),(typemax(Int)>>1)+1)) == 3 -@test signed(fld(typemax(Uint),typemax(Int)>>1)) == 4 -@test signed(fld(typemax(Uint),typemin(Int))) == -2 -@test signed(fld(typemax(Uint),typemin(Int)+1)) == -3 -@test signed(fld(typemax(Uint),typemin(Int)>>1)) == -4 -@test signed(fld(typemax(Uint),(typemin(Int)>>1)+1)) == -5 +@test assigned(fld(asunsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 +@test assigned(fld(asunsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 +@test assigned(fld(asunsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 +@test assigned(fld(asunsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 +@test assigned(fld(asunsigned(typemax(Int64)) , 1)) == typemax(Int64) +@test assigned(fld(asunsigned(typemax(Int64)) ,-1)) == -typemax(Int64) + +@test assigned(fld(typemax(Uint),typemax(Int))) == 2 +@test assigned(fld(typemax(Uint),(typemax(Int)>>1)+1)) == 3 +@test assigned(fld(typemax(Uint),typemax(Int)>>1)) == 4 +@test assigned(fld(typemax(Uint),typemin(Int))) == -2 +@test assigned(fld(typemax(Uint),typemin(Int)+1)) == -3 +@test assigned(fld(typemax(Uint),typemin(Int)>>1)) == -4 +@test assigned(fld(typemax(Uint),(typemin(Int)>>1)+1)) == -5 @test cld(typemax(Uint64) , 1) == typemax(Uint64) @test cld(typemax(Uint64) ,-1) == -typemax(Uint64) @@ -1232,20 +1236,20 @@ end @test cld(typemax(Uint64)-2, 1) == typemax(Uint64)-2 @test cld(typemax(Uint64)-2,-1) == -typemax(Uint64)+2 -@test signed(cld(unsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 -@test signed(cld(unsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 -@test signed(cld(unsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 -@test signed(cld(unsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 -@test signed(cld(unsigned(typemax(Int64)) , 1)) == typemax(Int64) -@test signed(cld(unsigned(typemax(Int64)) ,-1)) == -typemax(Int64) +@test assigned(cld(asunsigned(typemax(Int64))+2, 1)) == typemax(Int64)+2 +@test assigned(cld(asunsigned(typemax(Int64))+2,-1)) == -typemax(Int64)-2 +@test assigned(cld(asunsigned(typemax(Int64))+1, 1)) == typemax(Int64)+1 +@test assigned(cld(asunsigned(typemax(Int64))+1,-1)) == -typemax(Int64)-1 +@test assigned(cld(asunsigned(typemax(Int64)) , 1)) == typemax(Int64) +@test assigned(cld(asunsigned(typemax(Int64)) ,-1)) == -typemax(Int64) @test signed(cld(typemax(Uint),typemax(Int))) == 3 @test signed(cld(typemax(Uint),(typemax(Int)>>1)+1)) == 4 @test signed(cld(typemax(Uint),typemax(Int)>>1)) == 5 -@test signed(cld(typemax(Uint),typemin(Int))) == -1 -@test signed(cld(typemax(Uint),typemin(Int)+1)) == -2 -@test signed(cld(typemax(Uint),typemin(Int)>>1)) == -3 -@test signed(cld(typemax(Uint),(typemin(Int)>>1)+1)) == -4 +@test assigned(cld(typemax(Uint),typemin(Int))) == -1 +@test assigned(cld(typemax(Uint),typemin(Int)+1)) == -2 +@test assigned(cld(typemax(Uint),typemin(Int)>>1)) == -3 +@test assigned(cld(typemax(Uint),(typemin(Int)>>1)+1)) == -4 # issue #4156 @test fld(1.4,0.35667494393873234) == 3.0