On Thu, 17 Oct 2024 12:59:37 GMT, fabioromano1 <d...@openjdk.org> wrote:

>> The comments are OK. However, there seems to be no explicit relation between 
>> the "running" vars used in the reasoning and the expected outcome.
>> 
>> To clarify what I mean, let v0, z0 and s0 be the initial values at method 
>> entry of intVal, z and scale, resp.
>> At the exit of the method, the following is supposed to hold by contract:
>> 
>> v0 = intVal * 10^z0, s0 = scale + z0.
>> 
>> At least to me, this is not apparent from the comments.
>
>> The comments are OK. However, there seems to be no explicit relation between 
>> the "running" vars used in the reasoning and the expected outcome.
>> 
>> To clarify what I mean, let v0, z0 and s0 be the initial values at method 
>> entry of intVal, z and scale, resp. At the exit of the method, the following 
>> is supposed to hold by contract:
>> 
>> v0 = intVal * 10^z0, s0 = scale + z0.
>> 
>> At least to me, this is not apparent from the comments.
> 
> @rgiulietti Starting from the facts `min(scale - preferredScale, powsOf2) >= 
> remainingZeros` and `remainingZeros >= 2^i`, if `intVal % 5^(2^i) == 0`, then 
> `(intVal * 2^powsOf2) % 10^(2^i) == 0`, so dividing `intVal` by `5^(2^i)` is 
> legit (in the sense that we don't remove powers of 2 and we don't reduce the 
> scale more than allowed) and exactly mimics the division `(intVal * 
> 2^powsOf2) / 10^(2^i)` subtracting `2^i` from `powsOf2`. This allows to 
> reduce the initial problem to the new values of the "running" vars after an 
> iteration. So, I don't see the reason why it should not be apparent from the 
> comments onestly...

OK, let me reformulate the reasoning to check that we are in sync.
For simplicity, I'm assuming that the powers of 2 are _not_ stripped away, so 
I'm using powers of 10 rather than powers of 5. Adding the powers of 2 
optimization to the reasoning is then straightforward.

As above, let v0, z0 and s0 be the initial values at method entry of intVal, z 
and scale, resp.
We need to return intVal = v0 / 10^z0, scale = s0 - z0.

Let sexp be the running sum of all exponents exp inside both loops that lead to 
zero remainders in the division intVal / 10^exp.
It should be easy to see that both "then" branches maintain

z = z0 - sexp, intVal = v0 / 10^sexp, scale = s0 - sexp

and that both branches in both loops maintain

remainingZeros >= z

When the 2nd loop exits, remainingZeros = 0, so z = 0. This means z0 = sexp, 
intVal = v0 / 10^z0, scale = s0 - z0 (correctness).

In addition, both loops exit for the reasons in the comments (termination) and 
both loops require very few iterations (quality of service).

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

PR Review Comment: https://git.openjdk.org/jdk/pull/21323#discussion_r1804899523

Reply via email to