compiler: float comparison uses machine epsilon by default

pull/2204/head
hazohelet 2019-10-02 04:38:36 +09:00 committed by Alexander Medvednikov
parent f35f6083cd
commit 56e4ed1e6b
3 changed files with 104 additions and 3 deletions

View File

@ -1540,7 +1540,7 @@ fn (p mut Parser) bterm() string {
// if tok in [ .eq, .gt, .lt, .le, .ge, .ne] { // if tok in [ .eq, .gt, .lt, .le, .ge, .ne] {
if tok == .eq || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne { if tok == .eq || tok == .gt || tok == .lt || tok == .le || tok == .ge || tok == .ne {
p.fgen(' ${p.tok.str()} ') 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(',') p.gen(',')
} }
else if p.is_sql && tok == .eq { 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(') case Token.lt: p.cgen.set_placeholder(ph, 'ustring_lt(')
} }
} }
if is_float && tok == .eq { if is_float {
p.gen(')') 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 return typ

View File

@ -26,6 +26,7 @@ pub fn ptr_str(ptr voidptr) string {
} }
// compare floats using C epsilon // compare floats using C epsilon
// ==
pub fn (a f64) eq(b f64) bool { pub fn (a f64) eq(b f64) bool {
return C.fabs(a - b) <= C.DBL_EPSILON 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) 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 { // fn (nn i32) str() string {
// return i // return i
// } // }

View File

@ -17,12 +17,33 @@ fn test_float_equal_operator() {
a -= 0.000001 a -= 0.000001
assert a == 1 assert a == 1
assert !a.eqbit(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 = f64(1)
a += 0.000001 a += 0.000001
a -= 0.000001 a -= 0.000001
assert a == 1 assert a == 1
assert !a.eqbit(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() { fn test_str_methods() {