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

trivially replacing division with multiplication still sometimes useful #41657

Closed
seebs opened this issue Sep 27, 2020 · 4 comments
Closed

trivially replacing division with multiplication still sometimes useful #41657

seebs opened this issue Sep 27, 2020 · 4 comments

Comments

@seebs
Copy link
Contributor

seebs commented Sep 27, 2020

What version of Go are you using (go version)?

$ go version
1.15

Does this issue reproduce with the latest release?

y

What operating system and processor architecture are you using (go env)?

x86

What did you do?

divided by a constant

What did you expect to see?

multiplication by its reciprocal

What did you see instead?

cycles. so many cycles.

https://play.golang.org/p/vW3TLeBm4KP

On a laptop:
BenchmarkMul-8 127098 9497 ns/op
BenchmarkDiv-8 106873 11400 ns/op

That's a pretty huge speedup for such a trivial code change.

@seebs
Copy link
Contributor Author

seebs commented Sep 27, 2020

(Side note: I'm not sure that's theoretically safe, because there could exist inputs for which the result isn't the same, but I've never actually found one of them.)

@seebs
Copy link
Contributor Author

seebs commented Sep 27, 2020

... and someone just pointed out that this rule is already there for reciprocalExact(c) values, so possibly I just happened to hit a case where it wasn't exact. I'm not going to close this in case there's a nuance I missed, but if that's already working-as-intended, feel free to close it.

@seebs
Copy link
Contributor Author

seebs commented Sep 27, 2020

Actually, thinking about it more: I believe there exist values such that reciprocalExact(c) is false, but where there's no input float32 value for which multiplication by the reciprocal produces a different result from division by the original value. Hmm. (... no wait, there almost certainly aren't. yay for math.)

@randall77
Copy link
Contributor

Yes, I think this is unlikely to ever work. Closing

func main() {
	for _, d := range []float64{3, 5, 7, 9, 30} {
		r := 1 / d
		for _, x := range []float64{3, 5, 6, 7, 9} {
			if x*r != x/d {
				fmt.Printf("%v %v %v %v\n", d, x, x*r, x/d)
			}
		}
	}
}

Produces

3 5 1.6666666666666665 1.6666666666666667
3 7 2.333333333333333 2.3333333333333335
5 3 0.6000000000000001 0.6
5 6 1.2000000000000002 1.2
5 7 1.4000000000000001 1.4
7 5 0.7142857142857142 0.7142857142857143
7 9 1.2857142857142856 1.2857142857142858
9 7 0.7777777777777777 0.7777777777777778

@golang golang locked and limited conversation to collaborators Sep 27, 2021
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

3 participants