I also posted a CSR draft: https://bugs.openjdk.org/browse/JDK-8301301
On Fri, Jan 27, 2023 at 11:46 AM Tagir Valeev <amae...@gmail.com> wrote: > > Hello, all! > > Thank you for an interesting discussion. As I see some interest > towards this feature, I've created a new issue to track this: > https://bugs.openjdk.org/browse/JDK-8301226 > I haven't found an exact duplicate, only an issue with related > discussion JDK-4466549. Feel free to link duplicates if you can search > JIRA better than me :-) > > On Thu, Jan 26, 2023 at 12:47 AM John Rose <john.r.r...@oracle.com> wrote: > > > > Dealing with numeric ranges is error-prone, so I welcome these. > > > > Another operation on ranges is membership. This is easy to derive > > from the clamp methods, I think: > > > > checkRange(x,min,max) := clamp(x,min,max) == x > > checkRange relates somehow to the methods we have in > java.util.Objects, namely checkFromIndexSize, checkIndex, etc. Though > these methods are throwing an exception, rather than returning false. > This could be considered as a separate enhancement. > > > But I think there is no harm and real benefit from widening > > the value parameters, so value is always either long or double. > > That will save casts (which also cause bugs) for some use > > cases, such as doing 32x32-to-64-bit arithmetic followed > > by overflow checks and/or saturation. That’s a common use > > case for clamping. > > > > public static int clamp(long value, int min, int max) > > public static long clamp(long value, long min, long max) > > public static double clamp(double value, double min, double max) > > public static float clamp(double value, float min, float max) > > I really like the idea of int clamp(long value, int min, int max), as > this makes the method much more useful. On the other hand, I have > doubles about > float clamp(double value, float min, float max), as it could be called > accidentally and we will have accidental precision loss. E.g., imagine > the following code: > > // bounds are declared as floats for some reason > // this usually doesn't matter, as these numbers are exact in float > and in double > float lower = 0.0f; > float upper = 10.0f; > > double v = 1/3.; > System.out.println(v); > v = Math.clamp(v, lower, upper); // oops! > System.out.println(v); > > Having float clamp(double, float, float), this method will be linked > here, resulting in accidental precision loss. The output is: > 0.3333333333333333 > 0.3333333432674408 > > Given that float type is rarely used, I'd stick to the following signatures: > public static int clamp(long value, int min, int max) > public static long clamp(long value, long min, long max) > public static double clamp(double value, double min, double max) > public static float clamp(float value, float min, float max) > > > I thought about cross-domain clamps, which preserve 64 bit > > precision and double range at the same time in different places: > > > > public static long clamp(long value, double min, double max) > > public static long clamp(double value, long min, long max) > > This is even more dangerous, as simply calling > double value = ... > value = clamp(value, 0, 1); // not 0.0 and 1.0 > you will get 0 instead of the original value that fits the range. > I imagine that many people will step on this. If these methods are desired, > it would be better to name them differently, to avoid overload ambiguity. > For now, I would avoid this. > > > The subexpression max-min never overflows, when it > > is regarded as an unsigned number, and the “>>>1” > > immediately converts that unsigned number into the > > correctly signed positive number. That’s the only > > way to avoid overflow for all inputs. The third > > idiom above (the “smartest” of the three) will fail, > > for example, if you feed it negative values. > > For some uses that is OK, but for others it isn’t. > > > > public static int midpoint(int min, int max) > > public static long midpoint(long min, long max) > > public static double midpoint(double min, double max) > > public static float midpoint(float min, float max) > > midpoint is another great idea, I like it! Could also be considered > separately. > > With best regards, > Tagir Valeev.