From 56e4ed1e6b50ee0f95775251bc03d30b005473ae Mon Sep 17 00:00:00 2001 From: hazohelet <48541090+hazohelet@users.noreply.github.com> Date: Wed, 2 Oct 2019 04:38:36 +0900 Subject: [PATCH] compiler: float comparison uses machine epsilon by default --- compiler/parser.v | 13 ++++++-- vlib/builtin/int.v | 73 +++++++++++++++++++++++++++++++++++++++++ vlib/builtin/int_test.v | 21 ++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/compiler/parser.v b/compiler/parser.v index 8922621b4e..47fd80e6a9 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -1540,7 +1540,7 @@ fn (p mut Parser) bterm() string { // if tok in [ .eq, .gt, .lt, .le, .ge, .ne] { if tok == .eq || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne { p.fgen(' ${p.tok.str()} ') - if ((is_float && tok == .eq) || (is_str || is_ustr)) && !p.is_js { + if (is_float || is_str || is_ustr) && !p.is_js { p.gen(',') } else if p.is_sql && tok == .eq { @@ -1594,9 +1594,16 @@ fn (p mut Parser) bterm() string { case Token.lt: p.cgen.set_placeholder(ph, 'ustring_lt(') } } - if is_float && tok == .eq { + if is_float { p.gen(')') - p.cgen.set_placeholder(ph, '${expr_type}_eq(') + switch tok { + case Token.eq: p.cgen.set_placeholder(ph, '${expr_type}_eq(') + case Token.ne: p.cgen.set_placeholder(ph, '${expr_type}_ne(') + case Token.le: p.cgen.set_placeholder(ph, '${expr_type}_le(') + case Token.ge: p.cgen.set_placeholder(ph, '${expr_type}_ge(') + case Token.gt: p.cgen.set_placeholder(ph, '${expr_type}_gt(') + case Token.lt: p.cgen.set_placeholder(ph, '${expr_type}_lt(') + } } } return typ diff --git a/vlib/builtin/int.v b/vlib/builtin/int.v index c8774bc41e..545c06db30 100644 --- a/vlib/builtin/int.v +++ b/vlib/builtin/int.v @@ -26,6 +26,7 @@ pub fn ptr_str(ptr voidptr) string { } // compare floats using C epsilon +// == pub fn (a f64) eq(b f64) bool { return C.fabs(a - b) <= C.DBL_EPSILON } @@ -39,6 +40,78 @@ pub fn (a f32) eqbit(b f32) bool { return C.DEFAULT_EQUAL(a, b) } +// != +fn (a f64) ne(b f64) bool { + return !a.eq(b) +} +fn (a f32) ne(b f32) bool { + return !a.eq(b) +} +pub fn (a f64) nebit(b f64) bool { + return C.DEFAULT_NOT_EQUAL(a, b) +} +pub fn (a f32) nebit(b f32) bool { + return C.DEFAULT_NOT_EQUAL(a, b) +} + +// a < b +fn (a f64) lt(b f64) bool { + return a.ne(b) && a.ltbit(b) +} +fn (a f32) lt(b f32) bool { + return a.ne(b) && a.ltbit(b) +} +fn (a f64) ltbit(b f64) bool { + return C.DEFAULT_LT(a, b) +} +fn (a f32) ltbit(b f32) bool { + return C.DEFAULT_LT(a, b) +} + +// a <= b +fn (a f64) le(b f64) bool { + return !a.gt(b) +} +fn (a f32) le(b f32) bool { + return !a.gt(b) +} +fn (a f64) lebit(b f64) bool { + return C.DEFAULT_LE(a, b) +} +fn (a f32) lebit(b f32) bool { + return C.DEFAULT_LE(a, b) +} + +// a > b +fn (a f64) gt(b f64) bool { + return a.ne(b) && a.gtbit(b) +} +fn (a f32) gt(b f32) bool { + return a.ne(b) && a.gtbit(b) +} +fn (a f64) gtbit(b f64) bool { + return C.DEFAULT_GT(a, b) +} +fn (a f32) gtbit(b f32) bool { + return C.DEFAULT_GT(a, b) +} + +// a >= b +fn (a f64) ge(b f64) bool { + return !a.lt(b) +} +fn (a f32) ge(b f32) bool { + return !a.lt(b) +} +fn (a f64) gebit(b f64) bool { + return C.DEFAULT_GE(a, b) +} +fn (a f32) gebit(b f32) bool { + return C.DEFAULT_GE(a, b) +} + + + // fn (nn i32) str() string { // return i // } diff --git a/vlib/builtin/int_test.v b/vlib/builtin/int_test.v index 0a2389c1e6..7f266d35c8 100644 --- a/vlib/builtin/int_test.v +++ b/vlib/builtin/int_test.v @@ -17,12 +17,33 @@ fn test_float_equal_operator() { a -= 0.000001 assert a == 1 assert !a.eqbit(1) + assert !(a != 1) + assert a.nebit(1) + a += 0.000001 + assert !(a < 1) + assert !a.ltbit(1) + assert !(a <= 1) + assert !a.lebit(1) + assert a > 1 + assert a.gtbit(1) + assert a >= 1 + assert a.gebit(1) a = f64(1) a += 0.000001 a -= 0.000001 assert a == 1 assert !a.eqbit(1) + assert !(a != 1) + a += 0.000001 + assert !(a < 1) + assert !a.ltbit(1) + assert !(a <= 1) + assert !a.lebit(1) + assert a > 1 + assert a.gtbit(1) + assert a >= 1 + assert a.gebit(1) } fn test_str_methods() {