Skip to main content

Fixed

Struct Fixed 

Source
pub struct Fixed(/* private fields */);
Expand description

A fixed-point number: Q47.16 in an i64.

§Contract

  • Resolution 2⁻¹⁶ ≈ 0.0000153; range ±2⁴⁷ ≈ ±1.4 × 10¹⁴.
  • Every operation saturates on overflow, in every build profile, and increments the thread’s crate::saturations counter when it does. Never wraps. Never differs between debug and release.
  • Multiplication and division round to nearest, ties away from zero. Symmetric under negation, which the obvious implementation is not — see Fixed::saturating_mul.
  • Total ordering. Ord, Eq and Hash are derived from the i64, so this sorts, deduplicates and hashes the way an integer does and floats cannot.

§Why Q47.16 and not Q32.32

Because physics squares things. A squared value has to fit the type it is stored in, so the range that matters is not what is representable but what is squarable — the square root of the representable range:

representablesquarable
Q47.16±1.4 × 10¹⁴±1.2 × 10⁷
Q32.32±2.1 × 10⁹±4.6 × 10⁴

Two hundred and fifty-six times the working room, for a resolution that is already finer than anything a game perceives.

Implementations§

Source§

impl Fixed

Source

pub const ZERO: Self

Zero.

Source

pub const ONE: Self

One whole unit.

Source

pub const MIN: Self

The smallest representable value.

Source

pub const MAX: Self

The largest representable value.

Source

pub const EPSILON: Self

The smallest step between two values: 2⁻¹⁶.

Source

pub const fn from_bits(raw: i64) -> Self

The raw Q47.16 pattern, for serialisation and tests.

Source

pub const fn to_bits(self) -> i64

The raw pattern back out.

Source

pub const fn from_int(value: i32) -> Self

A whole number, exactly.

i32 rather than i64 so the shift cannot overflow: every i32 shifted left by 16 fits an i64 with room to spare, which makes this total and lets it be const.

Source

pub const fn from_ratio(numerator: i32, denominator: i32) -> Self

A ratio of two integers — how a value like 9.81 is written without a float ever existing: Fixed::from_ratio(981, 100).

Rounds to nearest, ties away from zero, like Fixed::saturating_mul.

§Panics

If denominator is zero. A contract violation rather than a runtime condition (D5): the arguments are almost always literals, so this fails at the call site that wrote it, and in a const context it fails at compile time.

Source

pub const fn trunc_int(self) -> i64

The whole part, truncated toward zero.

Source

pub const fn fract(self) -> Self

The fractional part, with the sign of the whole.

Source

pub fn abs(self) -> Self

Absolute value, saturating at Fixed::MAX for Fixed::MIN.

Source

pub const fn signum(self) -> Self

-1, 0 or 1, as whole units.

Source

pub const fn min(self, other: Self) -> Self

The smaller of two values.

Source

pub const fn max(self, other: Self) -> Self

The larger of two values.

Source

pub const fn clamp(self, low: Self, high: Self) -> Self

Constrained to [low, high].

§Panics

If low > high, which is a contract violation rather than a value to interpret — the caller has said something they cannot mean.

Source

pub fn saturating_mul(self, other: Self) -> Self

Multiply, rounding to nearest with ties away from zero.

The rounding rule is load-bearing. The obvious implementation — (a as i128 * b as i128) >> 16 — is an arithmetic shift, which rounds toward negative infinity and is therefore asymmetric under negation: (-a) * b and -(a * b) differ for some inputs. That is deterministic and still wrong for physics, because a body moving left and the same body moving right would accumulate different error. Rounding to nearest with ties away from zero is symmetric, and halves the worst-case error besides.

Saturates rather than wrapping, and counts when it does.

Source

pub fn saturating_div(self, other: Self) -> Self

Divide, rounding to nearest with ties away from zero.

§Panics

If other is zero. Division by zero is a contract violation (D5), and returning a sentinel would put a NaN-shaped value into a type whose whole contract is that it has none.

Source

pub fn sqrt(self) -> Self

The square root, floored to the representable value below the exact result.

Uses u128::isqrt, which is exact by its own contract, on a u128 intermediate — the shifted value needs 79 bits, so a 64-bit one would be wrong rather than merely slower. Not a hand-rolled iteration: the standard library’s is boring and already correct, and this is the one kernel here with a non-trivial correctness argument.

§Panics

If self is negative. See Fixed::checked_sqrt for the form that answers instead of refusing.

Source

pub fn checked_sqrt(self) -> Option<Self>

The square root, or None for a negative value.

Source

pub const fn checked_add(self, other: Self) -> Option<Self>

Add, or None if the result would not fit.

Source

pub const fn checked_sub(self, other: Self) -> Option<Self>

Subtract, or None if the result would not fit.

Source

pub const fn checked_div(self, other: Self) -> Option<Self>

Divide, or None for a zero divisor or a result that would not fit.

The form to reach for wherever a divisor comes from data rather than from a literal — a ray direction, a difference of two positions, a time of impact. Fixed::saturating_div asserts on zero because a literal zero divisor is a programming error; a computed zero is an ordinary value that geometry produces constantly, and asserting on it would put a panic on a path that runs every frame.

Source

pub const fn checked_mul(self, other: Self) -> Option<Self>

Multiply, or None if the result would not fit.

const, and therefore not counted: a compile-time context has no thread to count on, and a caller asking this question wants the answer rather than a diagnostic.

Source§

impl Fixed

Source

pub const fn wide_mul(self, other: Self) -> Wide

Multiply without narrowing, so nothing can overflow.

The form to reach for when the product is itself going to be squared, summed with other products, or only compared — which covers most of what collision detection does with a multiply.

Trait Implementations§

Source§

impl Add for Fixed

Source§

type Output = Fixed

The resulting type after applying the + operator.
Source§

fn add(self, other: Self) -> Self

Performs the + operation. Read more
Source§

impl Clone for Fixed

Source§

fn clone(&self) -> Fixed

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Fixed

Source§

impl Debug for Fixed

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Fixed

Source§

fn default() -> Fixed

Returns the “default value” for a type. Read more
Source§

impl Div for Fixed

Source§

type Output = Fixed

The resulting type after applying the / operator.
Source§

fn div(self, other: Self) -> Self

Performs the / operation. Read more
Source§

impl Eq for Fixed

Source§

impl Hash for Fixed

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Mul for Fixed

Source§

type Output = Fixed

The resulting type after applying the * operator.
Source§

fn mul(self, other: Self) -> Self

Performs the * operation. Read more
Source§

impl Mul<Fixed> for Vec2

Scaled by a scalar. Saturating componentwise, like everything else here.

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, factor: Fixed) -> Self

Performs the * operation. Read more
Source§

impl Mul<Fixed> for Vec3

Source§

type Output = Vec3

The resulting type after applying the * operator.
Source§

fn mul(self, factor: Fixed) -> Self

Performs the * operation. Read more
Source§

impl Neg for Fixed

Source§

type Output = Fixed

The resulting type after applying the - operator.
Source§

fn neg(self) -> Self

Performs the unary - operation. Read more
Source§

impl Ord for Fixed

Source§

fn cmp(&self, other: &Fixed) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

impl PartialEq for Fixed

Source§

fn eq(&self, other: &Fixed) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for Fixed

Source§

fn partial_cmp(&self, other: &Fixed) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl StructuralPartialEq for Fixed

Source§

impl Sub for Fixed

Source§

type Output = Fixed

The resulting type after applying the - operator.
Source§

fn sub(self, other: Self) -> Self

Performs the - operation. Read more

Auto Trait Implementations§

§

impl Freeze for Fixed

§

impl RefUnwindSafe for Fixed

§

impl Send for Fixed

§

impl Sync for Fixed

§

impl Unpin for Fixed

§

impl UnsafeUnpin for Fixed

§

impl UnwindSafe for Fixed

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.