Skip to content

Commit

Permalink
add conversions between float and int128 types
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Feb 15, 2013
1 parent 06b0667 commit b198961
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 15 deletions.
31 changes: 20 additions & 11 deletions base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ convert(::Type{Float32}, x::Int8) = box(Float32,sitofp32(unbox(Int8,x)))
convert(::Type{Float32}, x::Int16) = box(Float32,sitofp32(unbox(Int16,x)))
convert(::Type{Float32}, x::Int32) = box(Float32,sitofp32(unbox(Int32,x)))
convert(::Type{Float32}, x::Int64) = box(Float32,sitofp32(unbox(Int64,x)))
convert(::Type{Float32}, x::Int128) = float32(uint128(abs(x)))*(1-2(x<0))
convert(::Type{Float32}, x::Uint8) = box(Float32,uitofp32(unbox(Uint8,x)))
convert(::Type{Float32}, x::Uint16) = box(Float32,uitofp32(unbox(Uint16,x)))
convert(::Type{Float32}, x::Uint32) = box(Float32,uitofp32(unbox(Uint32,x)))
convert(::Type{Float32}, x::Uint64) = box(Float32,uitofp32(unbox(Uint64,x)))
convert(::Type{Float32}, x::Uint128) = float32(uint64(x)) + ldexp(float32(uint64(x>>>64)),64)
convert(::Type{Float32}, x::Float64) = box(Float32,fptrunc32(unbox(Float64,x)))

convert(::Type{Float64}, x::Bool) = box(Float64,uitofp64(unbox(Bool,x)))
Expand All @@ -18,22 +20,26 @@ convert(::Type{Float64}, x::Int8) = box(Float64,sitofp64(unbox(Int8,x)))
convert(::Type{Float64}, x::Int16) = box(Float64,sitofp64(unbox(Int16,x)))
convert(::Type{Float64}, x::Int32) = box(Float64,sitofp64(unbox(Int32,x)))
convert(::Type{Float64}, x::Int64) = box(Float64,sitofp64(unbox(Int64,x)))
convert(::Type{Float64}, x::Int128) = float64(uint128(abs(x)))*(1-2(x<0))
convert(::Type{Float64}, x::Uint8) = box(Float64,uitofp64(unbox(Uint8,x)))
convert(::Type{Float64}, x::Uint16) = box(Float64,uitofp64(unbox(Uint16,x)))
convert(::Type{Float64}, x::Uint32) = box(Float64,uitofp64(unbox(Uint32,x)))
convert(::Type{Float64}, x::Uint64) = box(Float64,uitofp64(unbox(Uint64,x)))
convert(::Type{Float64}, x::Uint128) = float64(uint64(x)) + ldexp(float64(uint64(x>>>64)),64)
convert(::Type{Float64}, x::Float32) = box(Float64,fpext64(unbox(Float32,x)))

convert(::Type{FloatingPoint}, x::Bool) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Char) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int8) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int16) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int32) = convert(Float64, x)
convert(::Type{FloatingPoint}, x::Int64) = convert(Float64, x) # LOSSY
convert(::Type{FloatingPoint}, x::Uint8) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Uint16) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Uint32) = convert(Float64, x)
convert(::Type{FloatingPoint}, x::Uint64) = convert(Float64, x) # LOSSY
convert(::Type{FloatingPoint}, x::Bool) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Char) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int8) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int16) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Int32) = convert(Float64, x)
convert(::Type{FloatingPoint}, x::Int64) = convert(Float64, x) # LOSSY
convert(::Type{FloatingPoint}, x::Int128) = convert(Float64, x) # LOSSY
convert(::Type{FloatingPoint}, x::Uint8) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Uint16) = convert(Float32, x)
convert(::Type{FloatingPoint}, x::Uint32) = convert(Float64, x)
convert(::Type{FloatingPoint}, x::Uint64) = convert(Float64, x) # LOSSY
convert(::Type{FloatingPoint}, x::Uint128) = convert(Float64, x) # LOSSY

float32(x) = convert(Float32, x)
float64(x) = convert(Float64, x)
Expand Down Expand Up @@ -69,7 +75,10 @@ iround(::Type{Int64}, x::Float32) = box(Int64,fpsiround64(fpext64(unbox(Float32,
iround(::Type{Int64}, x::Float64) = box(Int64,fpsiround64(unbox(Float64,x)))
iround(::Type{Uint64}, x::Float32) = box(Uint64,fpuiround64(fpext64(unbox(Float32,x))))
iround(::Type{Uint64}, x::Float64) = box(Uint64,fpuiround64(unbox(Float64,x)))
# TODO: Int128
iround(::Type{Int128}, x::Float32) = convert(Int128,round(x))
iround(::Type{Int128}, x::Float64) = convert(Int128,round(x))
iround(::Type{Uint128}, x::Float32) = convert(Uint128,round(x))
iround(::Type{Uint128}, x::Float64) = convert(Uint128,round(x))

# this is needed very early because it is used by Range and colon
floor(x::Float64) = ccall((:floor, Base.libm_name), Float64, (Float64,), x)
Expand Down
20 changes: 16 additions & 4 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,14 @@ convert(::Type{Int128}, x::Uint32 ) = box(Int128,zext_int(Uint128,unbox(Uint32,x
convert(::Type{Int128}, x::Int64 ) = box(Int128,sext_int(Int128,unbox(Int64,x)))
convert(::Type{Int128}, x::Uint64 ) = box(Int128,zext_int(Uint128,unbox(Uint64,x)))
convert(::Type{Int128}, x::Uint128) = box(Int128,unbox(Uint128,x))
# TODO: convert(::Type{Int128}, x::Float32)
# TODO: convert(::Type{Int128}, x::Float64)
function convert(::Type{Int128}, x::Float64)
ax = abs(x)
top = trunc(ldexp(ax,-64))
bot = ax - ldexp(top,64)
n = int128(convert(Uint64,top))<<64 + int128(convert(Uint64,bot))
return x<0 ? -n : n
end

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Feb 15, 2013

Member

This seems crazy expensive, but I guess there aren't any LLVM intrinsics for this.

This comment has been minimized.

Copy link
@JeffBezanson

JeffBezanson Feb 15, 2013

Author Member

You're welcome :)
Actually, it turns out fptoui does work, we just need fptoui(Uint128, ...) and then get rid of the size-specific versions. But I'm not sure what the limit is there, or what the performance is for that matter.

This comment has been minimized.

Copy link
@StefanKarpinski

StefanKarpinski Feb 15, 2013

Member

:) Making it work even if slowly is, of course, way better than having it not work at all.

convert(::Type{Int128}, x::Float32) = convert(Int128, float64(x))

convert(::Type{Uint128}, x::Bool ) = box(Uint128,zext_int(Int128,unbox(Bool,x)))
convert(::Type{Uint128}, x::Int8 ) = box(Uint128,sext_int(Int128,unbox(Int8,x)))
Expand All @@ -137,8 +143,14 @@ convert(::Type{Uint128}, x::Uint32 ) = box(Uint128,zext_int(Uint128,unbox(Uint32
convert(::Type{Uint128}, x::Int64 ) = box(Uint128,sext_int(Int128,unbox(Int64,x)))
convert(::Type{Uint128}, x::Uint64 ) = box(Uint128,zext_int(Uint128,unbox(Uint64,x)))
convert(::Type{Uint128}, x::Int128 ) = box(Uint128,unbox(Int128,x))
# TODO: convert(::Type{Uint128}, x::Float32)
# TODO: convert(::Type{Uint128}, x::Float64)
function convert(::Type{Uint128}, x::Float64)
ax = abs(x)
top = trunc(ldexp(ax,-64))
bot = ax - ldexp(top,64)
n = uint128(convert(Uint64,top))<<64 + uint128(convert(Uint64,bot))
return x<0 ? -n : n
end
convert(::Type{Uint128}, x::Float32) = convert(Uint128, float64(x))

convert(::Type{Signed}, x::Uint8 ) = convert(Int,x)
convert(::Type{Signed}, x::Uint16 ) = convert(Int,x)
Expand Down
21 changes: 21 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,27 @@ end

@test typemax(Uint64) != 2.0^64

@test float64(int128(0)) == 0.0
@test float32(int128(0)) == 0.0f0
@test float64(int128(-1)) == -1.0
@test float32(int128(-1)) == -1.0f0
@test float64(int128(3)) == 3.0
@test float32(int128(3)) == 3.0f0
@test float64(uint128(10121)) == 10121.0
@test float32(uint128(10121)) == 10121.0f0
@test float64(typemin(Int128)) == -2.0^127
@test float32(typemin(Int128)) == -2.0f0^127
@test float64(typemax(Int128)) == 2.0^127
@test float32(typemax(Int128)) == 2.0f0^127
@test float64(typemin(Uint128)) == 0.0
@test float32(typemin(Uint128)) == 0.0f0
@test float64(typemax(Uint128)) == 2.0^128
@test float32(typemax(Uint128)) == 2.0f0^128

@test int128(-2.0^127) == typemin(Int128)
@test float64(uint128(3.7e19)) == 3.7e19
@test float64(uint128(3.7e30)) == 3.7e30

@test !(NaN <= 1)
@test !(NaN >= 1)
@test !(NaN < 1)
Expand Down

0 comments on commit b198961

Please sign in to comment.