https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63269
Bug ID: 63269 Summary: libgo/math test failures in TestLog2 Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: go Assignee: ian at airs dot com Reporter: vogt at linux dot vnet.ibm.com CC: cmang at google dot com There are several flaws in the math library test code. On s390x, the test TestLog2 fails for three reasons: 1) This part of the test is too strict for i == 0: for i := -1074; i <= 1023; i++ { f := Ldexp(1, i) l := Log2(f) if l != float64(i) { t.Errorf("Log2(2**%d) = %g, want %d", i, l, i) } } It should really use the veryclose function() as there is no guarantee that the result of this calculation from log10.go is exact: return Log(frac)*(1/Ln2) + float64(exp) With frac == 0.5 and exp == 1, the result may be just close to 0, not exactly zero: * If the compiler generated two instructions, one to mulitply and one to add, the result is (with a small error delta): Product: Log(0.5)*(1/Ln2) = -1 + delta -> rounded to -1 Sum: -1 + 1 = 0 -> rounded to 0 Result: 0 * If the compiler generates a single multiply and add instruction, only the final result is rouced, i.e. Product: Log(0.5)*(1/Ln2) = -1 + delta (not rounded) Sum: -1 + delta + 1 = delta -> rounded to delta' Result: delta' != 0 So, the fix is to use the "veryclose" error tolerance. 2) There's a bug in the tolerance() function: if a != 0 { e = e * a if e < 0 { e = -e } } This snippet uses the defective value a but should use the expected value b instead: if b != 0 { e = e * b if e < 0 { e = -e } } Otherwise, bad things happen for an expected value 0 when the defective value is very close, i.e. they never match. 3) The alike() function does allow an error tolerance. This kicks in on s390x in the case that the expected value is 0 and the defective value is not identical. switch { case IsNaN(a) && IsNaN(b): return true case a == b: return Signbit(a) == Signbit(b) } A possible fix would be to detect this one situation and return true, and rely on more specific tests to chack that the error is small ebough. switch { case IsNaN(a) && IsNaN(b): return true case a == 0 && !IsNaN(b) && !IsInf(b, 0): // allow deviations when the expected value is zero return true case a == b: return Signbit(a) == Signbit(b) }