Skip to content

Commit

Permalink
Add LLVM intrinsics for floor/ceil/trunc.
Browse files Browse the repository at this point in the history
Add tests for vector trunc, round, floor, ceil.
  • Loading branch information
Arch D. Robison committed Sep 16, 2014
1 parent afe9f60 commit b389e26
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
2 changes: 1 addition & 1 deletion base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ iround(::Type{Uint128}, x::Float64) = convert(Uint128,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)
floor(x::Float64) = box(Float64,floor_llvm(unbox(Float64,x)))

## floating point promotions ##

Expand Down
14 changes: 11 additions & 3 deletions base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin,
max, min, minmax, ceil, floor, trunc, round, ^, exp2,
exp10, expm1, log1p

import Core.Intrinsics: nan_dom_err, sqrt_llvm, box, unbox, powi_llvm
import Core.Intrinsics: nan_dom_err, ceil_llvm, floor_llvm, trunc_llvm, sqrt_llvm, box, unbox, powi_llvm

# non-type specific math functions

Expand Down Expand Up @@ -132,7 +132,15 @@ sqrt(x::Float32) = box(Float32,sqrt_llvm(unbox(Float32,x)))
sqrt(x::Real) = sqrt(float(x))
@vectorize_1arg Number sqrt

for f in (:ceil, :trunc, :significand) # :rint, :nearbyint
ceil(x::Float64) = box(Float64,ceil_llvm(unbox(Float64,x)))
ceil(x::Float32) = box(Float32,ceil_llvm(unbox(Float32,x)))
@vectorize_1arg Real ceil

trunc(x::Float64) = box(Float64,trunc_llvm(unbox(Float64,x)))
trunc(x::Float32) = box(Float32,trunc_llvm(unbox(Float32,x)))
@vectorize_1arg Real trunc

for f in (:significand,) # :rint, :nearbyint
@eval begin
($f)(x::Float64) = ccall(($(string(f)),libm), Float64, (Float64,), x)
($f)(x::Float32) = ccall(($(string(f,"f")),libm), Float32, (Float32,), x)
Expand All @@ -143,7 +151,7 @@ end
round(x::Float32) = ccall((:roundf, libm), Float32, (Float32,), x)
@vectorize_1arg Real round

floor(x::Float32) = ccall((:floorf, libm), Float32, (Float32,), x)
floor(x::Float32) = box(Float32,floor_llvm(unbox(Float32,x)))
@vectorize_1arg Real floor

hypot(x::Real, y::Real) = hypot(promote(float(x), float(y))...)
Expand Down
22 changes: 20 additions & 2 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace JL_I {
nan_dom_err,
// functions
abs_float, copysign_float, flipsign_int, select_value,
sqrt_llvm, powi_llvm,
ceil_llvm, floor_llvm, trunc_llvm, sqrt_llvm, powi_llvm,
// pointer access
pointerref, pointerset, pointertoref,
// c interface
Expand Down Expand Up @@ -1390,6 +1390,24 @@ static Value *emit_intrinsic(intrinsic f, jl_value_t **args, size_t nargs,
HANDLE(jl_alloca,1) {
return builder.CreateAlloca(IntegerType::get(jl_LLVMContext, 8),JL_INT(x));
}
HANDLE(ceil_llvm,1) {
x = FP(x);
return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::ceil,
ArrayRef<Type*>(x->getType())),
x);
}
HANDLE(floor_llvm,1) {
x = FP(x);
return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::floor,
ArrayRef<Type*>(x->getType())),
x);
}
HANDLE(trunc_llvm,1) {
x = FP(x);
return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::trunc,
ArrayRef<Type*>(x->getType())),
x);
}
HANDLE(sqrt_llvm,1) {
x = FP(x);
raise_exception_unless(builder.CreateFCmpUGE(x, ConstantFP::get(x->getType(),0.0)),
Expand Down Expand Up @@ -1494,7 +1512,7 @@ extern "C" void jl_init_intrinsic_functions(void)
ADD_I(uitofp); ADD_I(sitofp);
ADD_I(fptrunc); ADD_I(fpext);
ADD_I(abs_float); ADD_I(copysign_float);
ADD_I(flipsign_int); ADD_I(select_value); ADD_I(sqrt_llvm);
ADD_I(flipsign_int); ADD_I(select_value); ADD_I(ceil_llvm); ADD_I(floor_llvm); ADD_I(trunc_llvm); ADD_I(sqrt_llvm);
ADD_I(powi_llvm);
ADD_I(pointerref); ADD_I(pointerset); ADD_I(pointertoref);
ADD_I(checked_sadd); ADD_I(checked_uadd);
Expand Down
15 changes: 15 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,21 @@ for x = 2^24-10:2^24+10
@test iceil(y) == i
end

# rounding vectors
let (x,y) = x==y || typeof(x)==typeof(y)
for t in [Float32,Float64]
# try different vector lengths
for n in [0,3,255,256]
r = (1:n)-div(n,2)
y = t[x/4 for x in r]
@test trunc(y) t[div(i,4) for i in r]
@test round(y) t[(i+1+(i>=0))>>2 for i in r]
@test floor(y) t[i>>2 for i in r]
@test ceil(y) t[(i+3)>>2 for i in r]
end
end
end

@test_throws InexactError iround(Inf)
@test_throws InexactError iround(NaN)
@test iround(2.5) == 3
Expand Down

0 comments on commit b389e26

Please sign in to comment.