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

math: math.Log returns incorrect result #9546

Closed
ALTree opened this issue Jan 9, 2015 · 12 comments
Closed

math: math.Log returns incorrect result #9546

ALTree opened this issue Jan 9, 2015 · 12 comments
Milestone

Comments

@ALTree
Copy link
Member

ALTree commented Jan 9, 2015

Related to #8909 and #9545

math.Log(0.6023203277884887)
// go gives    :  -0.5069658692305488
// c and python:  -0.5069658692305486
// real value  :  -0.50696586923054861438656...

http://play.golang.org/p/BPuEBjA0Ip

@minux
Copy link
Member

minux commented Jan 9, 2015

something is definitely wrong here, the algorithm used by math.Log is
claimed to have <1ulp accuracy.

@StefanSchroeder
Copy link

I cannot reproduce this problem with Go 1.2.1 on linux/386, with Go 1.3.3 on linux/386 or Go 1.4.1 on linux/386. I dont know what platform the playground is running on, but it might be specific to that platform.

@ALTree
Copy link
Member Author

ALTree commented Jan 16, 2015

On 386 we use the FPU FYL2X instruction (see https://github.com/golang/go/blob/master/src/math/log_386.s), that's why it's precise. The issue affects every other platform.

@mavricknz
Copy link

What is the reason not to use FPU FYL2X on AMD64? Quick test and it looks ok (I'm certainly not an expert on ASM usage).

Ah it's about 50% slower.

@ALTree
Copy link
Member Author

ALTree commented Jan 21, 2015

By "quick test" you mean that you actually implemented Log with FYL2X, compiled it on amd64 with the go assembler, and it was fine? If yes, could you please share the code? Because I was under the assumption that the instruction set go uses for amd64 (sse2) didn't have a log instruction, and that FPU instructions couldn't be used on amd64 with the go assembler (I think I read that somewhere).

@minux
Copy link
Member

minux commented Jan 21, 2015

Your impression is incorrect. It's definitely ok to use FPU instructions
on amd64 with Go's assembler (SSE2 doesn't have log instruction, this
is right.)

try using this to replace the content of $GOROOT/src/math/log_amd64.s:
// func Log(x float64) float64
TEXT ·Log(SB),NOSPLIT,$0
FLDLN2 // F0=log(2)
FMOVD x+0(FP), F0 // F0=x, F1=log(2)
FYL2X // F0=log(x)=log2(x)*log(2)
FMOVDP F0, ret+8(FP)
RET

Curiously, my benchmark doesn't show any change for this change, so
we probably can use this patch to fix the issue.

However, I've confirmed that something is wrong with the Go implementation
(which claim to have <1ulp accuracy) too, and the inaccuracy for amd64 is
not due to incorrect translation from Go code to assembly.

@minux
Copy link
Member

minux commented Jan 22, 2015

The original code (which is the origin of our code and comment) from
fdlibm also have this problem. (http://www.netlib.org/fdlibm/e_log.c)

got: -0.50696586923054876017 // __ieee754_log from fdlibm
exp: -0.50696586923054864915 // glibc result

I've also verified that msun code from FreeBSD also has this problem.

Test code:
https://github.com/minux/gobugs/tree/master/issue9546_math.Log_accuracy

@minux
Copy link
Member

minux commented Jan 22, 2015

I did a little survey of various ways to compute correct math.Log,

glibc uses multiple-precision floats in the worst case,

http://dl.acm.org/citation.cfm?id=98267.98294 proposes a method
that uses only normal precision floats, but needs 2KB of lookup table.

https://github.com/JuliaLang/openlibm contains an implementation
of the table-lookup algorithm from paper and it seems to work.

Suggestions?

@minux minux added this to the Go1.5 milestone Jan 22, 2015
@ALTree
Copy link
Member Author

ALTree commented Jan 22, 2015

There are currently at least three or four open issues related to floating-point accuracy of various math functions (#8909 is the oldest one). Most of them are not 100% accurate. I think we should once and for all decide what we expect from the mathematical functions in the standard library: maximum accuracy (i.e. error < 1ulp)? Maximum speed? A good compromise between accuracy and speed?

Maybe this should be discussed on golang-dev.

@minux
Copy link
Member

minux commented Jan 22, 2015

I agree. Let's raise this topic on golang-dev.

@minux
Copy link
Member

minux commented Jan 26, 2015

@ALTree
Copy link
Member Author

ALTree commented Apr 11, 2015

Invalid (see rsc comment on #9545)

@ALTree ALTree closed this as completed Apr 11, 2015
@golang golang locked and limited conversation to collaborators Jun 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants