From 3848b4cd4d3d3eeb62c85301be7177c031ea7d07 Mon Sep 17 00:00:00 2001 From: "Arch D. Robison" Date: Fri, 12 Sep 2014 17:40:33 -0500 Subject: [PATCH] Add LLVM intrinsics for floor/ceil/trunc. Add tests for vector trunc, round, floor, ceil. --- base/float.jl | 2 +- base/math.jl | 14 +++++++++++--- src/intrinsics.cpp | 22 ++++++++++++++++++++-- test/numbers.jl | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/base/float.jl b/base/float.jl index a43243daf9f081..132de5752799c7 100644 --- a/base/float.jl +++ b/base/float.jl @@ -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 ## diff --git a/base/math.jl b/base/math.jl index 0df6fa18b805a5..915f611ff61608 100644 --- a/base/math.jl +++ b/base/math.jl @@ -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 @@ -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) @@ -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))...) diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 1a6a4518adf012..32645e4b5c7774 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -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 @@ -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(x->getType())), + x); + } + HANDLE(floor_llvm,1) { + x = FP(x); + return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::floor, + ArrayRef(x->getType())), + x); + } + HANDLE(trunc_llvm,1) { + x = FP(x); + return builder.CreateCall(Intrinsic::getDeclaration(jl_Module, Intrinsic::trunc, + ArrayRef(x->getType())), + x); + } HANDLE(sqrt_llvm,1) { x = FP(x); raise_exception_unless(builder.CreateFCmpUGE(x, ConstantFP::get(x->getType(),0.0)), @@ -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); diff --git a/test/numbers.jl b/test/numbers.jl index 6e8b9408f27fcc..870960d66b6b6c 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -1312,6 +1312,21 @@ for x = 2^24-10:2^24+10 @test iceil(y) == i end +# rounding vectors +let ==(x,y) = Base.(:(==))(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