Skip to content

Commit

Permalink
itrunc -> trunc, etc, improve iround
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbyrne committed Nov 24, 2014
1 parent 04271cd commit d17c909
Show file tree
Hide file tree
Showing 50 changed files with 576 additions and 581 deletions.
10 changes: 5 additions & 5 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ function randsubseq!(S::AbstractArray, A::AbstractArray, p::Real)
empty!(S)
p == 0 && return S
nexpected = p * length(A)
sizehint(S, iround(nexpected + 5*sqrt(nexpected)))
sizehint(S, round(Int,nexpected + 5*sqrt(nexpected)))
if p > 0.15 # empirical threshold for trivial O(n) algorithm to be better
for i = 1:n
rand() <= p && push!(S, A[i])
Expand All @@ -1396,14 +1396,14 @@ function randsubseq!(S::AbstractArray, A::AbstractArray, p::Real)
# s==k (k > 0) is (1-p)^(k-1) * p, and hence the probability (CDF) that
# s is in {1,...,k} is 1-(1-p)^k = F(k). Thus, we can draw the skip s
# from this probability distribution via the discrete inverse-transform
# method: s = iceil(F^{-1}(u)) where u = rand(), which is simply
# s = iceil(log(rand()) / log1p(-p)).
# method: s = ceil(F^{-1}(u)) where u = rand(), which is simply
# s = ceil(log(rand()) / log1p(-p)).
L = 1 / log1p(-p)
i = 0
while true
s = log(rand()) * L # note that rand() < 1, so s > 0
s >= n - i && return S # compare before iceil to avoid overflow
push!(S, A[i += iceil(s)])
s >= n - i && return S # compare before ceil to avoid overflow
push!(S, A[i += ceil(Int,s)])
end
# [This algorithm is similar in spirit to, but much simpler than,
# the one by Vitter for a related problem in "Faster methods for
Expand Down
5 changes: 1 addition & 4 deletions base/bitarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -790,10 +790,7 @@ function empty!(B::BitVector)
end

## Misc functions

for f in (:iround, :itrunc, :ifloor, :iceil, :abs)
@eval ($f)(B::BitArray) = copy(B)
end
abs(B::BitArray) = copy(B)

## Unary operators ##

Expand Down
2 changes: 1 addition & 1 deletion base/char.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
char(x) = convert(Char, x)
char(x::FloatingPoint) = char(iround(x))
char(x::FloatingPoint) = char(round(UInt32,x))

integer(x::Char) = int(x)

Expand Down
4 changes: 2 additions & 2 deletions base/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ function ^{T<:Complex}(z::T, p::T)

# apply some corrections to force known zeros
if pim == 0
ip = itrunc(pr)
ip = trunc(pr)
if ip == pr
if zi == 0
im = copysign(zero(im), im)
Expand All @@ -490,7 +490,7 @@ function ^{T<:Complex}(z::T, p::T)
end
else
dr = pr*2
ip = itrunc(dr)
ip = trunc(dr)
if ip == dr && zi == 0
if zr < 0
re = copysign(zero(re), re)
Expand Down
2 changes: 1 addition & 1 deletion base/darray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ end
# get array of start indexes for dividing sz into nc chunks
function defaultdist(sz::Int, nc::Int)
if sz >= nc
iround(linspace(1, sz+1, nc+1))
round(Int,linspace(1, sz+1, nc+1))
else
[[1:(sz+1)], zeros(Int, nc-sz)]
end
Expand Down
2 changes: 1 addition & 1 deletion base/dates/ranges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Base.colon{T<:DateTime}(start::T, stop::T) = StepRange(start, Day(1), stop)

# Given a start and end date, how many steps/periods are in between
guess(a::DateTime,b::DateTime,c) = ifloor(Int64,(int128(b) - int128(a))/toms(c))
guess(a::DateTime,b::DateTime,c) = floor(Int64,(int128(b) - int128(a))/toms(c))
guess(a::Date,b::Date,c) = int64(div(int64(b - a),days(c)))
function len(a,b,c)
lo, hi, st = min(a,b), max(a,b), abs(c)
Expand Down
9 changes: 9 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,12 @@ const Uint128 = UInt128

@deprecate rand!(r::Range, A::AbstractArray) rand!(A, r)
@deprecate rand!(mt::MersenneTwister, r::Range, A::AbstractArray) rand!(mt, A, r)

@deprecate itrunc(x) trunc(Integer,x)
@deprecate itrunc{T<:Integer}(::Type{T},x::Real) trunc(T,x)
@deprecate iceil(x) ceil(Integer,x)
@deprecate iceil{T}(::Type{T},x) ceil(T,x)
@deprecate ifloor(x) floor(Integer,x)
@deprecate ifloor{T}(::Type{T},x) floor(T,x)
@deprecate iround(x) round(Integer,x)
@deprecate iround{T}(::Type{T},x) round(T,x)
4 changes: 0 additions & 4 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,6 @@ export
gcdx,
hex2num,
hypot,
iceil,
ifloor,
imag,
int,
int128,
Expand All @@ -373,7 +371,6 @@ export
inv,
invdigamma,
invmod,
iround,
isapprox,
iseltype,
iseven,
Expand All @@ -387,7 +384,6 @@ export
isqrt,
isreal,
issubnormal,
itrunc,
lcm,
ldexp,
leading_ones,
Expand Down
111 changes: 53 additions & 58 deletions base/float.jl
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
## conversions to floating-point ##

convert(::Type{Float32}, x::Int128) = float32(reinterpret(UInt128,abs(x)))*(1-2(x<0))
convert(::Type{Float32}, x::UInt128) = float32(uint64(x&0xffffffffffffffff)) + ldexp(float32(uint64(x>>>64)),64)
promote_rule(::Type{Float32}, ::Type{Int128} ) = Float32
promote_rule(::Type{Float32}, ::Type{UInt128}) = Float32

convert(::Type{Float64}, x::Int128) = float64(reinterpret(UInt128,abs(x)))*(1-2(x<0))
convert(::Type{Float64}, x::UInt128) = float64(uint64(x&0xffffffffffffffff)) + ldexp(float64(uint64(x>>>64)),64)
promote_rule(::Type{Float64}, ::Type{Int128} ) = Float64
promote_rule(::Type{Float64}, ::Type{UInt128}) = Float64

convert(::Type{Float16}, x::Integer) = convert(Float16, convert(Float32,x))
for t in (Bool,Char,Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64)
@eval promote_rule(::Type{Float16}, ::Type{$t}) = Float32
end

for t1 in (Float32,Float64)
for st in (Int8,Int16,Int32,Int64)
for st in (Int8,Int16,Int32,Int64,Int128)
@eval begin
convert(::Type{$t1},x::($st)) = box($t1,sitofp($t1,unbox($st,x)))
promote_rule(::Type{$t1}, ::Type{$st} ) = $t1
end
end
for ut in (Bool,Char,UInt8,UInt16,UInt32,UInt64)
for ut in (Bool,Char,UInt8,UInt16,UInt32,UInt64,UInt128)
@eval begin
convert(::Type{$t1},x::($ut)) = box($t1,uitofp($t1,unbox($ut,x)))
promote_rule(::Type{$t1}, ::Type{$ut} ) = $t1
Expand Down Expand Up @@ -55,55 +44,39 @@ float32(x) = convert(Float32, x)
float64(x) = convert(Float64, x)
float(x) = convert(FloatingPoint, x)

## conversions from floating-point ##

# fallbacks using only convert, trunc, ceil, floor, round
itrunc(x::FloatingPoint) = convert(Integer,trunc(x))
iceil (x::FloatingPoint) = convert(Integer,ceil(x)) # TODO: fast primitive for iceil
ifloor(x::FloatingPoint) = convert(Integer,floor(x)) # TOOD: fast primitive for ifloor
iround(x::FloatingPoint) = convert(Integer,round(x))

itrunc{T<:Integer}(::Type{T}, x::FloatingPoint) = convert(T,trunc(x))
iceil {T<:Integer}(::Type{T}, x::FloatingPoint) = convert(T,ceil(x))
ifloor{T<:Integer}(::Type{T}, x::FloatingPoint) = convert(T,floor(x))
iround{T<:Integer}(::Type{T}, x::FloatingPoint) = convert(T,round(x))

## fast specific type conversions ##

iround(x::Float32) = iround(Int, x)
iround(x::Float64) = iround(Int, x)
itrunc(x::Float32) = itrunc(Int, x)
itrunc(x::Float64) = itrunc(Int, x)

for to in (Int8, Int16, Int32, Int64)
for Ti in (Int8, Int16, Int32, Int64, Int128)
@eval begin
iround(::Type{$to}, x::Float32) = box($to,fpsiround($to,unbox(Float32,x)))
iround(::Type{$to}, x::Float64) = box($to,fpsiround($to,unbox(Float64,x)))
itrunc(::Type{$to}, x::Float32) = box($to,fptosi($to,unbox(Float32,x)))
itrunc(::Type{$to}, x::Float64) = box($to,fptosi($to,unbox(Float64,x)))
unsafe_trunc(::Type{$Ti}, x::Float32) = box($Ti,fptosi($Ti,unbox(Float32,x)))
unsafe_trunc(::Type{$Ti}, x::Float64) = box($Ti,fptosi($Ti,unbox(Float64,x)))
end
end

for to in (UInt8, UInt16, UInt32, UInt64)
for Ti in (UInt8, UInt16, UInt32, UInt64, UInt128)
@eval begin
iround(::Type{$to}, x::Float32) = box($to,fpuiround($to,unbox(Float32,x)))
iround(::Type{$to}, x::Float64) = box($to,fpuiround($to,unbox(Float64,x)))
itrunc(::Type{$to}, x::Float32) = box($to,fptoui($to,unbox(Float32,x)))
itrunc(::Type{$to}, x::Float64) = box($to,fptoui($to,unbox(Float64,x)))
unsafe_trunc(::Type{$Ti}, x::Float32) = box($Ti,fptoui($Ti,unbox(Float32,x)))
unsafe_trunc(::Type{$Ti}, x::Float64) = box($Ti,fptoui($Ti,unbox(Float64,x)))
end
end

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))
# matches convert methods
# also determines floor, ceil, round
trunc(::Type{Signed}, x::Float32) = trunc(Int,x)
trunc(::Type{Signed}, x::Float64) = trunc(Int,x)
trunc(::Type{Unsigned}, x::Float32) = trunc(UInt,x)
trunc(::Type{Unsigned}, x::Float64) = trunc(UInt,x)
trunc(::Type{Integer}, x::Float32) = trunc(Int,x)
trunc(::Type{Integer}, x::Float64) = trunc(Int,x)

# fallbacks
floor{T<:Integer}(::Type{T}, x::FloatingPoint) = trunc(T,floor(x))
ceil {T<:Integer}(::Type{T}, x::FloatingPoint) = trunc(T,ceil(x))
round {T<:Integer}(::Type{T}, x::FloatingPoint) = trunc(T,round(x))


# this is needed very early because it is used by Range and colon
round(x::Float64) = ccall((:round, Base.libm_name), Float64, (Float64,), x)
floor(x::Float64) = ccall((:floor, Base.libm_name), Float64, (Float64,), x)

## floating point promotions ##

promote_rule(::Type{Float32}, ::Type{Float16}) = Float32
promote_rule(::Type{Float64}, ::Type{Float16}) = Float64
promote_rule(::Type{Float64}, ::Type{Float32}) = Float64
Expand All @@ -112,7 +85,6 @@ widen(::Type{Float16}) = Float32
widen(::Type{Float32}) = Float64

## floating point arithmetic ##

-(x::Float32) = box(Float32,neg_float(unbox(Float32,x)))
-(x::Float64) = box(Float64,neg_float(unbox(Float64,x)))

Expand All @@ -128,7 +100,6 @@ widen(::Type{Float32}) = Float64
# TODO: faster floating point div?
# TODO: faster floating point fld?
# TODO: faster floating point mod?

rem(x::Float32, y::Float32) = box(Float32,rem_float(unbox(Float32,x),unbox(Float32,y)))
rem(x::Float64, y::Float64) = box(Float64,rem_float(unbox(Float64,x),unbox(Float64,y)))

Expand All @@ -147,7 +118,6 @@ end


## floating point comparisons ##

==(x::Float32, y::Float32) = eq_float(unbox(Float32,x),unbox(Float32,y))
==(x::Float64, y::Float64) = eq_float(unbox(Float64,x),unbox(Float64,y))
!=(x::Float32, y::Float32) = ne_float(unbox(Float32,x),unbox(Float32,y))
Expand Down Expand Up @@ -177,31 +147,31 @@ function cmp(x::FloatingPoint, y::Real)
ifelse(x<y, -1, ifelse(x>y, 1, 0))
end

for Ti in (Int64,UInt64)
for Ti in (Int64,UInt64,Int128,UInt128)
for Tf in (Float32,Float64)
@eval begin
function ==(x::$Tf, y::$Ti)
fy = ($Tf)(y)
(x == fy) & (y == itrunc($Ti,fy))
(x == fy) & (y == unsafe_trunc($Ti,fy))
end
==(y::$Ti, x::$Tf) = x==y

function <(x::$Ti, y::$Tf)
fx = ($Tf)(x)
(fx < y) | ((fx == y) & ((fx == $(Tf(typemax(Ti)))) | (x < itrunc($Ti,fx)) ))
(fx < y) | ((fx == y) & ((fx == $(Tf(typemax(Ti)))) | (x < unsafe_trunc($Ti,fx)) ))
end
function <=(x::$Ti, y::$Tf)
fx = ($Tf)(x)
(fx < y) | ((fx == y) & ((fx == $(Tf(typemax(Ti)))) | (x <= itrunc($Ti,fx)) ))
(fx < y) | ((fx == y) & ((fx == $(Tf(typemax(Ti)))) | (x <= unsafe_trunc($Ti,fx)) ))
end

function <(x::$Tf, y::$Ti)
fy = ($Tf)(y)
(x < fy) | ((x == fy) & (fy < $(Tf(typemax(Ti)))) & (itrunc($Ti,fy) < y))
(x < fy) | ((x == fy) & (fy < $(Tf(typemax(Ti)))) & (unsafe_trunc($Ti,fy) < y))
end
function <=(x::$Tf, y::$Ti)
fy = ($Tf)(y)
(x < fy) | ((x == fy) & (fy < $(Tf(typemax(Ti)))) & (itrunc($Ti,fy) <= y))
(x < fy) | ((x == fy) & (fy < $(Tf(typemax(Ti)))) & (unsafe_trunc($Ti,fy) <= y))
end
end
end
Expand Down Expand Up @@ -263,6 +233,31 @@ nextfloat(x::Float64, i::Integer) =
nextfloat(x::FloatingPoint) = nextfloat(x,1)
prevfloat(x::FloatingPoint) = nextfloat(x,-1)

for Ti in (Int8, Int16, Int32, Int64, Int128, UInt8, UInt16, UInt32, UInt64, UInt128)
for Tf in (Float32, Float64)
if sizeof(Ti) < sizeof(Tf) || Ti <: Unsigned # Tf(typemin(Ti))-1 is exact
@eval function trunc(::Type{$Ti},x::$Tf)
$(Tf(typemin(Ti))-one(Tf)) < x < $(Tf(typemax(Ti))+one(Tf)) || throw(InexactError())
unsafe_trunc($Ti,x)
end
else
@eval function trunc(::Type{$Ti},x::$Tf)
$(Tf(typemin(Ti))) <= x < $(Tf(typemax(Ti))) || throw(InexactError())
unsafe_trunc($Ti,x)
end
end
end
end

# adding prevfloat(0.5) will prevent prevfloat(0.5) and odd x with eps(x)=1.0
# from rounding in the wrong direction in RoundToNearest
for Tf in (Float32,Float64)
@eval function round{T<:Integer}(::Type{T}, x::$Tf)
trunc(T,x+copysign($(prevfloat(Tf(0.5))),x))
end
end


@eval begin
issubnormal(x::Float32) = (abs(x) < $(box(Float32,unbox(UInt32,0x00800000)))) & (x!=0)
issubnormal(x::Float64) = (abs(x) < $(box(Float64,unbox(UInt64,0x0010000000000000)))) & (x!=0)
Expand Down
6 changes: 4 additions & 2 deletions base/float16.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ convert(::Type{UInt128}, x::Float16) = convert(UInt128, float32(x))

convert{T<:Integer}(::Type{T}, x::Float16) = convert(T, float32(x))

iround{T<:Integer}(::Type{T}, x::Float16) = iround(T, float32(x))
itrunc{T<:Integer}(::Type{T}, x::Float16) = itrunc(T, float32(x))
round{T<:Integer}(::Type{T}, x::Float16) = round(T, float32(x))
trunc{T<:Integer}(::Type{T}, x::Float16) = trunc(T, float32(x))
floor{T<:Integer}(::Type{T}, x::Float16) = floor(T, float32(x))
ceil {T<:Integer}(::Type{T}, x::Float16) = ceil(T, float32(x))

round(x::Float16) = float16(round(float32(x)))
trunc(x::Float16) = float16(trunc(float32(x)))
Expand Down
22 changes: 14 additions & 8 deletions base/floatfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ function hex2num(s::AbstractString)
return box(Float64,unbox(Int64,parseint(Int64,s,16)))
end

@vectorize_1arg Real iround
@vectorize_1arg Real itrunc
@vectorize_1arg Real ifloor
@vectorize_1arg Real iceil

@vectorize_1arg Number abs
@vectorize_1arg Number abs2
@vectorize_1arg Number angle
Expand All @@ -48,9 +43,20 @@ end
@vectorize_1arg Number isinf
@vectorize_1arg Number isfinite

iround{T<:Integer,R<:Real}(::Type{T}, x::AbstractArray{R,1}) = [ iround(T, x[i]) for i = 1:length(x) ]
iround{T<:Integer,R<:Real}(::Type{T}, x::AbstractArray{R,2}) = [ iround(T, x[i,j]) for i = 1:size(x,1), j = 1:size(x,2) ]
iround{T<:Integer,R<:Real}(::Type{T}, x::AbstractArray{R}) = reshape([ iround(T, x[i]) for i = 1:length(x) ], size(x))
for f in (:trunc,:floor,:ceil,:round)
@eval begin
function ($f){T,R<:Real}(::Type{T}, x::AbstractArray{R,1})
[ ($f)(T, x[i]) for i = 1:length(x) ]
end
function ($f){T,R<:Real}(::Type{T}, x::AbstractArray{R,2})
[ ($f)(T, x[i,j]) for i = 1:size(x,1), j = 1:size(x,2) ]
end
function ($f){T,R<:Real}(::Type{T}, x::AbstractArray{R})
reshape([ ($f)(T, x[i]) for i = 1:length(x) ], size(x))
end
end
end


# adapted from Matlab File Exchange roundsd: http://www.mathworks.com/matlabcentral/fileexchange/26212
# for round, og is the power of 10 relative to the decimal point
Expand Down
2 changes: 1 addition & 1 deletion base/grisu/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ const MinDecimalExponent = -348
const MaxDecimalExponent = 340

function binexp_cache(min_exponent,max_exponent)
k = iceil((min_exponent+63)*D_1_LOG2_10)
k = ceil(Integer,(min_exponent+63)*D_1_LOG2_10)
index = div(CachedPowersOffset+k-1,DecimalExponentDistance) + 1
cp = CachedPowers[index+1]
return cp
Expand Down
Loading

0 comments on commit d17c909

Please sign in to comment.