Solution (source code)

= Solution

Under exact <integer arithmetic>, the intended result is \b[$\lceil\log_2 x\rceil$], using the <ceiling function>. A sufficient <loop invariant> is
$$
i\geq0,\qquad y=2^i,\qquad i=0\ \lor\ 2^{i-1}<x.
$$
Initially $i=0,y=1$, and the final disjunction is true. If the guard holds, the old value $y=2^i$ is below $x$. Incrementing `i` and doubling `y` therefore preserves $y=2^i$ and makes the new lower bound $2^{i-1}<x$ true. At exit $y\geq x$. If $i=0$, positivity of $x$ forces $x=1$; otherwise $2^{i-1}<x\leq2^i$. Both cases establish the claimed <postcondition>. Doubling eventually reaches or exceeds any fixed positive $x$, proving <algorithm termination> in this arithmetic model. This is the <doubling-loop ceiling logarithm> argument.

\b[The printed Scala implementation is not correct for its entire stated `Int` domain.] Its `y` is an `Int`. For $x>2^{30}$, it reaches $y=2^{30}$, wraps to $-2^{31}$ on the next doubling, then becomes zero and stays zero. The guard remains true forever. The <loop invariant> above is valid for the printed code only when $1\leq x\leq2^{30}$. Scala documents `Int` as a signed 32-bit value equivalent to Java's primitive `int`.<Scala Int API documentation>[Scala 2.13.16, class Int: signed 32-bit representation]{ref}

A corrected implementation for every positive `Int` input widens the doubling variable before any multiplication:

``
def ceilingLog2(x: Int): Int = {
  require(x > 0)
  var i = 0
  var y = 1L
  while (y < x.toLong) {
    i += 1
    y *= 2L
  }
  i
}
``

Now at most 31 iterations are needed and $y\leq2^{31}$, safely within `Long`. The same <loop invariant> proves <total correctness> without the overflow gap.