Math.clamp method?
Tagir Valeev
amaembo at gmail.com
Sat Jan 28 16:20:59 UTC 2023
I also posted a CSR draft:
https://bugs.openjdk.org/browse/JDK-8301301
On Fri, Jan 27, 2023 at 11:46 AM Tagir Valeev <amaembo at 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.rose at 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.
More information about the core-libs-dev
mailing list