Skip to content

Commit

Permalink
Additional README notes
Browse files Browse the repository at this point in the history
  • Loading branch information
ulfjack committed Jul 7, 2019
1 parent e610692 commit 4de75fb
Showing 1 changed file with 83 additions and 81 deletions.
164 changes: 83 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ posed by White and Steele [1], for which they described an algorithm called
"Dragon". It was subsequently improved upon with algorithms that also had
dragon-themed names. I followed in the same vein using the japanese word for
dragon, Ryu. In general, all these algorithms should produce identical output
given identical input.
given identical input, and this is checked when running the benchmark program.

The C implementation of Ryu is in the ryu/ directory. The Java implementations
are RyuFloat and RyuDouble under src/main/java/. Both cover 32 and 64-bit
Expand Down Expand Up @@ -88,7 +88,18 @@ implementations, printf provides three floating-point specific formatters,

Ryu Printf implements %f and %e formatting in a way that should be drop-in
compatible with most implementations of printf, although it currently does not
implement any formatting flags other than precision.
implement any formatting flags other than precision. The benchmark program
verifies that the output matches exactly, and outputs a warning if not. Any
unexpected output from the benchmark indicates a difference in output.

*Note* that old versions of MSVC ship with a printf implementation that has a
confirmed bug: it does not always round the last digit correctly.

*Note* that msys cuts off the output after ~17 digits, and therefore generally
differs from Ryu Printf output for precision values larger than 17.

*Note* that the output for NaN values can differ between implementations; we use
ifdefs in an attempt to match platform output.

According to our benchmarks, Ryu Printf compares favorably with the following
implementations of printf for precision parameters 1, 10, 100, and 1000:
Expand Down Expand Up @@ -124,6 +135,13 @@ To build Ryu Printf, run
$ bazel build //ryu:ryu_printf
```

### Big-Endian Architectures
The C implementation of Ryu should work on big-endian architectures provided
that the floating point type and the corresponding integer type use the same
endianness.

There are no concerns around endianness for the Java implementation.

### Building with a Custom Compiler
You can select a custom C++ compiler by setting the CC environment variable
(e.g., on Ubuntu, run `export CC=clang-3.9`).
Expand All @@ -145,9 +163,69 @@ You can run both C and Java tests with
$ bazel test //ryu/... //src/...
```

### Benchmarks

#### Ryu

## Ryu: Additional Notes

### Jaffer
The code given by Jaffer in the original paper does not come with a license
declaration. Instead, we're using code found on GitHub, which contains a
license declaration by Jaffer. Compared to the original code, this
implementation no longer outputs incorrect values for negative numbers.

We provide a binary to find differences between Ryu and the Jaffer / Jdk
implementations:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:FindDifferences --
```

Add the `-mode=csv` option to get all the discovered differences as a CSV. Use
`-mode=latex` instead to get a latex snippet of the first 20. Use
`-mode=summary` to only print the number of discovered differences (this is the
default mode).

### Computing Required Lookup Table Sizes
You can compute the required lookup table sizes with:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ComputeTableSizes --
```

Add `-v` to get slightly more verbose output.

### Computing Required Bit Sizes
You can compute the required bit sizes with:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ComputeRequiredBitSizes --
```

Add the `-128` and `-256` flags to also cover 128- and 256-bit numbers. This
could take a while - 128-bit takes ~20 seconds on my machine while 256-bit takes
a few hours. Add `-v` to get very verbose output.

### Java: Comparing All Possible 32-bit Values Exhaustively
You can check the slow vs. the fast implementation for all 32-bit floating point
numbers using:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ExhaustiveFloatComparison
```

This takes ~60 hours to run to completion on an
Intel(R) Core(TM) i7-4770K with 3.50GHz.

### Java: Comparing All Possible 64-bit Values Exhaustively
You can check the slow vs. the fast implementation for all 64-bit floating point
numbers using:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ExtensiveDoubleComparison
```

This takes approximately forever, so you will need to interrupt the program.



## Benchmarks

### Ryu
We provide both C and Java benchmark programs.

Enable optimization by adding "-c opt" on the command line:
Expand Down Expand Up @@ -184,7 +262,7 @@ $ bazel build -c opt --jobs=1 //scripts:shortest-{c,java}-{float,double}.pdf

The resulting files are `bazel-genfiles/scripts/shortest-{c,java}-{float,double}.pdf`.

#### Ryu Printf
### Ryu Printf
We provide a C++ benchmark program that runs against the implementation of
```snprintf``` bundled with the selected C++ compiler. You need to enable
optimization using "-c opt" on the command line:
Expand Down Expand Up @@ -221,79 +299,3 @@ with:
```
$ bazel build -c opt --jobs=1 //scripts:{f,e}-c-double-{1,10,100,1000}.pdf
```


### Ryu: Comparison with Other Implementations

#### Grisu3

Ryu's output should exactly match Grisu3's output. Our benchmark verifies that
the generated numbers are identical.
```
$ bazel run -c opt //ryu/benchmark -- -64
Average & Stddev Ryu Average & Stddev Grisu3
64: 29.806 3.182 103.060 98.717
```

#### Jaffer's Implementation
The code given by Jaffer in the original paper does not come with a license
declaration. Instead, we're using code found on GitHub, which contains a
license declaration by Jaffer. Compared to the original code, this
implementation no longer outputs incorrect values for negative numbers.

#### Differences between Ryu and Jaffer / Jdk implementations
We provide a binary to find differences between Ryu and the Jaffer / Jdk
implementations:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:FindDifferences --
```

Add the `-mode=csv` option to get all the discovered differences as a CSV. Use
`-mode=latex` instead to get a latex snippet of the first 20. Use
`-mode=summary` to only print the number of discovered differences (this is the
default mode).

### Big-Endian Architectures
The C implementation of Ryu should work on big-endian architectures provided
that the floating point type and the corresponding integer type use the same
endianness.

There are no concerns around endianness for the Java implementation.

### Computing Required Lookup Table Sizes
You can compute the required lookup table sizes with:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ComputeTableSizes --
```

Add `-v` to get slightly more verbose output.

### Computing Required Bit Sizes
You can compute the required bit sizes with:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ComputeRequiredBitSizes --
```

Add the `-128` and `-256` flags to also cover 128- and 256-bit numbers. This
could take a while - 128-bit takes ~20 seconds on my machine while 256-bit takes
a few hours. Add `-v` to get very verbose output.

### Java: Comparing All Possible 32-bit Values Exhaustively
You can check the slow vs. the fast implementation for all 32-bit floating point
numbers using:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ExhaustiveFloatComparison
```

This takes ~60 hours to run to completion on an
Intel(R) Core(TM) i7-4770K with 3.50GHz.

### Java: Comparing All Possible 64-bit Values Exhaustively
You can check the slow vs. the fast implementation for all 64-bit floating point
numbers using:
```
$ bazel run //src/main/java/info/adams/ryu/analysis:ExtensiveDoubleComparison
```

This takes approximately forever, so you will need to interrupt the program.

0 comments on commit 4de75fb

Please sign in to comment.