Skip to content

Commit

Permalink
Pure julia port of SLEEF version 2.80
Browse files Browse the repository at this point in the history
  • Loading branch information
musm committed May 18, 2017
0 parents commit dde0c70
Show file tree
Hide file tree
Showing 20 changed files with 2,661 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
*.jl.cov
*.jl.*.cov
*.jl.mem

17 changes: 17 additions & 0 deletions .travis.yml
@@ -0,0 +1,17 @@
# Documentation: http://docs.travis-ci.com/user/languages/julia/
language: julia
os:
- linux
- osx
julia:
- 0.6
- nightly
notifications:
email: false
# uncomment the following lines to override the default test script
#script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'versioninfo(); Pkg.clone(pwd()); Pkg.build("Sleef"); Pkg.test("Sleef"; coverage=true)'
after_success:
# push coverage results
- julia -e 'cd(Pkg.dir("Sleef")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder()); Codecov.submit(Codecov.process_folder())'
28 changes: 28 additions & 0 deletions LICENSE.md
@@ -0,0 +1,28 @@
The Sleef.jl package is licensed under the MIT "Expat" License:

> Copyright (c) 2016: Mustafa Mohamad and other contributors:
>
> https://github.com/musm/Sleef.jl/graphs/contributors
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
>
Sleef.jl includes ported code from the following project

- [sleef](https://github.com/shibatch/sleef) [public domain] Author Naoki Shibata
61 changes: 61 additions & 0 deletions README.md
@@ -0,0 +1,61 @@
<div align="center"> <img
src="https://rawgit.com/musm/Sleef.jl/master/doc/src/assets/logo.svg"
alt="SLEEF Logo" width="420"></img> </div>

[![Travis Build Status](https://travis-ci.org/musm/Sleef.jl.svg?branch=master)](https://travis-ci.org/musm/Sleef.jl)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/j7lpafn4uf1trlfi/branch/master?svg=true)](https://ci.appveyor.com/project/musm/sleef-jl/branch/master)
[![Coverage Status](https://coveralls.io/repos/github/musm/Sleef.jl/badge.svg?branch=master)](https://coveralls.io/github/musm/Sleef.jl?branch=master)
[![codecov.io](http://codecov.io/github/musm/Sleef.jl/coverage.svg?branch=master)](http://codecov.io/github/musm/Sleef.jl?branch=master)

A port of the [SLEEF math library](https://github.com/shibatch/sleef) (author Naoki Shibata) in pure Julia. This port includes a few extras including an `exp10` function and many bug fixes over the original code ([see](https://github.com/JuliaMath/Sleef.jl/issues) for a list of remanining issues that have not been fixed upstream). The library supports `Float32` and `Float64` types.

Based on SLEEF version 2.80 (with additional bugfixes).

# Usage

We recommend running Julia with `-O3` for maximal performance using `Sleef.jl` and to also build a custom system image by running
```julia
# Pkg.add("WinRPM"); WinRPM.install("gcc") # on Windows please first run this line
julia> include(joinpath(dirname(JULIA_HOME), "share", "julia", "build_sysimg.jl"))
julia> build_sysimg(force=true)
```
and then to restart `julia`; this will ensure you are taking full advantage of hardware [FMA](https://en.wikipedia.org/wiki/FMA_instruction_set) if your CPU supports it.


To use `Sleef.jl`
```julia
julia> Pkg.clone("https://github.com/JuliaMath/Sleef.jl.git")

julia> using Sleef

julia> Sleef.sin(2.3)
0.7457052121767203

julia> Sleef.sin(2.3f0)
0.74570525f0

julia> Sleef.exp(3.0)
20.085536923187668

julia> Sleef.exp(3f0)
20.085537f0
```

The available functions include (within 1 ulp)
```julia
sin, cos, tan, asin, acos, atan, atan2, sincos, sinh, cosh, tanh,
asinh, acosh, atanh, log, log2, log10, log1p, ilog2, exp, exp2, exp10, expm1, ldexp, cbrt, pow
```
Faster variants include (within 3 ulp)

```julia
sin_fast, cos_fast, tan_fast, sincos_fast, asin_fast, acos_fast, atan_fast, atan2_fast, log_fast, cbrt_fast
```

# Benchmarks

You can benchmark the performance of the Sleef.jl math library on your machine by running

```julia
include(joinpath(Pkg.dir("Sleef"), "benchmark", "benchmark.jl"))
```
1 change: 1 addition & 0 deletions REQUIRE
@@ -0,0 +1 @@
julia 0.6
32 changes: 32 additions & 0 deletions appveyor.yml
@@ -0,0 +1,32 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"

branches:
only:
- master
- /release-.*/

notifications:
- provider: Email
on_build_success: false
on_build_failure: false
on_build_status_changed: false

install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile($env:JULIA_URL, "C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia

build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
- C:\projects\julia\bin\julia -e "versioninfo(); Pkg.clone(pwd(), \"Sleef\"); Pkg.build(\"Sleef\")"

test_script:
- C:\projects\julia\bin\julia -e "Pkg.test(\"Sleef\")"
132 changes: 132 additions & 0 deletions benchmark/benchmark.jl
@@ -0,0 +1,132 @@
using Libm
using BenchmarkTools
using JLD, DataStructures

RETUNE = false
VERBOSE = true
DETAILS = false

test_types = (Float64, Float32) # Which types do you want to bench?

const bench = ("Base","Libm")
const suite = BenchmarkGroup()
for n in bench
suite[n] = BenchmarkGroup([n])
end


bench_reduce(f::Function, X) = mapreduce(x -> reinterpret(Unsigned,x), |, f(x) for x in X)

typealias IEEEFloat Union{Float32,Float64}
MRANGE(::Type{Float64}) = 10000000
MRANGE(::Type{Float32}) = 10000
IntF(::Type{Float64}) = Int64
IntF(::Type{Float32}) = Int32
x_trig{T<:IEEEFloat}(::Type{T}) = begin
x_trig = T[]
for i = 1:10000
s = reinterpret(T, reinterpret(IntF(T), T(pi)/4 * i) - IntF(T)(20))
e = reinterpret(T, reinterpret(IntF(T), T(pi)/4 * i) + IntF(T)(20))
d = s
while d <= e
append!(x_trig, d)
d = reinterpret(T, reinterpret(IntF(T), d) + IntF(T)(1))
end
end
x_trig = append!(x_trig, -10:0.0002:10)
x_trig = append!(x_trig, -MRANGE(T):200.1:MRANGE(T))
end
x_exp{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -1000:0.1:1000))
x_exp2{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -120:0.023:1000, -1000:0.02:2000))
x_exp10{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -35:0.023:1000, -300:0.01:300))
x_expm1{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -1000:0.021:1000, -1000:0.023:1000, 10.0.^-(0:0.02:300), -10.0.^-(0:0.02:300), 10.0.^(0:0.021:300), -10.0.^-(0:0.021:300)))
x_log{T<:IEEEFloat}(::Type{T}) = map(T, vcat(0.0001:0.0001:10, 0.001:0.1:10000, 1.1.^(-1000:1000), 2.1.^(-1000:1000)))
x_log10{T<:IEEEFloat}(::Type{T}) = map(T, vcat(0.0001:0.0001:10, 0.0001:0.1:10000))
x_log1p{T<:IEEEFloat}(::Type{T}) = map(T, vcat(0.0001:0.0001:10, 0.0001:0.1:10000, 10.0.^-(0:0.02:300), -10.0.^-(0:0.02:300)))
x_atrig{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-1:0.00002:1))
x_atan{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -10000:0.2:10000, -10000:0.201:10000))
x_cbrt{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10000:0.2:10000, 1.1.^(-1000:1000), 2.1.^(-1000:1000)))
x_trigh{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -1000:0.02:1000))
x_asinhatanh{T<:IEEEFloat}(::Type{T}) = map(T, vcat(-10:0.0002:10, -1000:0.02:1000))
x_acosh{T<:IEEEFloat}(::Type{T}) = map(T, vcat(1:0.0002:10, 1:0.02:1000))
x_pow{T<:IEEEFloat}(::Type{T}) = begin
xx1 = map(Tuple{T,T}, [(x,y) for x = -100:0.20:100, y = 0.1:0.20:100])[:]
xx2 = map(Tuple{T,T}, [(x,y) for x = -100:0.21:100, y = 0.1:0.22:100])[:]
xx3 = map(Tuple{T,T}, [(x,y) for x = 2.1, y = -1000:0.1:1000])
xx = vcat(xx1, xx2, xx2)
end

import Base.atanh
for f in (:atanh,)
@eval begin
($f)(x::Float64) = ccall(($(string(f)),Base.libm_name), Float64, (Float64,), x)
($f)(x::Float32) = ccall(($(string(f,"f")),Base.libm_name), Float32, (Float32,), x)
end
end

const micros = OrderedDict(
"sin" => x_trig,
"cos" => x_trig,
"tan" => x_trig,
"asin" => x_atrig,
"acos" => x_atrig,
"atan" => x_atan,
"exp" => x_exp,
"exp2" => x_exp2,
"exp10" => x_exp10,
"expm1" => x_expm1,
"log" => x_log,
"log2" => x_log10,
"log10" => x_log10,
"log1p" => x_log1p,
"sinh" => x_trigh,
"cosh" => x_trigh,
"tanh" => x_trigh,
"asinh" => x_asinhatanh,
"acosh" => x_acosh,
"atanh" => x_asinhatanh,
"cbrt" => x_cbrt
)

for n in ("Base","Libm")
for (f,x) in micros
suite[n][f] = BenchmarkGroup([f])
for T in test_types
fex = Expr(:., Symbol(n), QuoteNode(Symbol(f)))
suite[n][f][string(T)] = @benchmarkable bench_reduce($fex, $(x(T)))
end
end
end


tune_params = joinpath(dirname(@__FILE__), "params.jld")
if !isfile(tune_params) || RETUNE
tune!(suite; verbose=VERBOSE, seconds = 2)
save(tune_params, "suite", params(suite))
println("Saving tuned parameters.")
else
println("Loading pretuned parameters.")
loadparams!(suite, load(tune_params, "suite"), :evals, :samples)
end

println("Running micro benchmarks...")
results = run(suite; verbose=VERBOSE, seconds = 2)

print_with_color(:blue, "Benchmarks: median ratio Libm/Base\n")
for f in keys(micros)
print_with_color(:magenta, string(f))
for T in test_types
println()
print("time: ", )
tratio = ratio(median(results["Libm"][f][string(T)]), median(results["Base"][f][string(T)])).time
tcolor = tratio > 3 ? :red : tratio < 1.5 ? :green : :blue
print_with_color(tcolor, @sprintf("%.2f",tratio), " ", string(T))
if DETAILS
print_with_color(:blue, "details Libm/Base\n")
println(results["Libm"][f][string(T)])
println(results["Base"][f][string(T)])
println()
end
end
println("\n")
end
34 changes: 34 additions & 0 deletions doc/src/assets/logo.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit dde0c70

Please sign in to comment.