Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scientific floats #398

Merged
merged 20 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9781df5
Update bril grammar to allow "from" as an identifier
Pat-Lafon Feb 7, 2025
9ba1380
uncomment and add to float_special
Pat-Lafon Feb 7, 2025
4652e19
Update brili to use exponential with exponents greater than 10
Pat-Lafon Feb 7, 2025
80c7ea6
Update brilirs to use exponential notation (with + fix) for exponents…
Pat-Lafon Feb 7, 2025
8716c29
Tear hair out until I switch to only using libc's printf for all prin…
Pat-Lafon Feb 7, 2025
106302b
Have brilift check for absolute exponent greater than or equal to 10
Pat-Lafon Feb 7, 2025
d57e962
Address clippy lint
Pat-Lafon Feb 7, 2025
a54cee9
Use just total magnitude instead to avoid log10
Pat-Lafon Feb 7, 2025
6e7b900
Add check for zero
Pat-Lafon Feb 7, 2025
388acd7
Add diff so I can see what's wrong
Pat-Lafon Feb 7, 2025
aa2b56a
Add more parenthesis?
Pat-Lafon Feb 7, 2025
147c8d2
update rt.rs because that's the thing that actually gets used in -j
Pat-Lafon Feb 7, 2025
d6746c6
Remove the -diff flag used in debugging
Pat-Lafon Feb 7, 2025
382fa4b
Relocate random_walk to mixed as it uses the char extension and exclu…
Pat-Lafon Feb 7, 2025
63fb9d5
Add the diff flag because #iworksonmymachineithink
Pat-Lafon Feb 7, 2025
da1730f
Specify exponential floats to 6 significant digits
Pat-Lafon Feb 9, 2025
58a9d62
Exclude random_walk from brillvm
Pat-Lafon Feb 9, 2025
a4f818e
Add documentation for switching to exponential notation when printing…
Pat-Lafon Feb 9, 2025
6b15e95
Update to use 17 decimal points of precision in all cases
Pat-Lafon Feb 10, 2025
e5d9ff0
Simplify the float printing docs a little bit
sampsyo Feb 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions benchmarks/float/exponentiation-by-squaring.out
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
3.083945934529577e+53
1.422023440989732e+137
3.08394593452957709e+53
1.42202344098973190e+137
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions bril-rs/bril2json/src/bril_grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ Ident: String = {
<s : IDENT_TOKEN> => s.to_string(),
"true" => "true".to_owned(),
"false" => "false".to_owned(),
"from" => "from".to_owned(),
}

Args: ParsingArgs = {
Expand Down
4 changes: 2 additions & 2 deletions bril-rs/brillvm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ TESTS := ../../test/interp/core/*.bril \
../../test/interp/float/*.bril \
../../test/interp/ssa/*.bril \
../../test/interp/mem/*.bril \
../../test/interp/mixed/*[^r].bril # A hack to exclude store-char.bril by excluding any file ending in r.bril
../../test/interp/mixed/*[!r].bril # A hack to exclude store-char.bril by excluding any file ending in r.bril

BENCHMARKS := ../../benchmarks/core/*.bril \
../../benchmarks/float/*.bril \
../../benchmarks/mem/*.bril \
../../benchmarks/mixed/*.bril
../../benchmarks/mixed/*[!k].bril # a hack to exclude random_walk.bril because it uses the char extension

build:
cargo build
Expand Down
4 changes: 2 additions & 2 deletions bril-rs/brillvm/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libc-print = "0.1"
libc = { version = "0.2", default-features = false }

# To properly set up the rt library for linking with LLVM
[profile.dev]
Expand All @@ -15,4 +15,4 @@ lto = true

[profile.release]
panic = "abort"
lto = true
lto = true
41 changes: 28 additions & 13 deletions bril-rs/brillvm/runtime/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,60 @@ use std::mem::size_of; */

use core::ffi::{c_char, CStr};

use libc_print::std_name::{print, println};

#[no_mangle]
pub extern "C" fn _bril_print_int(i: i64) {
print!("{}", i);
unsafe {
libc::printf(c"%lld".as_ptr().cast(), i);
}
}

#[no_mangle]
pub extern "C" fn _bril_print_bool(b: bool) {
if b {
print!("true")
} else {
print!("false")
let c_str = if b { c"true" } else { c"false" };
unsafe {
libc::printf(c_str.as_ptr().cast());
}
}

#[no_mangle]
pub extern "C" fn _bril_print_float(f: f64) {
if f.is_infinite() {
if f.is_sign_negative() {
print!("-Infinity");
unsafe {
libc::printf(c"-Infinity".as_ptr().cast());
}
} else {
print!("Infinity");
unsafe {
libc::printf(c"Infinity".as_ptr().cast());
}
}
} else if f.is_nan() {
print!("NaN");
unsafe {
libc::printf(c"NaN".as_ptr().cast());
}
} else if f != 0.0 && (f.abs() >= 1E10 || f.abs() <= 1E-10) {
unsafe {
libc::printf(c"%.17e".as_ptr().cast(), f);
}
} else {
print!("{:.17}", f);
unsafe {
libc::printf(c"%.17lf".as_ptr().cast(), f);
}
}
}

#[no_mangle]
pub extern "C" fn _bril_print_sep() {
print!(" ");
unsafe {
libc::printf(c" ".as_ptr().cast());
}
}

#[no_mangle]
pub extern "C" fn _bril_print_end() {
println!();
unsafe {
libc::printf(c"\n".as_ptr().cast());
}
}

#[no_mangle]
Expand Down
8 changes: 6 additions & 2 deletions brili.ts
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,12 @@ function evalInstr(instr: bril.Instruction, state: State): Action {
let args = instr.args || [];
let values = args.map(function (i) {
let val = get(state.env, i);
if (Object.is(-0, val)) { return "-0.00000000000000000" };
if (typeof val == "number") { return val.toFixed(17) } else {return val.toString()}}
if (typeof val == "number") {
if ( Object.is(-0.0, val)) { return "-" + val.toFixed(17) }
else if (val != 0.0 && Math.abs(Math.log10(Math.abs(val))) >= 10) { return val.toExponential(17) }
else { return val.toFixed(17) }
}
else {return val.toString()}}
);
console.log(...values);
return NEXT;
Expand Down
4 changes: 2 additions & 2 deletions brilift/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Brilift only supports core Bril for now, so we select those tests &
# benchmarks.
TESTS := ../test/interp/core/*.bril ../test/interp/float/*.bril ../test/interp/mem/*.bril ../test/interp/mixed/*[!r].bril # A hack to exclude store-char.bril by excluding any file ending in r.bril
BENCHMARKS := ../benchmarks/core/*.bril ../benchmarks/float/*.bril ../benchmarks/mem/*.bril ../benchmarks/mixed/*.bril
BENCHMARKS := ../benchmarks/core/*.bril ../benchmarks/float/*.bril ../benchmarks/mem/*.bril ../benchmarks/mixed/*[!k].bril # A hack to exclude random_walk.bril because it uses the char extension

CFLAGS := $(if $(TARGET),-target $(TARGET))
BRILFLAGS := $(if $(TARGET),-t $(TARGET))
Expand All @@ -23,7 +23,7 @@ test: rt.o release

.PHONY: benchmark
benchmark: rt.o release
turnt -e brilift-aot -e brilift-jit $(TURNTARGS) $(BENCHMARKS)
turnt --diff -e brilift-aot -e brilift-jit $(TURNTARGS) $(BENCHMARKS)

rt.o: rt.c
cc $(CFLAGS) -c -o $@ $^
Expand Down
2 changes: 2 additions & 0 deletions brilift/rt.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ void _bril_print_float(double f) {
} else {
printf("Infinity");
}
} else if ((f != 0.0) && ((fabs(f) >= 1E10) || (fabs(f) <= 1E-10))) {
printf("%.17e", f);
} else {
printf("%.17lf", f);
}
Expand Down
4 changes: 4 additions & 0 deletions brilift/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ pub extern "C" fn print_float(f: f64) {
} else {
print!("Infinity");
}
} else if f != 0.0 && f.abs().log10() >= 10.0 {
print!("{}", format!("{f:.17e}").replace('e', "e+").as_str());
} else if f != 0.0 && f.abs().log10() <= -10.0 {
print!("{f:.17e}");
} else {
print!("{f:.17}");
}
Expand Down
10 changes: 10 additions & 0 deletions brilirs/src/interp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ impl fmt::Display for Value {
Self::Bool(b) => write!(f, "{b}"),
Self::Float(v) if v.is_infinite() && v.is_sign_positive() => write!(f, "Infinity"),
Self::Float(v) if v.is_infinite() && v.is_sign_negative() => write!(f, "-Infinity"),
Self::Float(v) if v != &0.0 && v.abs().log10() >= 10.0 => {
f.write_str(format!("{v:.17e}").replace('e', "e+").as_str())
}
Self::Float(v) if v != &0.0 && v.abs().log10() <= -10.0 => write!(f, "{v:.17e}"),
Self::Float(v) => write!(f, "{v:.17}"),
Self::Char(c) => write!(f, "{c}"),
Self::Pointer(p) => write!(f, "{p:?}"),
Expand All @@ -213,6 +217,12 @@ fn optimized_val_output<T: std::io::Write>(out: &mut T, val: &Value) -> Result<(
Value::Float(f) if f.is_infinite() && f.is_sign_positive() => out.write_all(b"Infinity"),
Value::Float(f) if f.is_infinite() && f.is_sign_negative() => out.write_all(b"-Infinity"),
Value::Float(f) if f.is_nan() => out.write_all(b"NaN"),
Value::Float(f) if f != &0.0 && f.abs().log10() >= 10.0 => {
out.write_all(format!("{f:.17e}").replace('e', "e+").as_bytes())
}
Value::Float(f) if f != &0.0 && f.abs().log10() <= -10.0 => {
out.write_all(format!("{f:.17e}").as_bytes())
}
Value::Float(f) => out.write_all(format!("{f:.17}").as_bytes()),
Value::Char(c) => {
let buf = &mut [0_u8; 2];
Expand Down
4 changes: 3 additions & 1 deletion docs/lang/float.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Printing
--------

The [core `print` operation](./core.md#miscellaneous) prints `float` values with 17 decimal digits of precision, including trailing zeros.
(This is like using the `%.17lf` format specifier in C's `printf`.)
For values with magnitude 10¹⁰, it uses exponential notation with suffixes like `e+12`.
(In terms of C's `printf`, this is like using the `%.17lf` format specifier for small values and `%.17e` for large values, i.e., when `f.abs().log10().abs >= 10`.)

Positive and negative zero, while they are equal according to `feq`, look different when printed.
Not-a-number values are printed as `NaN`; infinite values are printed as the strings `Infinity` or `-Infinity`.
22 changes: 14 additions & 8 deletions test/interp/float/float_special.bril
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
print v0;
print v1;
print res;
# v2: float = const 1e6;
# v3: float = const 1E-6;
# v4: float = const -1E+6;
# v5: float = const +.11e12;
# print v2;
# print v3;
# print v4;
# print v5;
v2: float = const 1e6;
v3: float = const 1E-6;
v4: float = const -1E+6;
v5: float = const +.11e12;
print v2;
print v3;
print v4;
print v5;
v6: float = const 1e21;
v7: float = const 1e-21;
print v6;
print v7;
v8: float = const 1e5;
print v8;
}
7 changes: 7 additions & 0 deletions test/interp/float/float_special.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
0.00000000000000000
-0.00000000000000000
true
1000000.00000000000000000
0.00000100000000000
-1000000.00000000000000000
1.10000000000000000e+11
1.00000000000000000e+21
9.99999999999999908e-22
100000.00000000000000000
Loading