-
Notifications
You must be signed in to change notification settings - Fork 17.5k
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
proposal: math: MinOf and MaxOf for generic numeric limits #50019
Comments
To do this with any kind of efficiency in implementation code, generated code, and execution time seems unlikely. Plus you really want this to be a constant, which won't happen for a function. So this feels like the wrong approach to me, but the right approach might require some kind of language support if we are to avoid type-asserting from interface{} on the way out. |
P.S. That said, I'm not convinced it's worthwhile to do. I know what it's for but will it show up often enough to need so much mechanism? |
IMHO it's essential that somebody writes a crazy idea that everybody can reject. So here I go:
To be used like
|
In general we don't allow constants to be derived from type parameters (that way lies madness), but I think it could be done with reasonable efficiency if #45380 was implemented. In that case, the code might look like this:
I have a feeling it wouldn't take too smart a compiler to implement it as a direct lookup from the dictionary, so not as efficient as a constant (we don't allow constants based on type parameters anyway), but one indirection still isn't too bad. |
Did play around trying to get something similar, though just for constraints.Integer. With inlining they effectively a constant, though the inliner does assign them a higher inlining cost. https://gotipplay.golang.org/p/Hw4hnZq3imw Edit: Typo in code, should not have had the go vet warning. |
What I was getting at, incoherently, was that type parameters might not be the way to do this. The fact that a problem arises because of them does not necessarily mean the solution requires them too. |
What's being asked for here is the Go equivalent of the C++ |
This works for signed and unsigned integers:
|
I'm kind of new to golang, but this type of functionality seems like something that should be an included battery to a language standard library. Ultimately I guess the specifics are less important to me, but generic min/max functions make sense somewhere in the standard library. |
Note that this proposal is not about generic min/max functions. That is #59488. This proposal is about functions to return the minimum and maximum values of numeric types. |
Ah whelp.. sorry folks. |
I'm wondering a little bit about the use cases for this. Personally, I encountered this in one situation so far: A mathematical algorithm implemented as a generic function, which I wanted to test using a type-parametric helper that could also check some boundary cases. In other words: Nothing that really justifies a language change, but also nothing that requires a constant expression or anything efficient. For overflow checks, I prefer checking When asking on Slack, @justenwalker helped coming up with this, which is not a constant, but seems reasonably efficient: type Integer interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}
func Max[T Integer]() T {
if ^T(0) > 0 {
return ^T(0)
}
var v T
bits := 8 * unsafe.Sizeof(v)
return 1<<(bits-1) - 1
}
func Min[T Integer]() T {
if ^T(0) > 0 {
return 0
}
var v T
bits := 8 * unsafe.Sizeof(v)
return (^v) << (bits - 1)
} [edit] oh, sorry, just saw that @jdemeyer already posted something like this [/edit] |
Back in 2021 I wrote my use case in this comment. IMHO some algorithms seem to need boundary values to behave correctly (how would you implement
I feel like if |
You might be able to generalize the ideas from the integer function. For example, floats can be distinguished by I do agree that it's enough subtlety to justify doing it in the stdlib, anyways. i.e. I wouldn't expect anyone to be able to implement these correctly themselves. |
Currently when writing a function involving a generic numeric type, there's no easy way to determine the maximum or minimum possible value of that type, because the
math.Min*
andmath.Max*
constants are all type-specific.I propose that we add the following functions to the
math
package:It's currently not possible to write the above functions without using reflection until #45380
is fixed, but here's an approximation:
https://gotipplay.golang.org/p/0i3Wc7i4dJs
The text was updated successfully, but these errors were encountered: