diff --git a/dprint.json b/dprint.json index 911baad8b..5ac574797 100644 --- a/dprint.json +++ b/dprint.json @@ -12,7 +12,13 @@ "exts": ["vi"] }] }, - "excludes": ["tests/programs/fail", "tests/programs/repl", "tests/programs/fmt", "tests/snaps"], + "excludes": [ + "tests/programs/fail", + "tests/programs/repl", + "tests/programs/fmt", + "tests/snaps", + "tests/programs/floats.vi" + ], "plugins": [ "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", "https://plugins.dprint.dev/json-0.19.3.wasm", diff --git a/ivy/src/host/ext.rs b/ivy/src/host/ext.rs index c1e4371b8..050caa201 100644 --- a/ivy/src/host/ext.rs +++ b/ivy/src/host/ext.rs @@ -70,6 +70,7 @@ impl<'ivm> Host<'ivm> { "f32_mul" => |a, b| new_f32(as_f32(a).mul(as_f32(b))), "f32_div" => |a, b| new_f32(as_f32(a).div(as_f32(b))), "f32_rem" => |a, b| new_f32(as_f32(a).rem_euclid(as_f32(b))), + "f32_sqrt" => |a, _b| new_f32(as_f32(a).sqrt()), "f32_eq" => |a, b| new_bool(as_f32(a) == as_f32(b)), "f32_ne" => |a, b| new_bool(as_f32(a) != as_f32(b)), diff --git a/tests/programs/floats.vi b/tests/programs/floats.vi new file mode 100644 index 000000000..08a92739a --- /dev/null +++ b/tests/programs/floats.vi @@ -0,0 +1,46 @@ +// FIX(#110): formatting is currently disabled in dprint.json to keep the comments in this file. +// Enable formatting again once #110 is fixed. +pub fn main(&io: &IO) { + let interesting_floats = [ + // 1) Specials / domain errors + +0.0, + -0.0, + -42.0, + F32::inf, + F32::neg_inf, + F32::nan, + F32::from_bits(0x7FC0_0001), // quiet NaN w/ payload + // 2) Subnormals & very small positives + F32::from_bits(0x0000_0001), // smallest subnormal + F32::from_bits(0x0000_0002), + F32::from_bits(0x0040_0000), + F32::from_bits(0x007F_FFFF), // largest subnormal + F32::from_bits(0x0080_0000), // FLT_MIN (smallest normal) + // 3) Around 1.0 (cancellation-sensitive) + 1.0, + F32::from_bits(0x3F7F_FFFF), + F32::from_bits(0x3F80_0001), + F32::from_bits(0x3F7F_FFFE), // cspell:disable-line + F32::from_bits(0x3F80_0002), + // 4) Nice reference values + 0.5, + 2.0, + 2.7182817, // e (rounded in F32) + 3.1415927, // π (rounded in F32) + // 5) Range extremes & powers of two + F32::from_bits(0x3080_0000), // 2^-30 + F32::from_bits(0x4E80_0000), // 2^30 + F32::from_bits(0x0100_0000), // FLT_MIN * 2 + F32::from_bits(0x7EFF_FFFF), // FLT_MAX / 2 + F32::from_bits(0x7F7F_FFFF), // FLT_MAX + 1.0e-10, + 1.0e10, + ]; + + for f in interesting_floats.into_iter() { + io.println("f = {f}"); + io.println("ln(f) = {f.ln()}"); + io.println("sqrt(f) = {f.sqrt()}"); + io.println(""); + } +} diff --git a/tests/programs/repl/f32_misc.vi b/tests/programs/repl/f32_misc.vi deleted file mode 100644 index 19028643b..000000000 --- a/tests/programs/repl/f32_misc.vi +++ /dev/null @@ -1,33 +0,0 @@ -// 1) Specials / domain errors -+0.0.ln() --0.0.ln() --42.0.ln() -F32::inf.ln() -F32::neg_inf.ln() -F32::nan.ln() -F32::from_bits(0x7FC0_0001).ln() // quiet NaN w/ payload -// 2) Subnormals & very small positives -F32::from_bits(0x0000_0001).ln() // smallest subnormal -F32::from_bits(0x0000_0002).ln() -F32::from_bits(0x0040_0000).ln() -F32::from_bits(0x007F_FFFF).ln() // largest subnormal -F32::from_bits(0x0080_0000).ln() // FLT_MIN (smallest normal) -// 3) Around 1.0 (cancellation-sensitive) -1.0.ln() -F32::from_bits(0x3F7F_FFFF).ln() -F32::from_bits(0x3F80_0001).ln() -F32::from_bits(0x3F7F_FFFE).ln() // cspell:disable-line -F32::from_bits(0x3F80_0002).ln() -// 4) Nice reference values -0.5.ln() -2.0.ln() -2.7182817.ln() // e (rounded in F32) -3.1415927.ln() // π (rounded in F32) -// 5) Range extremes & powers of two -F32::from_bits(0x3080_0000).ln() // 2^-30 -F32::from_bits(0x4E80_0000).ln() // 2^30 -F32::from_bits(0x0100_0000).ln() // FLT_MIN * 2 -F32::from_bits(0x7EFF_FFFF).ln() // FLT_MAX / 2 -F32::from_bits(0x7F7F_FFFF).ln() // FLT_MAX -1.0e-10.ln() -1.0e10.ln() diff --git a/tests/programs/repl/f32_to_string.vi b/tests/programs/repl/f32_to_string.vi deleted file mode 100644 index d9ced49a4..000000000 --- a/tests/programs/repl/f32_to_string.vi +++ /dev/null @@ -1,12 +0,0 @@ -"{1.0}" -"{1.2345}" -"{6.283185}" -"{123.0/456.0}" -"{456.0/123.0}" -"{0.0/0.0}" -"{1.0/0.0}" -"{-1.0/0.0}" -"{0.0}" -"{-0.0}" -"{12345.0*67890.0}" -"{1.0/(12345.0*67890.0)}" diff --git a/tests/snaps/vine/floats/output.txt b/tests/snaps/vine/floats/output.txt new file mode 100644 index 000000000..b3001b5d7 --- /dev/null +++ b/tests/snaps/vine/floats/output.txt @@ -0,0 +1,112 @@ +f = +0.0 +ln(f) = -inf +sqrt(f) = +0.0 + +f = -0.0 +ln(f) = -inf +sqrt(f) = -0.0 + +f = -42.00000 +ln(f) = NaN +sqrt(f) = NaN + +f = +inf +ln(f) = +inf +sqrt(f) = +inf + +f = -inf +ln(f) = NaN +sqrt(f) = NaN + +f = NaN +ln(f) = NaN +sqrt(f) = NaN + +f = NaN +ln(f) = NaN +sqrt(f) = NaN + +f = +1.40129e-45 +ln(f) = -103.27893 +sqrt(f) = +3.74339e-23 + +f = +2.80259e-45 +ln(f) = -102.58578 +sqrt(f) = +5.29395e-23 + +f = +5.87747e-39 +ln(f) = -88.02969 +sqrt(f) = +7.66646e-20 + +f = +1.17549e-38 +ln(f) = -87.33654 +sqrt(f) = +1.08420e-19 + +f = +1.17549e-38 +ln(f) = -87.33654 +sqrt(f) = +1.08420e-19 + +f = +1.00000 +ln(f) = +0.0 +sqrt(f) = +1.00000 + +f = +0.00000 +ln(f) = -5.96046e-8 +sqrt(f) = +0.00000 + +f = +1.00000 +ln(f) = +1.19209e-7 +sqrt(f) = +1.00000 + +f = +0.99999 +ln(f) = -1.19209e-7 +sqrt(f) = +0.00000 + +f = +1.00000 +ln(f) = +2.38418e-7 +sqrt(f) = +1.00000 + +f = +0.50000 +ln(f) = -0.69314 +sqrt(f) = +0.70710 + +f = +2.00000 +ln(f) = +0.69314 +sqrt(f) = +1.41421 + +f = +2.71828 +ln(f) = +1.00000 +sqrt(f) = +1.64872 + +f = +3.14159 +ln(f) = +1.14472 +sqrt(f) = +1.77245 + +f = +9.31322e-10 +ln(f) = -20.79441 +sqrt(f) = +0.00003 + +f = +1.07374e+9 +ln(f) = +20.79441 +sqrt(f) = +32768.00000 + +f = +2.35098e-38 +ln(f) = -86.64339 +sqrt(f) = +1.53329e-19 + +f = +1.70141e+38 +ln(f) = +88.02969 +sqrt(f) = +1.30438e+19 + +f = +3.40282e+38 +ln(f) = +88.72283 +sqrt(f) = +1.84467e+19 + +f = +9.99999e-11 +ln(f) = -23.02585 +sqrt(f) = +0.00001 + +f = +1.00000e+10 +ln(f) = +23.02585 +sqrt(f) = +100000.00000 + diff --git a/tests/snaps/vine/floats/stats.txt b/tests/snaps/vine/floats/stats.txt new file mode 100644 index 000000000..d327efeb5 --- /dev/null +++ b/tests/snaps/vine/floats/stats.txt @@ -0,0 +1,17 @@ + +Interactions + Total 44_162 + Depth 1_878 + Breadth 23 + Annihilate 17_194 + Commute 0 + Copy 4_690 + Erase 4_270 + Expand 3_627 + Call 10_865 + Branch 3_516 + +Memory + Heap 52_944 B + Allocated 861_872 B + Freed 861_872 B diff --git a/tests/snaps/vine/repl/f32_misc.repl.vi b/tests/snaps/vine/repl/f32_misc.repl.vi deleted file mode 100644 index cce17cc16..000000000 --- a/tests/snaps/vine/repl/f32_misc.repl.vi +++ /dev/null @@ -1,129 +0,0 @@ - -let io: IO = #io; -> // 1) Specials / domain errors - -let io: IO = #io; -> +0.0.ln() --inf - -let io: IO = #io; -> -0.0.ln() --inf - -let io: IO = #io; -> -42.0.ln() -NaN - -let io: IO = #io; -> F32::inf.ln() -::std::numeric::F32::inf - -let io: IO = #io; -> F32::neg_inf.ln() -NaN - -let io: IO = #io; -> F32::nan.ln() -::std::numeric::F32::nan - -let io: IO = #io; -> F32::from_bits(0x7FC0_0001).ln() // quiet NaN w/ payload -NaN - -let io: IO = #io; -> // 2) Subnormals & very small positives - -let io: IO = #io; -> F32::from_bits(0x0000_0001).ln() // smallest subnormal --103.27893 - -let io: IO = #io; -> F32::from_bits(0x0000_0002).ln() --102.585785 - -let io: IO = #io; -> F32::from_bits(0x0040_0000).ln() --88.02969 - -let io: IO = #io; -> F32::from_bits(0x007F_FFFF).ln() // largest subnormal --87.33655 - -let io: IO = #io; -> F32::from_bits(0x0080_0000).ln() // FLT_MIN (smallest normal) --87.33655 - -let io: IO = #io; -> // 3) Around 1.0 (cancellation-sensitive) - -let io: IO = #io; -> 1.0.ln() -0.0 - -let io: IO = #io; -> F32::from_bits(0x3F7F_FFFF).ln() --5.9604645e-8 - -let io: IO = #io; -> F32::from_bits(0x3F80_0001).ln() -1.1920928e-7 - -let io: IO = #io; -> F32::from_bits(0x3F7F_FFFE).ln() // cspell:disable-line --1.192093e-7 - -let io: IO = #io; -> F32::from_bits(0x3F80_0002).ln() -2.3841855e-7 - -let io: IO = #io; -> // 4) Nice reference values - -let io: IO = #io; -> 0.5.ln() --0.6931472 - -let io: IO = #io; -> 2.0.ln() -0.6931472 - -let io: IO = #io; -> 2.7182817.ln() // e (rounded in F32) -1.0 - -let io: IO = #io; -> 3.1415927.ln() // π (rounded in F32) -1.1447299 - -let io: IO = #io; -> // 5) Range extremes & powers of two - -let io: IO = #io; -> F32::from_bits(0x3080_0000).ln() // 2^-30 --20.794415 - -let io: IO = #io; -> F32::from_bits(0x4E80_0000).ln() // 2^30 -20.794415 - -let io: IO = #io; -> F32::from_bits(0x0100_0000).ln() // FLT_MIN * 2 --86.643394 - -let io: IO = #io; -> F32::from_bits(0x7EFF_FFFF).ln() // FLT_MAX / 2 -88.02969 - -let io: IO = #io; -> F32::from_bits(0x7F7F_FFFF).ln() // FLT_MAX -88.72284 - -let io: IO = #io; -> 1.0e-10.ln() --23.02585 - -let io: IO = #io; -> 1.0e10.ln() -23.02585 - -let io: IO = #io; diff --git a/tests/snaps/vine/repl/f32_to_string.repl.vi b/tests/snaps/vine/repl/f32_to_string.repl.vi deleted file mode 100644 index ba318f547..000000000 --- a/tests/snaps/vine/repl/f32_to_string.repl.vi +++ /dev/null @@ -1,50 +0,0 @@ - -let io: IO = #io; -> "{1.0}" -"+1.00000" - -let io: IO = #io; -> "{1.2345}" -"+1.23450" - -let io: IO = #io; -> "{6.283185}" -"+6.28318" - -let io: IO = #io; -> "{123.0/456.0}" -"+0.26973" - -let io: IO = #io; -> "{456.0/123.0}" -"+3.70731" - -let io: IO = #io; -> "{0.0/0.0}" -"NaN" - -let io: IO = #io; -> "{1.0/0.0}" -"+inf" - -let io: IO = #io; -> "{-1.0/0.0}" -"-inf" - -let io: IO = #io; -> "{0.0}" -"+0.0" - -let io: IO = #io; -> "{-0.0}" -"-0.0" - -let io: IO = #io; -> "{12345.0*67890.0}" -"+8.38102e+8" - -let io: IO = #io; -> "{1.0/(12345.0*67890.0)}" -"+1.19317e-9" - -let io: IO = #io; diff --git a/tests/tests.rs b/tests/tests.rs index e53ce5ca4..e13b6fc45 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -57,6 +57,7 @@ fn tests(t: &mut DynTester) { test_vi(t, "tests/programs/cyclist.vi", b"", ".txt", true); test_vi(t, "tests/programs/final_countdown.vi", b"", ".txt", true); test_vi(t, "tests/programs/find_primes.vi", b"", ".txt", true); + test_vi(t, "tests/programs/floats.vi", b"", ".txt", true); test_vi(t, "tests/programs/centimanes.vi", b"", ".txt", true); test_vi(t, "tests/programs/inverse.vi", b"", ".txt", true); test_vi(t, "tests/programs/lambda.vi", lambda_input, ".txt", true); @@ -105,8 +106,6 @@ fn tests(t: &mut DynTester) { t.group("repl", |t| { test_vi_repl(t, "tests/programs/repl/advanced_repl.vi"); test_vi_repl(t, "tests/programs/repl/basic_repl.vi"); - test_vi_repl(t, "tests/programs/repl/f32_to_string.vi"); - test_vi_repl(t, "tests/programs/repl/f32_misc.vi"); test_vi_repl(t, "tests/programs/repl/i32_misc.vi"); test_vi_repl(t, "tests/programs/repl/misc.vi"); test_vi_repl(t, "tests/programs/repl/objects.vi"); diff --git a/vine/std/numeric/F32.vi b/vine/std/numeric/F32.vi index 27d7d9a92..6d886bdbe 100644 --- a/vine/std/numeric/F32.vi +++ b/vine/std/numeric/F32.vi @@ -59,6 +59,10 @@ pub mod F32 { } } + pub fn .sqrt(f: F32) -> F32 { + inline_ivy! (f <- f) -> F32 { out f = @f32_sqrt(0 out) } + } + pub impl neg: Neg[F32, F32] { fn neg(a: F32) -> F32 { inline_ivy! (a <- a) -> F32 { out a = @f32_sub$(-0.0 out) }