TorchLean API

FloatLib.Floats.Formats.BinaryInterchange.Operations.Proof.RoundToIntegral

Integral-rounding contracts #

The unbounded dyadic-to-integer kernel is related to the usual nearest-even, floor, ceiling, and truncation semantics. The floating-point wrapper then records exactly when fractional bits were discarded and exposes the exceptional branches.

For IEEE encodings with fmt.fracWidth ≤ fmt.maxNormalExponent, the selected integer is exactly representable. This condition holds for the IEEE interchange formats. On finite inputs, roundToIntegral then denotes the floor, ceiling, truncation, or nearest-even integer selected by the rounding direction, and roundToIntegralExactWithStatus reports no overflow.

@[simp]

Exact zero rounds to integer zero in every direction.

Nearest-even integer rounding has its usual mathematical meaning, independently of the stored dyadic exponent or magnitude.

Rounding toward zero truncates the exact dyadic: nonnegative values use floor and negative values use ceiling.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.dyadicIsIntegral_ofNat (negative : Bool) (significand exponent : ) :
dyadicIsIntegral { negative := negative, significand := significand, exponent := Int.ofNat exponent } = true

A dyadic with a nonnegative exponent is already an integer.

@[simp]
theorem FloatLib.Floats.Formats.BinaryInterchange.Model.dyadicIsIntegral_zero (negative : Bool) (exponent : ) :
dyadicIsIntegral { negative := negative, significand := 0, exponent := exponent } = true

Dyadic zero is integral independently of its stored sign and exponent.

An exact dyadic is integral precisely when no negative binary exponent leaves a fractional bit.

For exponent -(shift + 1), this says that 2^(shift + 1) divides the significand. A nonnegative exponent is always integral.

@[simp]

roundToIntegral is exactly the value component of its status-bearing operation.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.roundToIntegralExactWithStatus_of_finite {fmt : FloatFormat} (value : Model fmt) (mode : IEEERoundingMode) (exact : Numerics.Dyadic) (hvalue : value.exactValue = ExactValue.finite exact) :
value.roundToIntegralExactWithStatus mode = have coefficient := roundDyadicToInt mode exact; have rounded := if (coefficient == 0) = true then zero fmt exact.negative else roundDyadicWithRounding fmt mode (Numerics.Dyadic.ofScaledInt coefficient 0); have encodingStatus := dyadicRoundingStatus fmt mode (Numerics.Dyadic.ofScaledInt coefficient 0) rounded; { value := rounded, status := { overflow := encodingStatus.overflow, inexact := !dyadicIsIntegral exact } }

On finite input, roundToIntegralExactWithStatus rounds the exact dyadic to an unbounded integer, then encodes that integer in the selected direction. The status records discarded fractional bits and the encoder's overflow classification.

On finite input, roundToIntegralExactWithStatus raises inexact exactly when a negative binary exponent leaves at least one fractional bit.

roundToIntegralExactWithStatus preserves either infinity and returns clear status.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.roundToIntegralExactWithStatus_of_nan {fmt : FloatFormat} (value : Model fmt) (mode : IEEERoundingMode) (negative signaling : Bool) (payload : ) (hvalue : value.exactValue = ExactValue.nan negative signaling payload) :
value.roundToIntegralExactWithStatus mode = { value := value.quietNaN, status := { invalid := signaling } }

roundToIntegralExactWithStatus quiets a NaN and raises invalid exactly when it was signaling.

Representability of the rounded integer #

Every rounding direction lands at or above the floor of the exact value.

Every rounding direction lands at or below the ceiling of the exact value.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.abs_roundDyadicToInt_le_two_pow_of_exponent_neg (mode : IEEERoundingMode) (value : Numerics.Dyadic) (fracWidth : ) (hsig : value.significand < 2 ^ (fracWidth + 1)) (hexp : value.exponent < 0) :
|roundDyadicToInt mode value| 2 ^ fracWidth

If the significand is below 2^(fracWidth + 1) and the binary exponent is negative, the rounded integer has magnitude at most 2^fracWidth.

On a finite input of an IEEE format whose exponent range reaches the precision, the result represents the selected integer exactly and reports no overflow. Fractional input can still set inexact.

Every IEEE interchange format satisfies fmt.fracWidth ≤ fmt.maxNormalExponent.

Integral rounding of a finite IEEE value never overflows when fmt.fracWidth ≤ fmt.maxNormalExponent.

Integral rounding of a finite IEEE value is finite when the exponent range reaches the precision.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.toReal_roundToIntegral {fmt : FloatFormat} (hfmt : fmt.isIEEE = true) (hrange : fmt.fracWidth fmt.maxNormalExponent) (value : Model fmt) (mode : IEEERoundingMode) (exact : Numerics.Dyadic) (hd : value.toDyadic? = some exact) :
(value.roundToIntegral mode).toReal = (roundDyadicToInt mode exact)

The real value of a finite integral rounding is the integer selected by roundDyadicToInt.

theorem FloatLib.Floats.Formats.BinaryInterchange.Model.exists_int_toReal_roundToIntegral {fmt : FloatFormat} (hfmt : fmt.isIEEE = true) (hrange : fmt.fracWidth fmt.maxNormalExponent) (value : Model fmt) (mode : IEEERoundingMode) (hfinite : value.isFinite = true) :
∃ (n : ), (value.roundToIntegral mode).toReal = n

The result of integral rounding is an integer.

Rounding toward negative infinity computes the floor of the real value.

Rounding toward positive infinity computes the ceiling of the real value.

Rounding toward zero truncates the real value: floor when nonnegative, ceiling otherwise.

Rounding to nearest computes the nearest integer with ties to even, nearestEven from the Flocq theory. Mathlib's round resolves ties toward positive infinity.