ek_rnd Function

public function ek_rnd(x) result(y)

The rounding barrier: an identity that the optimiser may not fuse across.

The volatile local is the entire content of this procedure. Without it, ek_rnd(a * b) + c is just a * b + c -- the exact shape a compiler with FMA contracts, rounding once where IEEE rounds twice, which changes the result and moves the frozen fingerprint. volatile obliges the compiler to store x to memory and read it back, so the product is a rounded real64 by the time the add sees it, on every conforming compiler. Unlike a noinline directive this is not advice the optimiser may decline, which is why the procedure is written this way and not that way -- see exp_key's doc-comment for the flang build that made the difference concrete.

Do not make this pure (a pure procedure may not have a volatile local -- that restriction is what the directive form was working around), do not drop the volatile, and do not "simplify" the call sites back to bare arithmetic.

Public because a second module needs the same barrier for the same reason. parquet_random's polar normal composes sqrt and a division around exp_key, and those compositions are exposed to exactly the fusions and regroupings this closes -- so it imports this as ek_round. It is not part of the library's user-facing surface (parquet_expkey is not re-exported by the parquet facade, and every importer re-hides it), and it is not a general-purpose utility: it exists to hold ONE expression's grouping, and a caller reaching for it should be able to name the rewrite it is stopping.

Arguments

Type IntentOptional Attributes Name
real(kind=real64), intent(in) :: x

the product to round

Return Value real(kind=real64)

the same value, rounded to real64


Source Code

    function ek_rnd(x) result(y)
        real(real64), intent(in) :: x   !! the product to round
        real(real64) :: y               !! the same value, rounded to real64
        real(real64), volatile :: t     !! the barrier: forces a store and a reload

        t = x
        y = t
    end function ek_rnd