Commit 123f17ff authored by nicoo's avatar nicoo

New upstream version 1.2

parents
.git
graphs
ml-toy
papers
herbie/compile/tc*
herbie/compile/nr*
rebuild-paper.sh
*~
graphs
compile/*.o
compile/*.bin
compile/tc*.c
compile/tc*.out
compile/tc.json
compile/nr*.c
compile/nr*.out
compile/nr.json
compile/cost
compiled/
ml-toy
papers
www/demo
demo.log
*.class
cost
previous
language: c
sudo: required
env:
global:
- RACKET_DIR=~/racket
TBENCHES="bench/tutorial.fpcore bench/hamming/"
HERBIE_SEED="#(2749829514 1059579101 312104142 915324965 966790849 1349306526)"
TSEED="racket $TRAVIS_BUILD_DIR/infra/travis.rkt --seed '${HERBIE_SEED}' $TBENCHES"
TRAND="racket $TRAVIS_BUILD_DIR/infra/travis.rkt $TBENCHES"
UTEST="raco test src"
matrix:
# separate builds for travis benches and unit tests
- RACKET_VERSION="6.7"
JOB="${TSEED}"
- RACKET_VERSION="6.9"
JOB="${TSEED}"
- RACKET_VERSION="6.11"
JOB="${TSEED}"
- RACKET_VERSION="6.7"
JOB="${UTEST}"
- RACKET_VERSION="6.9"
JOB="${UTEST}"
- RACKET_VERSION="6.11"
JOB="${UTEST}"
# remember to change the `allow_failures` key below!
- RACKET_VERSION="6.11"
JOB="${TRAND}"
matrix:
allow_failures:
- env: RACKET_VERSION="6.11"
JOB="${TRAND}"
before_install:
- git clone https://github.com/greghendershott/travis-racket.git ../travis-racket
- cat ../travis-racket/install-racket.sh | bash
- export PATH="${RACKET_DIR}/bin:${PATH}"
install:
- raco pkg install --auto $TRAVIS_BUILD_DIR/src
script:
- echo ${JOB} && eval ${JOB}
notifications:
slack:
secure: QB8ib/gxZWZ8rY9H54BktIgx8LfjdqabSAkmWip0VHlUhrh2ULG566XgmB5h75eNzCil2cw76ma5wfSC0MNIQ1iDHKCxAgTE0+gcPcZAYGfucQ28sKGBG2wcuJfvBLG6lVDxj+luGUh3XohouTLYI9cg509JBgTgpcrXVexYAaE=
FROM jackfirth/racket:6.12
MAINTAINER Pavel Panchekha <me@pavpanchekha.com>
RUN apt-get update \
&& apt-get install -y libcairo2-dev libjpeg62 libpango1.0-dev \
&& rm -rf /var/lib/apt/lists/*
ADD src /src/herbie
RUN raco pkg install --auto /src/herbie
ENTRYPOINT ["racket", "/src/herbie/herbie.rkt"]
Editing
=======
You should use Emacs to edit Racket code; Dr. Racket, which ships with
Racket, is a bit too limited an editor for the number of files and
complexity of Herbie. You’ll want to use the `quack` and `geiser` Emacs
packages to give you Racket-specific highlighting and a Racket REPL.
The easiest way to install these is to run
(require 'package)
(add-to-list 'package-archives
'("marmalade" . "http://marmalade-repo.org/packages/"))
(package-initialize)
(mapcar #'package-install '(quack geiser))
This needs to be done once. You can now open a Racket file, like
`herbie/main.rkt`, and the mode-line will read `Scheme Racket/A`,
indicating that Quack, the Scheme mode, is running.
If you hit `C-c C-a` in a Racket buffer, you’ll open up a REPL and
“enter” that module, allowing you to refer to definitions in it. The
same `C-c C-a` binding reloads the file, while `C-M-x` reloads
individual definitions and `C-c C-e` executes individual
S-expressions.
\ No newline at end of file
Copyright (c) 2015 Herbie Project
Modified work Copyright 2016 Google Inc.
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.
.PHONY: all install update nightly index clean publish start-server package loc deploy
all:
@echo "Type 'make install' to install Herbie as a Racket package,"
@echo "Run 'racket src/herbie.rkt shell' to run Herbie."
install:
raco pkg install --name herbie src/
update:
raco pkg update --name herbie src/
nightly:
bash infra/nightly.sh
bash infra/nightly.sh --enable rules:numerics
$(MAKE) index
index:
bash infra/publish.sh index
herbie.zip herbie.zip.CHECKSUM:
raco pkg create src/
mv src.zip herbie.zip
mv src.zip.CHECKSUM herbie.zip.CHECKSUM
clean:
rm -f cost
rm -rf graphs/
publish:
bash infra/publish.sh upload graphs/
bash infra/publish.sh index
start-server:
racket src/herbie.rkt web --seed '#(2775764126 3555076145 3898259844 1891440260 2599947619 1948460636)' --timeout 60 --num-iters 2 --demo --prefix /demo/ --port 4053 --save-session www/demo/ --log infra/server.log --quiet 2>&1
package:
raco pkg
loc:
find herbie/ -type f -exec cat {} \; | wc -l
# This rule is run by herbie.uwplse.org on every commit to Github.
# It does not restart the demo server, but it does pull new static content
deploy:
cd $(shell ~/uwplse/getdir) && git pull
cost: infra/cost.c
$(CC) -O0 $^ -lm -o $@
![Herbie](logo.png)
[![Build Status](https://travis-ci.org/uwplse/herbie.svg?branch=master)](https://travis-ci.org/uwplse/herbie)
Herbie synthesizes floating-point programs from real-number programs,
automatically handling simple numerical instabilities. Visit [our
website](https://herbie.uwplse.org) for tutorials, documentation, and
an online demo. Herbie has semi-regular releases twice a year,
maintains backwards compatibility, and uses standardized formats.
Installing
----------
For full details on installing Herbie, please see the
[tutorial](http://herbie.uwplse.org/doc/latest/installing.html).
Herbie requires Racket 6.7 or later, and supports Windows, OS X, and
Linux. Install it with:
raco pkg install herbie
This will install a `herbie` binary to somewhere in your home
directory. You can also run `src/herbie.rkt` directly instead of using
the `herbie` command, for example if you'd like to download the source
directly instead of through the package manager.
Running Herbie
--------------
For full details on running Herbie, please see the
[tutorial](http://herbie.uwplse.org/doc/latest/using-web.html).
Herbie's input is a Scheme-based language called [FPCore](http://fpbench.org/spec/fpcore-1.0.html);
you can several examples in `bench/`.
For example, consider this simple expression:
(FPCore (x)
(- (+ 1 x) x))
Run Herbie from the top-level directory of the repo, and enter the
cancellation test:
$ herbie shell
Herbie 1.2 with seed #(349461420 3681359142 2680361770 2900531005 1939065059 1779362427)
Find help on <https://herbie.uwplse.org/>, exit with Ctrl-D
herbie> (FPCore (x) (- (+ 1 x) x))
(FPCore (x) ... 1)
The output is Herbie's improved, more-accurate expression, in this case
the constant `1`.
Besides the `shell`, Herbie also has a `web` interface, and can run on
files of FPCore expressions with the `improve` and `report` commands.
Consult the
[documentation](http://herbie.uwplse.org/doc/latest/options.html).
for more.
Helping Out
-----------
Herbie development is organized on our
[mailing list](https://mailman.cs.washington.edu/mailman/listinfo/herbie)
where we discuss work in progress and announce major improvements.
[Email us](mailto:herbie@cs.washington.edu) to get involved!
We use [Github](https://github.com/uwplse/herbie)
and [Trello](https://trello.com/b/lh7b33Dr/herbie) to organize some
development goals.
Running Tests
-------------
Herbie contains unit tests to test basic functionality, though
coverage is far from complete. You can run the test suite with:
raco test src/
Herbie also contains a large integration suite from open source
projects, examples emailed to the developers, and from numerical
analysis textbooks. This suite is found in `bench/`. The full test can
be run with
herbie report bench/ graphs/
The output is an HTML report in `graphs/`. This full test can take
several hours to run. We often test Herbie on basic but representative
examples with:
herbie report bench/hamming/ graphs/
This takes approximately 15 minutes.
Historic and nightly test results are collected on
[uwplse.org](http://herbie.uwplse.org/reports/).
; -*- mode: scheme -*-
; Herbie cannot sample enough input points for these tests.
(FPCore (x)
:name "Random Jason Timeout Test 001"
(+ x (asin (cosh x))))
(FPCore (x y)
:name "Random Jason Timeout Test 009"
(fabs (fmod y (asin (- 2.821952756469356e+184 x)))))
(FPCore (a b c)
:pre (and (< 0 a) (< 0 b) (< 0 c))
:name "Area of a triangle"
(sqrt (* (* (* (/ (+ (+ a b) c) 2) (- (/ (+ (+ a b) c) 2) a))
(- (/ (+ (+ a b) c) 2) b))
(- (/ (+ (+ a b) c) 2) c))))
(FPCore (n U t l Om U*)
:name "Toniolo and Linder, Equation (13)"
(sqrt (* (* (* 2 n) U)
(- (- t (* 2 (/ (* l l) Om)))
(* (* n (pow (/ l Om) 2)) (- U U*))))))
; -*- mode: scheme -*-
; Herbie cannot evaluate these tests fast enough with MPFR.
; In contrast to challenge/timeout.fpcore, these tests do
; not finish sampling input points (sometimes varying with seed).
(FPCore (a b)
:name "Random Jason Timeout Test 003"
(sin (pow (sqrt (atan2 b b)) (- b a))))
(FPCore (a b)
:name "Random Jason Timeout Test 015"
(sin (pow (sqrt (atan2 b b)) (- b a))))
(FPCore (lo hi x)
:pre (and (< lo -1e308) (> hi 1e308))
(/ (- x lo) (- hi lo)))
; -*- mode: scheme -*-
; Herbie requires too much MPFR precision for these tests.
(FPCore (c)
:name "Random Jason Timeout Test 002"
(fmod (sinh c) (- c (pow -2.9807307601812193e+165 2))))
(FPCore (a c)
:name "Random Jason Timeout Test 004"
(fmod (cosh c) (log1p a)))
(FPCore (a)
:name "Random Jason Timeout Test 012"
(acos (pow (fmod (cosh a) (* a a)) (log1p a))))
(FPCore (c)
:name "Random Jason Timeout Test 014"
(fmod (sinh c) (- c (pow -2.9807307601812193e+165 2))))
; -*- mode: scheme -*-
; Herbie times out on these tests, but gets past sampling.
(FPCore (a)
:name "Random Jason Timeout Test 006"
(fabs (fmod (atan2 (expm1 (sin (expm1 a))) (atan a)) a)))
; -*- mode: scheme -*-
; TODO: exp function unimplemented.
#;(FPCore (xre xim)
:name "exp with complex power real part (p55)"
(let ([x (complex xre xim)])
(re (/ (+ (exp x) (exp (- x))) (complex 2 0)))))
#;(FPCore (xre xim)
:name "exp with complex power imaginary part (p55)"
(let ([x (complex xre xim)])
(im (/ (+ (exp x) (exp (- x))) (complex 2 0)))))
#;(FPCore (x y)
:name "Euler formula real part (p55)"
(let ([a (/ (+ (exp x) (exp (- x))) 2)]
[b (/ (- (exp x) (exp (- x))) 2)])
(re (complex (* a (cos y)) (* b (sin y))))))
#;(FPCore (x y)
:name "Euler formula imaginary part (p55)"
(let ([a (/ (+ (exp x) (exp (- x))) 2)]
[b (/ (- (exp x) (exp (- x))) 2)])
(im (complex (* a (cos y)) (* b (sin y))))))
(FPCore ()
:name "3.9.1 real part (p56)"
(let ([x (complex -1 1)])
(re (+ (* x x x x x x) (* (complex 6 0) x x x x x) (* (complex 15 0) x x x x) (* (complex 20 0) x x x) (* (complex 15 0) x x) (* (complex 6 0) x) (complex 1 0)))))
(FPCore ()
:name "3.9.1 imaginary part (p56)"
(let ([x (complex -1 1)])
(im (+ (* x x x x x x) (* (complex 6 0) x x x x x) (* (complex 15 0) x x x x) (* (complex 20 0) x x x) (* (complex 15 0) x x) (* (complex 6 0) x) (complex 1 0)))))
(FPCore ()
:name "3.9.2 real part (p56)"
(let ([x (complex (/ (- 1) 2) (/ (sqrt 3) 2))])
(re (+ (* x x x x) (* (complex (- 2) 0) x x x) (* (complex 5 0) x x) (* (complex 4 0) x) (complex 7 0)))))
(FPCore ()
:name "3.9.2 imaginary part (p56)"
(let ([x (complex (/ (- 1) 2) (/ (sqrt 3) 2))])
(im (+ (* x x x x) (* (complex (- 2) 0) x x x) (* (complex 5 0) x x) (* (complex 4 0) x) (complex 7 0)))))
; -*- mode: scheme -*-
(FPCore (a x)
:name "expax (section 3.5)"
:herbie-target
(if (< (fabs (* a x)) 1/10)
(* (* a x) (+ 1 (+ (/ (* a x) 2) (/ (pow (* a x) 2) 6))))
(- (exp (* a x)) 1))
(- (exp (* a x)) 1))
; -*- mode: scheme -*-
(FPCore (x)
:name "expq2 (section 3.11)"
:herbie-target
(/ 1 (- 1 (exp (- x))))
(/ (exp x) (- (exp x) 1)))
; -*- mode: scheme -*-
(FPCore (a b c)
:name "quadp (p42, positive)"
:herbie-target
(let ([d (sqrt (- (* b b) (* 4 (* a c))))])
(let ([r1 (/ (+ (- b) d) (* 2 a))]
[r2 (/ (- (- b) d) (* 2 a))])
(if (< b 0) r1 (/ c (* a r2)))))
(let ([d (sqrt (- (* b b) (* 4 (* a c))))])
(/ (+ (- b) d) (* 2 a))))
(FPCore (a b c)
:name "quadm (p42, negative)"
:herbie-target
(let ((d (sqrt (- (* b b) (* 4 (* a c))))))
(let ([r1 (/ (+ (- b) d) (* 2 a))] [r2 (/ (- (- b) d) (* 2 a))])
(if (< b 0) (/ c (* a r1)) r2)))
(let ([d (sqrt (- (* b b) (* 4 (* a c))))])
(/ (- (- b) d) (* 2 a))))
(FPCore (a b_2 c)
:name "quad2m (problem 3.2.1, negative)"
(let ([d (sqrt (- (* b_2 b_2) (* a c)))])
(/ (- (- b_2) d) a)))
(FPCore (a b_2 c)
:name "quad2p (problem 3.2.1, positive)"
(let ([d (sqrt (- (* b_2 b_2) (* a c)))])
(/ (+ (- b_2) d) a)))
; -*- mode: scheme -*-
(FPCore (x)
:name "2sqrt (example 3.1)"
:herbie-target
(/ 1 (+ (sqrt (+ x 1)) (sqrt x)))
(- (sqrt (+ x 1)) (sqrt x)))
(FPCore (x eps)
:name "2sin (example 3.3)"
:herbie-target
(* 2 (* (cos (+ x (/ eps 2))) (sin (/ eps 2))))
(- (sin (+ x eps)) (sin x)))
(FPCore (x)
:name "tanhf (example 3.4)"
:herbie-expected 2
:herbie-target
(tan (/ x 2))
(/ (- 1 (cos x)) (sin x)))
(FPCore (N)
:name "2atan (example 3.5)"
:herbie-target
(atan (/ 1 (+ 1 (* N (+ N 1)))))
(- (atan (+ N 1)) (atan N)))
(FPCore (x)
:name "2isqrt (example 3.6)"
:herbie-target
(/ 1 (+ (* (+ x 1) (sqrt x)) (* x (sqrt (+ x 1)))))
(- (/ 1 (sqrt x)) (/ 1 (sqrt (+ x 1)))))
(FPCore (x)
:name "2frac (problem 3.3.1)"
(- (/ 1 (+ x 1)) (/ 1 x)))
(FPCore (x eps)
:name "2tan (problem 3.3.2)"
:herbie-target
(/ (sin eps) (* (cos x) (cos (+ x eps))))
(- (tan (+ x eps)) (tan x)))
(FPCore (x)
:name "3frac (problem 3.3.3)"
:herbie-target
(/ 2 (* x (- (* x x) 1)))
(+ (- (/ 1 (+ x 1)) (/ 2 x)) (/ 1 (- x 1))))
(FPCore (x)
:name "2cbrt (problem 3.3.4)"
(- (cbrt (+ x 1)) (cbrt x)))
(FPCore (x eps)
:name "2cos (problem 3.3.5)"
(- (cos (+ x eps)) (cos x)))
(FPCore (N)
:name "2log (problem 3.3.6)"
(- (log (+ N 1)) (log N)))
(FPCore (x)
:name "exp2 (problem 3.3.7)"
:herbie-target
(* 4 (pow (sinh (/ x 2)) 2))
(+ (- (exp x) 2) (exp (- x))))
; -*- mode: scheme -*-
(FPCore (x)
:name "expm1 (example 3.7)"
:pre (< -0.00017 x)
:herbie-target
(* x (+ 1 (/ x 2) (/ (* x x) 6)))
(- (exp x) 1))
(FPCore (n)
:name "logs (example 3.8)"
:pre (> n 6.8e+15)
:herbie-target
(- (log (+ n 1)) (- (/ 1 (* 2 n)) (- (/ 1 (* 3 (* n n))) (/ 4 (pow n 3)))))
(- (* (+ n 1) (log (+ n 1))) (* n (log n)) 1))
(FPCore (x)
:name "invcot (example 3.9)"
:pre (and (< -0.026 x) (< x 0.026))
:herbie-target
(if (< (fabs x) 0.026)
(* (/ x 3) (+ 1 (/ (* x x) 15)))
(- (/ 1 x) (/ 1 (tan x))))
(- (/ 1 x) (/ 1 (tan x))))
(FPCore (x)
:name "qlog (example 3.10)"
:pre (and (< -1 x) (< x 1))
:herbie-target
(- (+ 1 x (/ (* x x) 2) (* 5/12 (pow x 3))))
(/ (log (- 1 x)) (log (+ 1 x))))
(FPCore (x)
:name "cos2 (problem 3.4.1)"
(/ (- 1 (cos x)) (* x x)))
(FPCore (a b eps)
:name "expq3 (problem 3.4.2)"
:pre (and (< -1 eps) (< eps 1))
:herbie-target
(/ (+ a b) (* a b))
(/
(* eps (- (exp (* (+ a b) eps)) 1))
(* (- (exp (* a eps)) 1) (- (exp (* b eps)) 1))))
(FPCore (eps)
:name "logq (problem 3.4.3)"
:herbie-target
(* -2 (+ eps (/ (pow eps 3) 3) (/ (pow eps 5) 5)))
(log (/ (- 1 eps) (+ 1 eps))))
(FPCore (x)
:name "sqrtexp (problem 3.4.4)"
(sqrt (/ (- (exp (* 2 x)) 1) (- (exp x) 1))))
(FPCore (x)
:name "sintan (problem 3.4.5)"
(/ (- x (sin x)) (- x (tan x))))
(FPCore (x n)
:name "2nthrt (problem 3.4.6)"
(- (pow (+ x 1) (/ 1 n)) (pow x (/ 1 n))))
This diff is collapsed.
; -*- mode: scheme -*-
(FPCore (d1 d2 d3)
:name "FastMath dist"
:herbie-target
(* d1 (+ d2 d3))
(+ (* d1 d2) (* d1 d3)))
(FPCore (d)
:name "FastMath test1"
:herbie-target
(* d 30)
(+ (* d 10) (* d 20)))
(FPCore (d1 d2)
:name "FastMath test2"
:herbie-target
(* d1 (+ 30 d2))
(+ (* d1 10) (* d1 d2) (* d1 20)))
(FPCore (d1 d2 d3)
:name "FastMath dist3"
:herbie-target
(* d1 (+ 37 d3 d2))
(+ (* d1 d2) (* (+ d3 5) d1) (* d1 32)))
(FPCore (d1 d2 d3 d4)
:name "FastMath dist4"
:herbie-target
(* d1 (- (+ (- d2 d3) d4) d1))
(- (+ (- (* d1 d2) (* d1 d3)) (* d4 d1)) (* d1 d1)))
(FPCore (d1 d2 d3)
:name "FastMath test3"
:herbie-target
(* d1 (+ 3 d2 d3))
(+ (* d1 3