On Fri, 28 Feb 2025 21:46:13 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

>> That's absolutely true, however this can change quickly when large values 
>> are added or subtracted to/from small values, or when division or 
>> multiplication gets involved.  So I'd say its relatively safe to do simple 
>> calculations with near snapped values, but one must be careful with 
>> functions like `ceil` and `floor` as they can amplify tiny floating-point 
>> errors due to their discontinuous nature.  For example, if take a snapped 
>> `spacing` and add a snapped `left` and `right` margin, then call ceil on the 
>> result, it could go like this:
>> 
>>              1.99999999999999 +
>>              4.00000000000001 +
>>              4.00000000000001 =
>>             10.00000000000001 -> ceil -> 11 (instead of the expected 10)
>
> good point!
> 
> This is exactly the reason for the code in ScaledMath:71
> 
> return Math.ceil(d - Math.ulp(d)) / scale;

Come to think of it, most the issues here are caused by using functions like 
`floor` and `ceil`.  It might be an idea to change these functions to bias them 
slightly towards rounding to the closest value, instead of always doing a 
straight up `floor` or `ceil`.

For example, let's say I calculate a size as `3.0000001`; ceiling this (with 
snapSize) to `4` is quite ridiculous; obviously `3` was intended, but the 
ceiling function won't care.  But what if we subtracted a value (assuming we're 
dealing with pixels of course, which the `snap` functions are)? We could bias 
it slightly towards the correct value by using something ridiculously small 
like 1/10000th of a pixel. For example:

`3.0000001` - 1/10000th of a pixel = `2.9999`. Ceiling this value yields the 
intended `3`.  We could work much safer with near snapped values, as there is 
much less risk of a one ulp difference being dramatically amplified by 
floor/ceil functions.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1723#discussion_r1976045508

Reply via email to