Skip to content

Commit

Permalink
check signed<->unsigned conversions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JeffBezanson committed Sep 18, 2014
1 parent 8495944 commit e1690fc
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 84 deletions.
2 changes: 1 addition & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion base/dict.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 12 additions & 7 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 9 additions & 9 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand All @@ -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 ##

Expand Down Expand Up @@ -252,16 +252,16 @@ 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
($sym)(x::Unsigned, p::Int) = ($sym)(x,p,false)
($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

Expand Down
4 changes: 2 additions & 2 deletions base/number.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 12 additions & 1 deletion src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1089,6 +1089,16 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
return builder.CreateExtractValue(res, ArrayRef<unsigned>(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));
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 9 additions & 9 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
112 changes: 58 additions & 54 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -1133,39 +1133,41 @@ 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

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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit e1690fc

Please sign in to comment.