Skip to main content

I128

Struct I128 

Source
#[repr(transparent)]
pub struct I128<const SCALE: u32>(pub i128);
Expand description

Scaled fixed-point decimal with 128-bit storage.

SCALE is the base-10 exponent. A logical value v is stored as v * 10^SCALE in the underlying i128. For example, with SCALE = 12 the number 1.5 is stored as i128(1_500_000_000_000).

§Precision

N/A: type definition, no arithmetic performed.

§Determinism

All arithmetic is integer arithmetic on i128. The same inputs produce the same bit-pattern on every platform.

§Equality and ordering

Hash, Eq, and Ord are derived from i128. Two I128<S> values are equal if and only if their underlying i128 fields are bit-equal. This works because the scale is fixed at compile time – each logical value has exactly one representation.

§Const-generic scale

The const generic allows scale variants (I128<9>, I128<6>, etc.) as trivial type aliases without duplicating any method implementations. Mixed-scale arithmetic is deliberately not provided; callers convert explicitly.

Tuple Fields§

§0: i128

Implementations§

Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub const fn abs(self) -> Self

Return the absolute value of self.

§Panics

Panics in debug builds when self == I128::MIN because i128::MIN has no positive counterpart in two’s-complement. Wraps to i128::MIN in release builds.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let x = I128s12::from_bits(-1_500_000_000_000);
assert_eq!(x.abs().to_bits(), 1_500_000_000_000);
Source

pub fn signum(self) -> Self

Return the sign of self as a scaled I128.

Returns -ONE for negative values, ZERO for zero, and +ONE for positive values, mirroring f64::signum / i128::signum lifted into the I128 type. Unlike i128::signum which returns a bare -1, 0, or 1, this method encodes the result as N * 10^S.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_bits(500_000_000_000).signum(), I128s12::ONE);
assert_eq!(I128s12::ZERO.signum(), I128s12::ZERO);
assert_eq!(I128s12::from_bits(-500_000_000_000).signum(), -I128s12::ONE);
Source

pub fn floor(self) -> Self

Return the largest integer multiple of ONE that is less than or equal to self (round toward negative infinity).

For negative inputs this differs from truncation: I128(-0.5).floor() returns I128(-1.0), not I128(0.0).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let x = I128s12::from_bits(2_500_000_000_000); // 2.5
assert_eq!(x.floor().to_bits(), 2_000_000_000_000);

let y = I128s12::from_bits(-2_500_000_000_000); // -2.5
assert_eq!(y.floor().to_bits(), -3_000_000_000_000);
Source

pub fn ceil(self) -> Self

Return the smallest integer multiple of ONE that is greater than or equal to self (round toward positive infinity).

For negative inputs: I128(-0.5).ceil() returns I128(0.0).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let x = I128s12::from_bits(2_500_000_000_000); // 2.5
assert_eq!(x.ceil().to_bits(), 3_000_000_000_000);

let y = I128s12::from_bits(-2_500_000_000_000); // -2.5
assert_eq!(y.ceil().to_bits(), -2_000_000_000_000);
Source

pub fn round(self) -> Self

Round to the nearest integer using half-away-from-zero.

Ties (values whose fractional part is exactly 0.5) round away from zero: 2.5 rounds to 3.0 and -2.5 rounds to -3.0. This matches f64::round. Half-even (“banker’s”) rounding is not provided; use floor and fract to compose it if needed.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_bits(2_500_000_000_000).round().to_bits(), 3_000_000_000_000);
assert_eq!(I128s12::from_bits(2_400_000_000_000).round().to_bits(), 2_000_000_000_000);
assert_eq!(I128s12::from_bits(-2_500_000_000_000).round().to_bits(), -3_000_000_000_000);
Source

pub fn trunc(self) -> Self

Drop the fractional part, rounding toward zero.

For negative inputs this differs from floor: I128(-2.5).trunc() returns I128(-2.0), whereas I128(-2.5).floor() returns I128(-3.0).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_bits(2_500_000_000_000).trunc().to_bits(), 2_000_000_000_000);
assert_eq!(I128s12::from_bits(-2_500_000_000_000).trunc().to_bits(), -2_000_000_000_000);
Source

pub fn fract(self) -> Self

Return only the fractional part: self - self.trunc().

The result has the same sign as self because trunc rounds toward zero. I128(2.5).fract() is I128(0.5); I128(-2.5).fract() is I128(-0.5).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_bits(2_500_000_000_000).fract().to_bits(), 500_000_000_000);
assert_eq!(I128s12::from_bits(-2_500_000_000_000).fract().to_bits(), -500_000_000_000);
assert_eq!(I128s12::from_bits(2_000_000_000_000).fract().to_bits(), 0);
Source

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

Return the lesser of self and other.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000);
let b = I128s12::from_bits(2_000_000_000_000);
assert_eq!(a.min(b), a);
Source

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

Return the greater of self and other.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000);
let b = I128s12::from_bits(2_000_000_000_000);
assert_eq!(a.max(b), b);
Source

pub fn clamp(self, lo: Self, hi: Self) -> Self

Restrict self to the closed interval [lo, hi].

Returns lo if self < lo, hi if self > hi, and self otherwise.

§Panics

Panics if lo > hi, matching Ord::clamp.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let lo = I128s12::from_bits(1_000_000_000_000); // 1.0
let hi = I128s12::from_bits(3_000_000_000_000); // 3.0
let x  = I128s12::from_bits(5_000_000_000_000); // 5.0
assert_eq!(x.clamp(lo, hi), hi);
Source

pub fn recip(self) -> Self

Return the multiplicative inverse: ONE / self.

§Panics

Panics when self == ZERO (division by zero).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let two  = I128s12::from_bits(2_000_000_000_000);
let half = I128s12::from_bits(500_000_000_000);
assert_eq!(two.recip(), half);
Source

pub fn copysign(self, sign: Self) -> Self

Return a value with the magnitude of self and the sign of sign.

When sign == ZERO the result is positive because i128 has no negative-zero representation.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let pos = I128s12::from_bits(1_500_000_000_000);
let neg = I128s12::from_bits(-2_000_000_000_000);
assert_eq!(pos.copysign(neg).to_bits(), -1_500_000_000_000);
Source

pub fn div_euclid(self, rhs: Self) -> Self

Euclidean division: returns the quotient as a I128 integer multiple of ONE, chosen so that the remainder is non-negative.

Delegates to i128::div_euclid on the raw storage values; the quotient is rescaled by multiplier() to produce a value in N * 10^S form.

§Panics

Panics on rhs == ZERO and on overflow in debug builds (e.g. I128::MIN.div_euclid(-ONE) overflows the quotient, mirroring i128::div_euclid).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(-5_000_000_000_000); // -5.0
let b = I128s12::from_bits( 2_000_000_000_000); //  2.0
// Euclidean: quotient = -3, remainder = 1 (always non-negative)
assert_eq!(a.div_euclid(b).to_bits(), -3_000_000_000_000);
Source

pub fn rem_euclid(self, rhs: Self) -> Self

Euclidean remainder: self - rhs * self.div_euclid(rhs).

The result is always non-negative when rhs != ZERO. Because both operands share the same scale, self.0.rem_euclid(rhs.0) already lives in value * 10^S form without rescaling.

§Panics

Panics on rhs == ZERO.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(-5_000_000_000_000); // -5.0
let b = I128s12::from_bits( 2_000_000_000_000); //  2.0
assert_eq!(a.rem_euclid(b).to_bits(), 1_000_000_000_000); // 1.0, non-negative
Source

pub fn div_floor(self, rhs: Self) -> Self

Floor-rounded division: returns floor(self / rhs) as a I128 integer multiple of ONE.

Differs from div_euclid for negative divisors: div_floor is keyed to the real-number quotient, while div_euclid is keyed to keeping the remainder non-negative regardless of divisor sign.

Implemented inline because i128::div_floor for signed types is still behind an unstable feature as of Rust 1.95.

§Panics

Panics on rhs == ZERO.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(-5_000_000_000_000); // -5.0
let b = I128s12::from_bits( 2_000_000_000_000); //  2.0
// floor(-2.5) = -3
assert_eq!(a.div_floor(b).to_bits(), -3_000_000_000_000);
Source

pub fn div_ceil(self, rhs: Self) -> Self

Ceil-rounded division: returns ceil(self / rhs) as a I128 integer multiple of ONE.

Implemented inline because i128::div_ceil for signed types is still behind an unstable feature as of Rust 1.95.

§Panics

Panics on rhs == ZERO.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(5_000_000_000_000); // 5.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
// ceil(2.5) = 3
assert_eq!(a.div_ceil(b).to_bits(), 3_000_000_000_000);
Source

pub fn abs_diff(self, rhs: Self) -> Self

Return the absolute difference |self - rhs| as a I128.

Computed as max(self, rhs) - min(self, rhs) so the subtraction is always non-negative. Returns a signed I128 rather than a u128 because I128 uses signed storage. Standard panic-debug / wrap-release applies if the difference exceeds i128::MAX (only possible at the MAX - MIN boundary).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits( 5_000_000_000_000); //  5.0
let b = I128s12::from_bits(-2_000_000_000_000); // -2.0
assert_eq!(a.abs_diff(b).to_bits(), 7_000_000_000_000); // 7.0
Source

pub fn midpoint(self, rhs: Self) -> Self

Return the midpoint of self and rhs without intermediate overflow.

Delegates to i128::midpoint (stable since Rust 1.85). Rounds toward negative infinity when the exact midpoint is not representable, matching i128::midpoint semantics.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000); // 1.0
let b = I128s12::from_bits(3_000_000_000_000); // 3.0
assert_eq!(a.midpoint(b).to_bits(), 2_000_000_000_000); // 2.0
Source

pub const fn is_nan(self) -> bool

Always returns false; I128 has no NaN representation.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(!I128s12::ZERO.is_nan());
assert!(!I128s12::MAX.is_nan());
Source

pub const fn is_infinite(self) -> bool

Always returns false; I128 has no infinity representation.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(!I128s12::MAX.is_infinite());
Source

pub const fn is_finite(self) -> bool

Always returns true; every I128 value is finite.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(I128s12::MAX.is_finite());
assert!(I128s12::MIN.is_finite());
Source

pub const fn is_normal(self) -> bool

Returns true for any non-zero value.

I128 has no subnormal representation, so zero is the only value that is not normal.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(!I128s12::ZERO.is_normal());
assert!(I128s12::ONE.is_normal());
Source

pub const fn is_zero(self) -> bool

Returns true if the value is zero.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(I128s12::ZERO.is_zero());
assert!(!I128s12::ONE.is_zero());
Source

pub const fn is_positive(self) -> bool

Returns true if the value is strictly greater than zero.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!(I128s12::ONE.is_positive());
assert!(!I128s12::ZERO.is_positive());
assert!(!(-I128s12::ONE).is_positive());
Source

pub const fn is_negative(self) -> bool

Returns true if the value is strictly less than zero.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert!((-I128s12::ONE).is_negative());
assert!(!I128s12::ZERO.is_negative());
assert!(!I128s12::ONE.is_negative());
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub const fn unsigned_shr(self, n: u32) -> Self

Logical (zero-fill) right shift of the underlying i128 storage by n bits.

Unlike the Shr operator, which is arithmetic (sign-extending), this method reinterprets storage as u128 for the shift, so the vacated high bits are always filled with zeros regardless of sign.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

Panics in debug builds when n >= 128; wraps modulo 128 in release builds.

§Examples
use decimal_scaled::I128s12;
// -1 raw is all-ones. Arithmetic shr keeps it all-ones;
// unsigned_shr clears the top bit, giving i128::MAX.
let neg_one = I128s12::from_bits(-1);
assert_eq!(neg_one >> 1u32, neg_one);                          // sign-extending
assert_eq!(neg_one.unsigned_shr(1), I128s12::from_bits(i128::MAX)); // zero-fill
Source

pub const fn rotate_left(self, n: u32) -> Self

Rotate the underlying i128 storage left by n bits. Bits shifted off the high end wrap into the low end.

Operates on raw bits, not the logical decimal value. Delegates to i128::rotate_left.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// 0b111 rotated left by 1 = 0b1110.
assert_eq!(I128s12::from_bits(0b111).rotate_left(1), I128s12::from_bits(0b1110));
Source

pub const fn rotate_right(self, n: u32) -> Self

Rotate the underlying i128 storage right by n bits. Bits shifted off the low end wrap into the high end.

Operates on raw bits, not the logical decimal value. Delegates to i128::rotate_right.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// 1 rotated right by 1 wraps the low bit to the top: i128::MIN.
assert_eq!(I128s12::from_bits(1).rotate_right(1), I128s12::from_bits(i128::MIN));
Source

pub const fn leading_zeros(self) -> u32

Number of leading zero bits in the underlying i128 storage.

Returns 128 for storage value 0, 127 for 1, and 0 for from_bits(-1) (all-ones). Delegates to i128::leading_zeros.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::from_bits(1).leading_zeros(), 127);
assert_eq!(I128s12::ZERO.leading_zeros(), 128);
assert_eq!(I128s12::from_bits(-1).leading_zeros(), 0);
Source

pub const fn trailing_zeros(self) -> u32

Number of trailing zero bits in the underlying i128 storage.

Returns 128 for storage value 0 and 3 for from_bits(8). Delegates to i128::trailing_zeros.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::from_bits(8).trailing_zeros(), 3);
assert_eq!(I128s12::ZERO.trailing_zeros(), 128);
Source

pub const fn count_ones(self) -> u32

Population count: number of 1 bits set in the underlying i128 storage.

Note the storage-not-value semantic: I128s12::ONE.count_ones() returns the popcount of 10^12 (= 21), not 1. Use I128::from_bits when you need a predictable bit pattern.

Delegates to i128::count_ones.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::from_bits(0b101).count_ones(), 2);
Source

pub const fn count_zeros(self) -> u32

Number of 0 bits in the underlying i128 storage. Always equal to 128 - self.count_ones().

Delegates to i128::count_zeros.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// 0b101 has 2 ones and 126 zeros in 128-bit storage.
assert_eq!(I128s12::from_bits(0b101).count_zeros(), 126);
Source

pub const fn is_power_of_two(self) -> bool

Returns true if the underlying i128 storage is a power of two (exactly one bit set and the value is positive).

Implemented by reinterpreting the storage as u128 and delegating to u128::is_power_of_two. Negative i128 values always return false because the sign bit being set means more than one bit is set in the u128 view.

Note the storage-not-value semantic: I128s12::ONE.is_power_of_two() returns false because storage is 10^12 = 2^12 * 5^12, not a single-bit value.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert!(I128s12::from_bits(8).is_power_of_two());
assert!(!I128s12::from_bits(7).is_power_of_two());
assert!(!I128s12::from_bits(-1).is_power_of_two());
Source

pub const fn next_power_of_two(self) -> Self

Smallest power of two greater than or equal to the underlying i128 storage, treating the storage as u128.

Delegates to u128::next_power_of_two over the unsigned reinterpretation, then casts the result back to i128. If the next power of two exceeds i128::MAX the raw bit pattern wraps into the negative i128 range.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

Panics in debug builds when the next power of two overflows u128::MAX, matching u128::next_power_of_two semantics.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::from_bits(7).next_power_of_two(), I128s12::from_bits(8));
assert_eq!(I128s12::from_bits(8).next_power_of_two(), I128s12::from_bits(8));
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub const EPSILON: Self

Smallest representable positive value: 1 LSB = 10^-SCALE.

Provided as an analogue to f64::EPSILON for generic numeric code. Note that this differs from the f64 definition (“difference between 1.0 and the next-larger f64”): for I128 the LSB is uniform across the entire representable range.

§Precision

N/A: constant value, no arithmetic performed.

Source

pub const MIN_POSITIVE: Self

Smallest positive value (equal to Self::EPSILON).

Provided as an analogue to f64::MIN_POSITIVE for generic numeric code. Unlike f64, I128 has no subnormals, so MIN_POSITIVE and EPSILON are the same value.

§Precision

N/A: constant value, no arithmetic performed.

Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub fn from_int(value: i64) -> Self

Constructs a I128 from an i64 integer value.

Named constructor that wraps From<i64>. Prefer this over I128::from(value) when the intent of converting from an integer should be explicit at the call site.

At SCALE = 12 every i64 value fits with roughly six orders of magnitude of headroom before i128::MAX.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_int(1), I128s12::ONE);
assert_eq!(I128s12::from_int(-42).to_bits(), -42_000_000_000_000_i128);
Source

pub fn from_i32(value: i32) -> Self

Constructs a I128 from an i32 integer value.

Named constructor that wraps From<i32>. Lossless at any practical SCALE (safe up to SCALE < 28).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_i32(1), I128s12::ONE);
assert_eq!(I128s12::from_i32(0), I128s12::ZERO);
Source

pub fn from_f64_lossy(value: f64) -> Self

Constructs a I128 from an f64, saturating on non-finite or out-of-range inputs.

Multiplies value by 10^SCALE and truncates to i128. Non-finite and out-of-range inputs are handled as follows:

  • NaN returns I128::ZERO (deterministic, no panic).
  • +inf or any finite value above the representable range returns I128::MAX.
  • -inf or any finite value below the representable range returns I128::MIN.

Use TryFrom<f64> when you want an error instead of saturation.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_f64_lossy(1.0), I128s12::ONE);
assert_eq!(I128s12::from_f64_lossy(f64::NAN), I128s12::ZERO);
assert_eq!(I128s12::from_f64_lossy(f64::INFINITY), I128s12::MAX);
assert_eq!(I128s12::from_f64_lossy(f64::NEG_INFINITY), I128s12::MIN);
Source

pub fn to_int_lossy(self) -> i64

Converts to i64 by truncating the fractional part toward zero.

The integer part is self.0 / 10^SCALE. If that value exceeds i64::MAX or falls below i64::MIN, the result saturates to i64::MAX or i64::MIN respectively. At SCALE = 12 the saturation threshold is approximately 9.2e18 (the i64 limit), which is well below the I128 maximum of ~1.7e26.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;

// Truncates toward zero.
assert_eq!(I128s12::from_bits(2_500_000_000_000).to_int_lossy(), 2);
assert_eq!(I128s12::from_bits(-2_500_000_000_000).to_int_lossy(), -2);

// Saturates when the integer part exceeds i64 range.
assert_eq!(I128s12::MAX.to_int_lossy(), i64::MAX);
assert_eq!(I128s12::MIN.to_int_lossy(), i64::MIN);
Source

pub fn to_f64_lossy(self) -> f64

Converts to f64 by dividing the raw storage by 10^SCALE.

f64 has a 53-bit mantissa, so large or precision-dense I128 values will round. The division is performed as (self.0 as f64) / multiplier to keep as much precision as f64 allows.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ZERO.to_f64_lossy(), 0.0);
assert_eq!(I128s12::ONE.to_f64_lossy(), 1.0);
Source

pub fn to_f32_lossy(self) -> f32

Converts to f32 via f64, then narrows to f32.

f32 has only a 24-bit mantissa, making this lossier than Self::to_f64_lossy. The f64 intermediate step retains the best precision available before the final narrowing cast.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ZERO.to_f32_lossy(), 0.0_f32);
assert_eq!(I128s12::ONE.to_f32_lossy(), 1.0_f32);
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub const ZERO: Self

The additive identity. Stored as i128(0).

§Precision

N/A: constant value, no arithmetic performed.

Source

pub const ONE: Self

The multiplicative identity. Stored as i128(10^SCALE).

At SCALE = 12 the raw value is 1_000_000_000_000.

§Precision

N/A: constant value, no arithmetic performed.

Source

pub const MAX: Self

The largest representable value: I128(i128::MAX).

In logical terms this is i128::MAX / 10^SCALE. At SCALE = 12 that is approximately 1.7e14 model units. Arithmetic that overflows this bound panics in debug builds and wraps in release builds.

§Precision

N/A: constant value, no arithmetic performed.

Source

pub const MIN: Self

The smallest representable value: I128(i128::MIN).

Mirror of Self::MAX. Note that -MIN panics in debug builds because i128::MIN has no positive two’s-complement counterpart.

§Precision

N/A: constant value, no arithmetic performed.

Source

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

Constructs a I128<SCALE> from a raw i128 bit pattern.

The integer is interpreted directly as the internal storage: raw represents the logical value raw * 10^(-SCALE). This is the inverse of Self::to_bits.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// Raw 1_500_000_000_000 represents the logical value 1.5.
let v = I128s12::from_bits(1_500_000_000_000);
assert_eq!(v.to_bits(), 1_500_000_000_000);
Source

pub const fn to_bits(self) -> i128

Returns the raw i128 storage value.

The returned integer encodes the logical value self * 10^SCALE. This is the inverse of Self::from_bits.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::ONE.to_bits(), 1_000_000_000_000_i128);
Source

pub const fn multiplier() -> i128

Returns 10^SCALE, the factor that converts a logical integer value to its storage representation.

This equals the bit pattern of Self::ONE.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Overflow

10^SCALE overflows i128 at SCALE >= 39. For practical scales (SCALE <= 38) this is within range. Calling with an overflowing scale panics at compile time when the const item is evaluated.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::multiplier(), 1_000_000_000_000_i128);
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub fn from_num<T: ToPrimitive>(value: T) -> Self

Constructs a I128<SCALE> from any T: ToPrimitive.

This is a compatibility alias for the idiomatic From<T> / num_traits::FromPrimitive surface. Routes through num_traits::NumCast::from, which dispatches to the num_traits::FromPrimitive impl on I128.

§Precision

Lossy: involves f32 or f64 at some point when T is a float type; result may lose precision. For integer T, the conversion is Strict: all arithmetic is integer-only; result is bit-exact.

§Saturation policy
§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from_num(42_i32), I128s12::from(42_i32));
assert_eq!(I128s12::from_num(f64::INFINITY), I128s12::MAX);
assert_eq!(I128s12::from_num(f64::NAN), I128s12::ZERO);
Source

pub fn to_num<T: NumCast + Bounded>(self) -> T

Converts self to any T: NumCast + Bounded.

This is a compatibility alias for the idiomatic num_traits::ToPrimitive / to_X_lossy surface. Routes through num_traits::NumCast::from, which dispatches to the num_traits::ToPrimitive impl on I128.

§Precision

Lossy: involves f32 or f64 at some point when T is a float type; result may lose precision. For integer T, the conversion is Strict: all arithmetic is integer-only; result is bit-exact.

§Saturation policy
§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(42_i32).to_num::<i32>(), 42_i32);
assert_eq!(I128s12::MAX.to_num::<i32>(), i32::MAX);
assert_eq!(I128s12::MIN.to_num::<i32>(), i32::MIN);
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub fn ln(self) -> Self

Returns the natural logarithm (base e) of self.

§Precision

Lossy: converts to f64, calls f64::ln, converts back. f64::ln returns -Infinity for 0.0 (saturates to I128::MIN) and NaN for negative inputs (maps to I128::ZERO).

§Examples
use decimal_scaled::I128s12;
// ln(1) == 0 (f64::ln(1.0) == 0.0 exactly).
assert_eq!(I128s12::ONE.ln(), I128s12::ZERO);
Source

pub fn log(self, base: Self) -> Self

Returns the logarithm of self in the given base.

Implemented via a single f64::log(self_f64, base_f64) call, which avoids the extra quantisation that would come from computing ln(self) / ln(base) with two separate f64 round-trips.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// log_2(8) is approximately 3 within f64 precision.
let eight = I128s12::from_int(8);
let two   = I128s12::from_int(2);
let result = eight.log(two);
Source

pub fn log2(self) -> Self

Returns the base-2 logarithm of self.

§Precision

Lossy: involves f64 at some point; result may lose precision. On IEEE-754 platforms, f64::log2 is exact for integer powers of two (e.g. log2(8.0) == 3.0). Out-of-domain inputs follow the same saturation policy as Self::ln.

§Examples
use decimal_scaled::I128s12;
// log2(1) == 0 (f64::log2(1.0) == 0.0 exactly).
assert_eq!(I128s12::ONE.log2(), I128s12::ZERO);
Source

pub fn log10(self) -> Self

Returns the base-10 logarithm of self.

§Precision

Lossy: involves f64 at some point; result may lose precision. Out-of-domain inputs follow the same saturation policy as Self::ln.

§Examples
use decimal_scaled::I128s12;
// log10(1) == 0 (f64::log10(1.0) == 0.0 exactly).
assert_eq!(I128s12::ONE.log10(), I128s12::ZERO);
Source

pub fn exp(self) -> Self

Returns e^self (natural exponential).

§Precision

Lossy: involves f64 at some point; result may lose precision. Large positive inputs overflow f64 to +Infinity, which saturates to I128::MAX. Large negative inputs underflow to 0.0 in f64, which maps to I128::ZERO.

§Examples
use decimal_scaled::I128s12;
// exp(0) == 1 (f64::exp(0.0) == 1.0 exactly).
assert_eq!(I128s12::ZERO.exp(), I128s12::ONE);
Source

pub fn exp2(self) -> Self

Returns 2^self (base-2 exponential).

§Precision

Lossy: involves f64 at some point; result may lose precision. Saturation behaviour is analogous to Self::exp but at different magnitudes (inputs beyond approximately 1024 overflow to +Infinity).

§Examples
use decimal_scaled::I128s12;
// exp2(0) == 1 (f64::exp2(0.0) == 1.0 exactly).
assert_eq!(I128s12::ZERO.exp2(), I128s12::ONE);
Source§

impl<const SCALE: u32> I128<SCALE>

Source

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

Returns self + rhs, or None if the result overflows i128.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000); // 1.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.checked_add(b), Some(I128s12::from_bits(3_000_000_000_000)));
assert_eq!(I128s12::MAX.checked_add(I128s12::ONE), None);
Source

pub const fn wrapping_add(self, rhs: Self) -> Self

Returns self + rhs with two’s-complement wrap on overflow.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000); // 1.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.wrapping_add(b), I128s12::from_bits(3_000_000_000_000));
// Overflow wraps to MIN.
assert_eq!(I128s12::MAX.wrapping_add(I128s12::from_bits(1)), I128s12::MIN);
Source

pub const fn saturating_add(self, rhs: Self) -> Self

Returns self + rhs, clamped to I128::MAX or I128::MIN on overflow.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000); // 1.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.saturating_add(b), I128s12::from_bits(3_000_000_000_000));
assert_eq!(I128s12::MAX.saturating_add(I128s12::ONE), I128s12::MAX);
assert_eq!(I128s12::MIN.saturating_add(-I128s12::ONE), I128s12::MIN);
Source

pub const fn overflowing_add(self, rhs: Self) -> (Self, bool)

Returns (self + rhs, did_overflow) where the value is the two’s-complement wrapping result.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_000_000_000_000); // 1.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.overflowing_add(b), (I128s12::from_bits(3_000_000_000_000), false));
assert_eq!(
    I128s12::MAX.overflowing_add(I128s12::from_bits(1)),
    (I128s12::MIN, true),
);
Source

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

Returns self - rhs, or None if the result overflows i128.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let three = I128s12::from_bits(3_000_000_000_000);
let two   = I128s12::from_bits(2_000_000_000_000);
assert_eq!(three.checked_sub(two), Some(I128s12::ONE));
assert_eq!(I128s12::MIN.checked_sub(I128s12::ONE), None);
Source

pub const fn wrapping_sub(self, rhs: Self) -> Self

Returns self - rhs with two’s-complement wrap on overflow.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let three = I128s12::from_bits(3_000_000_000_000);
let two   = I128s12::from_bits(2_000_000_000_000);
assert_eq!(three.wrapping_sub(two), I128s12::ONE);
// Underflow wraps to MAX.
assert_eq!(I128s12::MIN.wrapping_sub(I128s12::from_bits(1)), I128s12::MAX);
Source

pub const fn saturating_sub(self, rhs: Self) -> Self

Returns self - rhs, clamped to I128::MAX or I128::MIN on overflow.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let three = I128s12::from_bits(3_000_000_000_000);
let two   = I128s12::from_bits(2_000_000_000_000);
assert_eq!(three.saturating_sub(two), I128s12::ONE);
assert_eq!(I128s12::MIN.saturating_sub(I128s12::ONE), I128s12::MIN);
Source

pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool)

Returns (self - rhs, did_overflow) where the value is the two’s-complement wrapping result.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let three = I128s12::from_bits(3_000_000_000_000);
let two   = I128s12::from_bits(2_000_000_000_000);
assert_eq!(three.overflowing_sub(two), (I128s12::ONE, false));
assert_eq!(
    I128s12::MIN.overflowing_sub(I128s12::from_bits(1)),
    (I128s12::MAX, true),
);
Source

pub const fn checked_neg(self) -> Option<Self>

Returns -self, or None for I128::MIN (whose two’s-complement negation does not fit in i128).

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ONE.checked_neg(), Some(-I128s12::ONE));
assert_eq!(I128s12::MIN.checked_neg(), None);
Source

pub const fn wrapping_neg(self) -> Self

Returns -self with two’s-complement wrap. For I128::MIN this returns I128::MIN (matches i128::wrapping_neg).

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ONE.wrapping_neg(), -I128s12::ONE);
assert_eq!(I128s12::MIN.wrapping_neg(), I128s12::MIN);
Source

pub const fn saturating_neg(self) -> Self

Returns -self, clamped to I128::MAX for I128::MIN (matches i128::saturating_neg).

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ONE.saturating_neg(), -I128s12::ONE);
assert_eq!(I128s12::MIN.saturating_neg(), I128s12::MAX);
Source

pub const fn overflowing_neg(self) -> (Self, bool)

Returns (-self, did_overflow). Overflow occurs only for I128::MIN, in which case the wrapping result is I128::MIN.

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::ONE.overflowing_neg(), (-I128s12::ONE, false));
assert_eq!(I128s12::MIN.overflowing_neg(), (I128s12::MIN, true));
Source

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

Returns self * rhs, or None if the rescaled product does not fit in i128.

The intermediate product is computed with 256-bit arithmetic and cannot itself overflow. The only failure mode is a final i128 quotient that exceeds the storage range.

§Precision

Strict: the result is truncated (not rounded) toward zero during the scale-restoring divide, identical to the default * operator.

§Examples
use decimal_scaled::I128s12;

let half = I128s12::from_bits(500_000_000_000); // 0.5
assert_eq!(half.checked_mul(half), Some(I128s12::from_bits(250_000_000_000)));
assert_eq!(I128s12::MAX.checked_mul(I128s12::from_bits(2_000_000_000_000)), None);
Source

pub fn wrapping_mul(self, rhs: Self) -> Self

Returns self * rhs with two’s-complement wrap when the rescaled product does not fit in i128.

On overflow, falls back to (a.wrapping_mul(b)).wrapping_div(multiplier()). The exact bit pattern of the wrapping result at extreme magnitudes is an implementation detail; only the no-panic contract is guaranteed.

§Precision

Strict: truncates toward zero during the scale-restoring divide.

§Examples
use decimal_scaled::I128s12;

let half = I128s12::from_bits(500_000_000_000); // 0.5
assert_eq!(half.wrapping_mul(half), I128s12::from_bits(250_000_000_000));
// Overflow does not panic.
let _ = I128s12::MAX.wrapping_mul(I128s12::from_bits(2_000_000_000_000));
Source

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

Returns self * rhs, clamped to I128::MAX or I128::MIN on overflow.

The clamp direction is determined by the XOR of operand signs: same-sign operands saturate to MAX; mixed-sign operands saturate to MIN.

§Precision

Strict: truncates toward zero during the scale-restoring divide.

§Examples
use decimal_scaled::I128s12;

let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(I128s12::MAX.saturating_mul(two), I128s12::MAX);
assert_eq!(I128s12::MAX.saturating_mul(-two), I128s12::MIN);
Source

pub fn overflowing_mul(self, rhs: Self) -> (Self, bool)

Returns (self * rhs, did_overflow) where the value is the wrapping result when overflow occurs.

§Precision

Strict: truncates toward zero during the scale-restoring divide.

§Examples
use decimal_scaled::I128s12;

let half = I128s12::from_bits(500_000_000_000); // 0.5
assert_eq!(half.overflowing_mul(half), (I128s12::from_bits(250_000_000_000), false));
let (_, ovf) = I128s12::MAX.overflowing_mul(I128s12::from_bits(2_000_000_000_000));
assert!(ovf);
Source

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

Returns self / rhs, or None on division by zero or if the rescaled quotient does not fit in i128.

The only finite-operand overflow case is I128::MIN / NEG_ONE (storage negation of i128::MIN overflows).

§Precision

Strict: the widening divide truncates toward zero, identical to the default / operator.

§Examples
use decimal_scaled::I128s12;

let six = I128s12::from_bits(6_000_000_000_000); // 6.0
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(six.checked_div(two), Some(I128s12::from_bits(3_000_000_000_000)));
assert_eq!(I128s12::ONE.checked_div(I128s12::ZERO), None);
Source

pub fn wrapping_div(self, rhs: Self) -> Self

Returns self / rhs with two’s-complement wrap when the rescaled quotient does not fit in i128.

On overflow, falls back to (a.wrapping_mul(multiplier())).wrapping_div(b).

§Precision

Strict: truncates toward zero.

§Panics

Panics on rhs == ZERO (matches i128::wrapping_div).

§Examples
use decimal_scaled::I128s12;

let six = I128s12::from_bits(6_000_000_000_000); // 6.0
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(six.wrapping_div(two), I128s12::from_bits(3_000_000_000_000));
Source

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

Returns self / rhs, clamped to I128::MAX or I128::MIN on overflow.

The clamp direction is determined by the XOR of operand signs, because the scale multiplier is always positive.

§Precision

Strict: truncates toward zero.

§Panics

Panics on rhs == ZERO (matches i128::saturating_div).

§Examples
use decimal_scaled::I128s12;

let six = I128s12::from_bits(6_000_000_000_000); // 6.0
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(six.saturating_div(two), I128s12::from_bits(3_000_000_000_000));
// MAX / 0.5 overflows; both positive so clamp to MAX.
assert_eq!(I128s12::MAX.saturating_div(I128s12::from_bits(500_000_000_000)), I128s12::MAX);
Source

pub fn overflowing_div(self, rhs: Self) -> (Self, bool)

Returns (self / rhs, did_overflow) where the value is the wrapping result when overflow occurs.

§Precision

Strict: truncates toward zero.

§Panics

Panics on rhs == ZERO (matches i128::overflowing_div).

§Examples
use decimal_scaled::I128s12;

let six = I128s12::from_bits(6_000_000_000_000); // 6.0
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(six.overflowing_div(two), (I128s12::from_bits(3_000_000_000_000), false));
let half = I128s12::from_bits(500_000_000_000); // 0.5
let (_, ovf) = I128s12::MAX.overflowing_div(half);
assert!(ovf);
Source

pub const fn checked_rem(self, rhs: Self) -> Option<Self>

Returns self % rhs, or None on rhs == ZERO or for the storage-level overflow case I128::MIN % from_bits(-1) (matches i128::checked_rem).

§Precision

Strict: operates on integer raw storage with no rounding.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(5_500_000_000_000); // 5.5
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.checked_rem(two), Some(I128s12::from_bits(1_500_000_000_000)));
assert_eq!(I128s12::ONE.checked_rem(I128s12::ZERO), None);
Source

pub const fn wrapping_rem(self, rhs: Self) -> Self

Returns self % rhs. For the storage-level overflow case I128::MIN.wrapping_rem(from_bits(-1)), returns ZERO (matches i128::wrapping_rem).

§Precision

Strict: operates on integer raw storage with no rounding.

§Panics

Panics on rhs == ZERO (matches i128::wrapping_rem).

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(5_500_000_000_000); // 5.5
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.wrapping_rem(two), I128s12::from_bits(1_500_000_000_000));
Source

pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool)

Returns (self % rhs, did_overflow). Overflow (did_overflow == true) occurs only for the storage-level case I128::MIN % from_bits(-1), in which case the wrapping result is ZERO.

§Precision

Strict: operates on integer raw storage with no rounding.

§Panics

Panics on rhs == ZERO (matches i128::overflowing_rem).

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(5_500_000_000_000); // 5.5
let two = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!(a.overflowing_rem(two), (I128s12::from_bits(1_500_000_000_000), false));
let neg_one_lsb = I128s12::from_bits(-1);
assert_eq!(I128s12::MIN.overflowing_rem(neg_one_lsb), (I128s12::ZERO, true));
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub fn pow(self, exp: u32) -> Self

Raises self to the power exp.

Uses square-and-multiply: walks the bits of exp from low to high, squaring the base each step and accumulating when the corresponding bit is set. Costs O(log exp) multiplications. Each multiplication routes through the I128 Mul operator.

exp = 0 always returns ONE, even when self is ZERO (matches i128::pow convention).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

In debug builds, panics on i128 overflow at any multiplication step. In release builds, wraps two’s-complement. Matches i128::pow and I128::Mul semantics.

Use Self::checked_pow, Self::wrapping_pow, Self::saturating_pow, or Self::overflowing_pow for explicit overflow control.

§Examples
use decimal_scaled::I128s12;
let two = I128s12::from_int(2);
assert_eq!(two.pow(10), I128s12::from_int(1024));
// exp = 0 returns ONE regardless of base.
assert_eq!(I128s12::ZERO.pow(0), I128s12::ONE);
Source

pub fn powi(self, exp: i32) -> Self

Raises self to the signed integer power exp.

For non-negative exp, equivalent to self.pow(exp as u32). For negative exp, returns I128::ONE / self.pow(exp.unsigned_abs()), i.e. the reciprocal of the positive-exponent form.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics
  • Overflow of i128 storage at any step in debug builds (matches Self::pow).
  • Division by zero when self == ZERO and exp < 0.
§Examples
use decimal_scaled::I128s12;
let two = I128s12::from_int(2);
assert_eq!(two.powi(-1), I128s12::ONE / two);
assert_eq!(two.powi(0), I128s12::ONE);
assert_eq!(two.powi(3), I128s12::from_int(8));
Source

pub fn powf(self, exp: I128<SCALE>) -> Self

Raises self to the power exp via the f64 bridge.

Converts both operands to f64, calls f64::powf, then converts the result back. For integer exponents, prefer Self::pow or Self::powi, which are bit-exact.

NaN results map to ZERO; infinities clamp to MAX or MIN, following the saturate-vs-error policy of Self::from_f64_lossy.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
let two = I128s12::from_int(2);
let three = I128s12::from_int(3);
// 2^3 = 8, within f64 precision.
assert!((two.powf(three).to_f64_lossy() - 8.0).abs() < 1e-9);
Source

pub fn sqrt(self) -> Self

Returns the square root of self via the f64 bridge.

IEEE 754 mandates that f64::sqrt is correctly-rounded (round-to-nearest, ties-to-even). Combined with the deterministic to_f64_lossy / from_f64_lossy round-trip, this makes I128::sqrt bit-deterministic: the same input produces the same output bit-pattern on every IEEE-754-conformant platform.

Negative inputs produce a NaN from f64::sqrt, which Self::from_f64_lossy maps to ZERO per the saturate-vs-error policy. No panic is raised for negative inputs.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::ZERO.sqrt(), I128s12::ZERO);
// f64::sqrt(1.0) == 1.0 exactly, so the result is bit-exact.
assert_eq!(I128s12::ONE.sqrt(), I128s12::ONE);
Source

pub fn cbrt(self) -> Self

Returns the cube root of self via the f64 bridge.

f64::cbrt is defined for the entire real line, including negative inputs (cbrt(-8.0) == -2.0). The result is bit-deterministic across IEEE-754-conformant platforms because f64::cbrt is correctly-rounded.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
let neg_eight = I128s12::from_int(-8);
let result = neg_eight.cbrt();
assert!((result.to_f64_lossy() - (-2.0_f64)).abs() < 1e-9);
Source

pub fn mul_add(self, a: Self, b: Self) -> Self

Returns self * a + b.

Mirrors the f64::mul_add call shape so f64-generic numeric code can monomorphise to I128 without rewriting call sites. No hardware FMA is involved; the multiply uses the I128 Mul operator and the add uses plain i128 addition.

The result is bit-equal to self * a + b on every input, including panic or wrap behaviour at overflow boundaries.

Available in no_std builds because the underlying Mul and Add operators require only core.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

In debug builds, panics on overflow at the multiply step or the add step. In release builds, both steps wrap two’s-complement.

§Examples
use decimal_scaled::I128s12;
let two   = I128s12::from_int(2);
let three = I128s12::from_int(3);
let four  = I128s12::from_int(4);
// 2 * 3 + 4 = 10
assert_eq!(two.mul_add(three, four), I128s12::from_int(10));
Source

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

Returns sqrt(self^2 + other^2) without intermediate overflow.

The naive form (self * self + other * other).sqrt() overflows i128 once either operand approaches sqrt(I128::MAX). This method uses the scale trick to avoid that:

hypot(a, b) = max(|a|, |b|) * sqrt(1 + (min(|a|, |b|) / max(|a|, |b|))^2)

The min/max ratio is in [0, 1], so ratio^2 is also in [0, 1] and cannot overflow. The outer multiply by large only overflows when the true hypotenuse genuinely exceeds I128::MAX, which matches f64::hypot’s contract.

Both inputs are absolute-valued before processing, so hypot(-a, b) == hypot(a, b).

Edge cases: hypot(0, 0) == 0 (bit-exact via the early return); hypot(0, x) ~= |x| and hypot(x, 0) ~= |x|.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
let three = I128s12::from_int(3);
let four  = I128s12::from_int(4);
// Pythagorean triple: hypot(3, 4) ~= 5.
assert!((three.hypot(four).to_f64_lossy() - 5.0).abs() < 1e-9);
Source

pub fn checked_pow(self, exp: u32) -> Option<Self>

Returns Some(self^exp), or None if any multiplication step overflows i128.

Walks the same square-and-multiply as Self::pow but uses mul_div_pow10 (which returns Option<i128>) at each step. The first None short-circuits to a None return.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// MAX^2 overflows.
assert!(I128s12::MAX.checked_pow(2).is_none());
// Any power of ONE is ONE.
assert_eq!(I128s12::ONE.checked_pow(1_000_000), Some(I128s12::ONE));
Source

pub fn wrapping_pow(self, exp: u32) -> Self

Returns self^exp, wrapping two’s-complement on overflow at every multiplication step.

Follows the same square-and-multiply structure as Self::pow. When a step overflows mul_div_pow10, the fallback is wrapping_mul followed by wrapping_div of the scale multiplier. The exact wrap pattern is deterministic and reproducible but is not otherwise specified.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
// ONE^N never overflows and returns ONE.
assert_eq!(I128s12::ONE.wrapping_pow(1_000_000), I128s12::ONE);
// MAX^2 wraps to a deterministic but unspecified value.
let _ = I128s12::MAX.wrapping_pow(2);
Source

pub fn saturating_pow(self, exp: u32) -> Self

Returns self^exp, clamping to I128::MAX or I128::MIN on overflow at any step.

On the first step that overflows, the result is clamped based on the sign of the mathematical result: positive overflows clamp to MAX, negative overflows clamp to MIN. The sign of the result is determined by self.signum() and whether exp is odd.

exp = 0 always returns ONE before entering the loop.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::MAX.saturating_pow(2), I128s12::MAX);
assert_eq!(I128s12::ONE.saturating_pow(1_000_000), I128s12::ONE);
Source

pub fn overflowing_pow(self, exp: u32) -> (Self, bool)

Returns (self^exp, overflowed).

overflowed is true if any multiplication step overflowed i128. The returned value is the wrapping form (matches Self::wrapping_pow).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
let (_value, overflowed) = I128s12::MAX.overflowing_pow(2);
assert!(overflowed);
let (value, overflowed) = I128s12::ONE.overflowing_pow(5);
assert!(!overflowed);
assert_eq!(value, I128s12::ONE);
Source§

impl<const SCALE: u32> I128<SCALE>

Source

pub fn sin(self) -> Self

Sine of self, where self is in radians.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// sin(0) == 0 (bit-exact: f64::sin(0.0) == 0.0).
assert_eq!(I128s12::ZERO.sin(), I128s12::ZERO);
Source

pub fn cos(self) -> Self

Cosine of self, where self is in radians.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// cos(0) == 1 (bit-exact: f64::cos(0.0) == 1.0).
assert_eq!(I128s12::ZERO.cos(), I128s12::ONE);
Source

pub fn tan(self) -> Self

Tangent of self, where self is in radians.

f64::tan returns very large magnitudes near odd multiples of pi/2 and infinity at the limit. Inputs that drive the f64 result outside [I128::MIN, I128::MAX] saturate per Self::from_f64_lossy.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// tan(0) == 0 (bit-exact: f64::tan(0.0) == 0.0).
assert_eq!(I128s12::ZERO.tan(), I128s12::ZERO);
Source

pub fn asin(self) -> Self

Arcsine of self. Returns radians in [-pi/2, pi/2].

f64::asin returns NaN for inputs outside [-1, 1], which Self::from_f64_lossy maps to I128::ZERO.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// asin(0) == 0.
assert_eq!(I128s12::ZERO.asin(), I128s12::ZERO);
Source

pub fn acos(self) -> Self

Arccosine of self. Returns radians in [0, pi].

f64::acos returns NaN for inputs outside [-1, 1], which Self::from_f64_lossy maps to I128::ZERO.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::{I128s12, DecimalConsts};
// acos(1) == 0.
assert_eq!(I128s12::ONE.acos(), I128s12::ZERO);
Source

pub fn atan(self) -> Self

Arctangent of self. Returns radians in (-pi/2, pi/2).

Defined for the entire real line.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// atan(0) == 0.
assert_eq!(I128s12::ZERO.atan(), I128s12::ZERO);
Source

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

Four-quadrant arctangent of self (y) over other (x). Returns radians in (-pi, pi].

Signature matches f64::atan2(self, other): the receiver is y and the argument is x.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::{I128s12, DecimalConsts};
// atan2(1, 1) ~= pi/4 (45 degrees, first quadrant).
let one = I128s12::ONE;
let result = one.atan2(one); // approximately I128s12::quarter_pi()
Source

pub fn sinh(self) -> Self

Hyperbolic sine of self.

Defined for the entire real line. Saturates at large magnitudes per Self::from_f64_lossy.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// sinh(0) == 0.
assert_eq!(I128s12::ZERO.sinh(), I128s12::ZERO);
Source

pub fn cosh(self) -> Self

Hyperbolic cosine of self.

Defined for the entire real line; result is always >= 1. Saturates at large magnitudes per Self::from_f64_lossy.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// cosh(0) == 1.
assert_eq!(I128s12::ZERO.cosh(), I128s12::ONE);
Source

pub fn tanh(self) -> Self

Hyperbolic tangent of self.

Defined for the entire real line; range is (-1, 1).

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// tanh(0) == 0.
assert_eq!(I128s12::ZERO.tanh(), I128s12::ZERO);
Source

pub fn asinh(self) -> Self

Inverse hyperbolic sine of self.

Defined for the entire real line.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// asinh(0) == 0.
assert_eq!(I128s12::ZERO.asinh(), I128s12::ZERO);
Source

pub fn acosh(self) -> Self

Inverse hyperbolic cosine of self.

f64::acosh returns NaN for inputs less than 1, which Self::from_f64_lossy maps to I128::ZERO.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// acosh(1) == 0.
assert_eq!(I128s12::ONE.acosh(), I128s12::ZERO);
Source

pub fn atanh(self) -> Self

Inverse hyperbolic tangent of self.

f64::atanh returns NaN for inputs outside (-1, 1), which Self::from_f64_lossy maps to I128::ZERO.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// atanh(0) == 0.
assert_eq!(I128s12::ZERO.atanh(), I128s12::ZERO);
Source

pub fn to_degrees(self) -> Self

Convert radians to degrees: self * (180 / pi).

Routed through f64::to_degrees so results match the de facto reference produced by the rest of the Rust ecosystem. Multiplying by a precomputed I128 factor derived from I128::pi() would diverge from f64 by a 1-LSB rescale rounding without any practical determinism gain, since the f64 bridge is already the precision floor.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// to_degrees(0) == 0.
assert_eq!(I128s12::ZERO.to_degrees(), I128s12::ZERO);
Source

pub fn to_radians(self) -> Self

Convert degrees to radians: self * (pi / 180).

Routed through f64::to_radians. See Self::to_degrees for the rationale.

§Precision

Lossy: involves f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
// to_radians(0) == 0.
assert_eq!(I128s12::ZERO.to_radians(), I128s12::ZERO);

Trait Implementations§

Source§

impl<const SCALE: u32> Add for I128<SCALE>

Source§

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

Add two values of the same scale.

Because both operands are in value * 10^S form, the raw storage values can be added directly with no rescaling.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_500_000_000_000); // 1.5
let b = I128s12::from_bits(2_500_000_000_000); // 2.5
assert_eq!((a + b).to_bits(), 4_000_000_000_000);
Source§

type Output = I128<SCALE>

The resulting type after applying the + operator.
Source§

impl<const SCALE: u32> AddAssign for I128<SCALE>

Source§

fn add_assign(&mut self, rhs: Self)

Add rhs to self in place.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Binary for I128<SCALE>

Source§

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

Formats the raw i128 storage in binary.

See fmt::LowerHex for the storage-versus-value distinction.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

// 10^12 in binary is a 40-bit value.
let s = format!("{:b}", I128s12::ONE);
assert_eq!(s, "1110100011010100101001010001000000000000");
Source§

impl<const SCALE: u32> BitAnd for I128<SCALE>

Source§

fn bitand(self, rhs: Self) -> Self

Bitwise AND of the underlying i128 storage values.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
let a = I128s12::from_bits(0b1100);
let b = I128s12::from_bits(0b1010);
assert_eq!(a & b, I128s12::from_bits(0b1000));
Source§

type Output = I128<SCALE>

The resulting type after applying the & operator.
Source§

impl<const SCALE: u32> BitAndAssign for I128<SCALE>

Source§

fn bitand_assign(&mut self, rhs: Self)

In-place bitwise AND of the underlying i128 storage.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> BitOr for I128<SCALE>

Source§

fn bitor(self, rhs: Self) -> Self

Bitwise OR of the underlying i128 storage values.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
let a = I128s12::from_bits(0b1100);
let b = I128s12::from_bits(0b1010);
assert_eq!(a | b, I128s12::from_bits(0b1110));
Source§

type Output = I128<SCALE>

The resulting type after applying the | operator.
Source§

impl<const SCALE: u32> BitOrAssign for I128<SCALE>

Source§

fn bitor_assign(&mut self, rhs: Self)

In-place bitwise OR of the underlying i128 storage.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> BitXor for I128<SCALE>

Source§

fn bitxor(self, rhs: Self) -> Self

Bitwise XOR of the underlying i128 storage values.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
let a = I128s12::from_bits(0b1100);
let b = I128s12::from_bits(0b1010);
assert_eq!(a ^ b, I128s12::from_bits(0b0110));
Source§

type Output = I128<SCALE>

The resulting type after applying the ^ operator.
Source§

impl<const SCALE: u32> BitXorAssign for I128<SCALE>

Source§

fn bitxor_assign(&mut self, rhs: Self)

In-place bitwise XOR of the underlying i128 storage.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Bounded for I128<SCALE>

Source§

fn min_value() -> Self

Returns the smallest representable value, equal to I128::MIN.

The raw storage is i128::MIN.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Bounded;

assert_eq!(I128s12::min_value(), I128s12::MIN);
Source§

fn max_value() -> Self

Returns the largest representable value, equal to I128::MAX.

The raw storage is i128::MAX.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Bounded;

assert_eq!(I128s12::max_value(), I128s12::MAX);
Source§

impl<const SCALE: u32> CheckedAdd for I128<SCALE>

Source§

fn checked_add(&self, rhs: &Self) -> Option<Self>

Adds rhs to self, returning None on overflow.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedAdd;

let two = I128s12::from_bits(2_000_000_000_000);
assert_eq!(I128s12::ONE.checked_add(I128s12::ONE), Some(two));
assert_eq!(I128s12::MAX.checked_add(I128s12::ONE), None);
Source§

impl<const SCALE: u32> CheckedDiv for I128<SCALE>

Source§

fn checked_div(&self, v: &Self) -> Option<Self>

Divides self by v, returning None on division by zero or overflow.

Delegates to the inherent I128::checked_div method, which uses a 256-bit widening divide. Returns None on division by zero or when the result overflows i128 (the only case is I128::MIN / -ONE). The trait and inherent paths are bit-identical.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedDiv;

let half = I128s12::from_bits(500_000_000_000);
let two = I128s12::from_bits(2_000_000_000_000);
let quarter = I128s12::from_bits(250_000_000_000);
assert_eq!(half.checked_div(two), Some(quarter));
assert_eq!(I128s12::ONE.checked_div(I128s12::ZERO), None);
Source§

impl<const SCALE: u32> CheckedMul for I128<SCALE>

Source§

fn checked_mul(&self, v: &Self) -> Option<Self>

Multiplies self by v, returning None when the result overflows i128.

Delegates to the inherent I128::checked_mul method, which uses a 256-bit intermediate product so that only the final result needs to fit in i128. Returns None only when the quotient after rescaling overflows. The trait and inherent paths are bit-identical.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedMul;

let half = I128s12::from_bits(500_000_000_000);
let quarter = I128s12::from_bits(250_000_000_000);
assert_eq!(half.checked_mul(half), Some(quarter));

let two = I128s12::from_bits(2_000_000_000_000);
assert_eq!(I128s12::MAX.checked_mul(two), None);
Source§

impl<const SCALE: u32> CheckedNeg for I128<SCALE>

Source§

fn checked_neg(&self) -> Option<Self>

Negates self, returning None for I128::MIN.

i128::MIN has no positive counterpart in two’s-complement, so negating it overflows. All other values succeed.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedNeg;

assert_eq!(I128s12::ONE.checked_neg(), Some(-I128s12::ONE));
assert_eq!(I128s12::ZERO.checked_neg(), Some(I128s12::ZERO));
assert_eq!(I128s12::MIN.checked_neg(), None);
Source§

impl<const SCALE: u32> CheckedRem for I128<SCALE>

Source§

fn checked_rem(&self, rhs: &Self) -> Option<Self>

Computes self % rhs, returning None when rhs is zero.

Because both operands share the same SCALE, no rescaling is needed. Delegates directly to i128::checked_rem.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedRem;

let a = I128s12::from_bits(5_500_000_000_000); // 5.5
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
let expected = I128s12::from_bits(1_500_000_000_000); // 1.5
assert_eq!(a.checked_rem(b), Some(expected));
assert_eq!(a.checked_rem(I128s12::ZERO), None);
Source§

impl<const SCALE: u32> CheckedSub for I128<SCALE>

Source§

fn checked_sub(&self, rhs: &Self) -> Option<Self>

Subtracts rhs from self, returning None on underflow.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::CheckedSub;

let three = I128s12::from_bits(3_000_000_000_000);
let two = I128s12::from_bits(2_000_000_000_000);
assert_eq!(three.checked_sub(two), Some(I128s12::ONE));
assert_eq!(I128s12::MIN.checked_sub(I128s12::ONE), None);
Source§

impl<const SCALE: u32> Clone for I128<SCALE>

Source§

fn clone(&self) -> I128<SCALE>

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<const SCALE: u32> Debug for I128<SCALE>

Source§

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

Formats as I128<SCALE>(<canonical decimal>).

Delegates to fmt::Display so the output shows the human-readable decimal value rather than the raw i128 storage.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let v = I128s12::from_bits(1_500_000_000_000);
assert_eq!(format!("{v:?}"), "I128<12>(1.500000000000)");
Source§

impl<const SCALE: u32> DecimalConsts for I128<SCALE>

Source§

fn pi() -> Self

Pi (~3.14159265…). One half-turn in radians. Read more
Source§

fn tau() -> Self

Tau (~6.28318530…). One full turn in radians. Read more
Source§

fn half_pi() -> Self

Half-pi (~1.57079632…). One quarter-turn in radians. Read more
Source§

fn quarter_pi() -> Self

Quarter-pi (~0.78539816…). One eighth-turn in radians. Read more
Source§

fn golden() -> Self

The golden ratio (~1.61803398…). Dimensionless. Read more
Source§

fn e() -> Self

Euler’s number (~2.71828182…). Dimensionless. Read more
Source§

impl<const SCALE: u32> Default for I128<SCALE>

Default returns ZERO, matching i128::default() == 0.

This lets #[derive(Default)] work correctly on structs that contain I128<S> fields.

Source§

fn default() -> Self

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

impl<'de, const SCALE: u32> Deserialize<'de> for I128<SCALE>

Source§

fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>

Deserialise from a base-10 integer string (human-readable formats), 16 little-endian bytes (binary formats), or a native integer (self-describing binary formats such as CBOR).

Human-readable formats route via deserialize_any so a JSON string, JSON number, or TOML integer all reach the correct visitor branch. Binary formats that are not self-describing (postcard, bincode) route via deserialize_bytes directly.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Display for I128<SCALE>

Source§

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

Formats the value as a canonical decimal string.

Always emits exactly SCALE fractional digits. The integer and fractional parts are derived from integer division of the unsigned magnitude, so i128::MIN (whose absolute value overflows i128) is handled correctly via unsigned_abs.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let v = I128s12::from_bits(1_500_000_000_000);
assert_eq!(v.to_string(), "1.500000000000");

let neg = I128s12::from_bits(-1_500_000_000_000);
assert_eq!(neg.to_string(), "-1.500000000000");
Source§

impl<const SCALE: u32> Div for I128<SCALE>

Source§

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

Divide self by rhs, rescaling the numerator to keep the result in value * 10^S form.

The numerator self.0 is widened to 256 bits and multiplied by 10^SCALE before dividing by rhs.0. This avoids the intermediate overflow that would occur with a naive (self.0 * 10^S) / rhs.0 approach at large dividend magnitudes.

§Panics

Panics on division by zero (matching i128 /). Also panics in debug builds when the final quotient overflows i128; wraps in release builds.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(3_000_000_000_000); // 3.0
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!((a / b).to_bits(), 1_500_000_000_000); // 1.5
Source§

type Output = I128<SCALE>

The resulting type after applying the / operator.
Source§

impl<const SCALE: u32> DivAssign for I128<SCALE>

Source§

fn div_assign(&mut self, rhs: Self)

Divide self by rhs in place.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> From<i16> for I128<SCALE>

Source§

fn from(value: i16) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 33.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_i16).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> From<i32> for I128<SCALE>

Source§

fn from(value: i32) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 28.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_i32).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> From<i64> for I128<SCALE>

Source§

fn from(value: i64) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 19. At SCALE = 12 all i64 values fit with roughly six orders of magnitude of headroom before i128::MAX.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_i64).to_bits(), 1_000_000_000_000);
assert_eq!(I128s12::from(-1_i64).to_bits(), -1_000_000_000_000);
Source§

impl<const SCALE: u32> From<i8> for I128<SCALE>

Source§

fn from(value: i8) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 36 (since i8::MAX * 10^36 < i128::MAX).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_i8).to_bits(), 1_000_000_000_000);
assert_eq!(I128s12::from(-1_i8).to_bits(), -1_000_000_000_000);
Source§

impl<const SCALE: u32> From<u16> for I128<SCALE>

Source§

fn from(value: u16) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 33.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_u16).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> From<u32> for I128<SCALE>

Source§

fn from(value: u32) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 28.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_u32).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> From<u64> for I128<SCALE>

Source§

fn from(value: u64) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 19. At SCALE = 12 the worst-case product is u64::MAX * 10^12 (~1.8e31), well under i128::MAX (~1.7e38).

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_u64).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> From<u8> for I128<SCALE>

Source§

fn from(value: u8) -> Self

Converts value by scaling it to value * 10^SCALE.

Lossless for all SCALE < 36.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(I128s12::from(1_u8).to_bits(), 1_000_000_000_000);
Source§

impl<const SCALE: u32> FromPrimitive for I128<SCALE>

Source§

fn from_i64(n: i64) -> Option<Self>

Constructs a I128<SCALE> from an i64 integer value.

Scales n by 10^SCALE. Returns None when the multiplication overflows i128, which can occur at pathologically large scale values. At SCALE <= 18 the call always succeeds for any i64.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_i64(0), Some(I128s12::ZERO));
assert_eq!(I128s12::from_i64(1), Some(I128s12::ONE));
assert_eq!(I128s12::from_i64(-42), Some(I128s12::from_bits(-42_000_000_000_000)));
Source§

fn from_u64(n: u64) -> Option<Self>

Constructs a I128<SCALE> from a u64 integer value.

Scales n by 10^SCALE. Returns None on overflow. At SCALE <= 18 the call always succeeds for any u64.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_u64(0), Some(I128s12::ZERO));
assert_eq!(I128s12::from_u64(42), Some(I128s12::from_bits(42_000_000_000_000)));
Source§

fn from_i128(n: i128) -> Option<Self>

Constructs a I128<SCALE> from an i128 integer value.

Returns None when scaling overflows. Delegates to the existing TryFrom<i128> implementation.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_i128(7), Some(I128s12::from_bits(7_000_000_000_000)));
assert_eq!(I128s12::from_i128(i128::MAX), None);
Source§

fn from_u128(n: u128) -> Option<Self>

Constructs a I128<SCALE> from a u128 integer value.

Returns None when n > i128::MAX or when scaling overflows. Delegates to the existing TryFrom<u128> implementation.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_u128(99), Some(I128s12::from_bits(99_000_000_000_000)));
assert_eq!(I128s12::from_u128(u128::MAX), None);
Source§

fn from_f32(n: f32) -> Option<Self>

Constructs a I128<SCALE> from an f32 value.

Returns None for NaN, infinities, or finite values whose scaled representation overflows i128. Delegates to the existing TryFrom<f32> implementation.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_f32(0.0), Some(I128s12::ZERO));
assert_eq!(I128s12::from_f32(1.0), Some(I128s12::ONE));
assert_eq!(I128s12::from_f32(f32::NAN), None);
assert_eq!(I128s12::from_f32(f32::INFINITY), None);
Source§

fn from_f64(n: f64) -> Option<Self>

Constructs a I128<SCALE> from an f64 value.

Returns None for NaN, infinities, or finite values whose scaled representation overflows i128. Delegates to the existing TryFrom<f64> implementation.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
use num_traits::FromPrimitive;

assert_eq!(I128s12::from_f64(0.0), Some(I128s12::ZERO));
assert_eq!(I128s12::from_f64(1.0), Some(I128s12::ONE));
assert_eq!(I128s12::from_f64(f64::NAN), None);
assert_eq!(I128s12::from_f64(1e30), None);
Source§

fn from_isize(n: isize) -> Option<Self>

Converts an isize to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_i8(n: i8) -> Option<Self>

Converts an i8 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_i16(n: i16) -> Option<Self>

Converts an i16 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_i32(n: i32) -> Option<Self>

Converts an i32 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_usize(n: usize) -> Option<Self>

Converts a usize to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_u8(n: u8) -> Option<Self>

Converts an u8 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_u16(n: u16) -> Option<Self>

Converts an u16 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

fn from_u32(n: u32) -> Option<Self>

Converts an u32 to return an optional value of this type. If the value cannot be represented by this type, then None is returned.
Source§

impl<const SCALE: u32> FromStr for I128<SCALE>

Source§

fn from_str(s: &str) -> Result<Self, Self::Err>

Parses a canonical decimal literal into I128<SCALE>.

Delegates to the internal parser. See the module-level docs for the full list of accepted and rejected forms, and ParseDecimalError for the failure variants.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let v: I128s12 = "1.5".parse().unwrap();
assert_eq!(v.to_bits(), 1_500_000_000_000);

let neg: I128s12 = "-1.5".parse().unwrap();
assert_eq!(neg.to_bits(), -1_500_000_000_000);
Source§

type Err = ParseDecimalError

The associated error which can be returned from parsing.
Source§

impl<const SCALE: u32> Hash for I128<SCALE>

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<const SCALE: u32> LowerExp for I128<SCALE>

Source§

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

Formats the value in scientific notation with a lowercase e.

Trailing zeros in the mantissa are stripped, so 1.500000000000 formats as 1.5e0. Zero formats as 0e0.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let v = I128s12::from_bits(1_500_000_000_000);
assert_eq!(format!("{v:e}"), "1.5e0");

let sub = I128s12::from_bits(1_500_000_000);
assert_eq!(format!("{sub:e}"), "1.5e-3");
Source§

impl<const SCALE: u32> LowerHex for I128<SCALE>

Source§

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

Formats the raw i128 storage (= value * 10^SCALE) as lowercase hex.

This is a bit-level view of the storage, not a hex encoding of the decimal value. All standard format flags (#, 0, width, precision) are forwarded to the underlying i128 formatter.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

// Storage for 1.0 at SCALE=12 is 10^12 = 0xe8d4a51000.
assert_eq!(format!("{:x}", I128s12::ONE), "e8d4a51000");
Source§

impl<const SCALE: u32> Mul for I128<SCALE>

Source§

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

Multiply two values, rescaling the result back to value * 10^S form.

The raw product a.0 * b.0 has units 10^(2S), so it must be divided by 10^S to restore the canonical scale. This is done via a 256-bit widening intermediate and a Moller-Granlund magic-number divide (see the mg_divide module), which avoids the intermediate overflow that would occur with a naive i128 multiply at large operand magnitudes.

§Panics

Panics in debug builds when the final rescaled quotient overflows i128::MAX. In release builds the result wraps two’s-complement.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(1_500_000_000_000); // 1.5
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!((a * b).to_bits(), 3_000_000_000_000); // 3.0
Source§

type Output = I128<SCALE>

The resulting type after applying the * operator.
Source§

impl<const SCALE: u32> MulAssign for I128<SCALE>

Source§

fn mul_assign(&mut self, rhs: Self)

Multiply self by rhs in place.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Neg for I128<SCALE>

Source§

fn neg(self) -> Self

Negate the value.

Negates the raw i128 storage directly; no rescaling needed.

§Panics

Panics in debug builds when self == I128::MIN because i128::MIN has no positive counterpart in two’s-complement. In release builds the result wraps to i128::MIN.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let x = I128s12::from_bits(1_500_000_000_000); // 1.5
assert_eq!((-x).to_bits(), -1_500_000_000_000);
Source§

type Output = I128<SCALE>

The resulting type after applying the - operator.
Source§

impl<const SCALE: u32> Not for I128<SCALE>

Source§

fn not(self) -> Self

Bitwise complement of the underlying i128 storage (flip every bit).

!I128::ZERO produces I128::from_bits(-1) (all-ones in two’s complement).

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
assert_eq!(!I128s12::ZERO, I128s12::from_bits(-1));
assert_eq!(!I128s12::from_bits(-1), I128s12::ZERO);
Source§

type Output = I128<SCALE>

The resulting type after applying the ! operator.
Source§

impl<const SCALE: u32> Num for I128<SCALE>

Source§

fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr>

Parses a decimal string in the given radix.

Only radix == 10 is supported; I128<SCALE> is a base-10 type by construction. Any other radix returns ParseDecimalError::InvalidChar without attempting to parse the string.

For radix == 10 the call delegates to the core::str::FromStr implementation on I128<SCALE>.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Num;

let v = I128s12::from_str_radix("1", 10).expect("parse 1");
assert_eq!(v, I128s12::ONE);

assert!(I128s12::from_str_radix("1", 16).is_err());
Source§

type FromStrRadixErr = ParseDecimalError

Source§

impl<const SCALE: u32> NumCast for I128<SCALE>

Source§

fn from<T: ToPrimitive>(n: T) -> Option<Self>

Casts any T: ToPrimitive value to I128<SCALE>.

Uses the f64 conversion path for inputs that carry fractional information, and the i128 path for integer-shaped inputs. The integer path is taken when (to_i128() as f64) == to_f64(), which holds for true integer types even when their magnitude exceeds f64’s exact-integer range of 2^53. Returns None when neither path produces a representable value.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
use num_traits::NumCast;

let from_int: I128s12 = NumCast::from(42_i32).unwrap();
assert_eq!(from_int, I128s12::from_bits(42_000_000_000_000));

let from_float: I128s12 = NumCast::from(1.5_f64).unwrap();
assert_eq!(from_float, I128s12::from_f64_lossy(1.5));

let nan: Option<I128s12> = NumCast::from(f64::NAN);
assert!(nan.is_none());
Source§

impl<const SCALE: u32> Octal for I128<SCALE>

Source§

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

Formats the raw i128 storage in octal.

See fmt::LowerHex for the storage-versus-value distinction.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(format!("{:o}", I128s12::ZERO), "0");
Source§

impl<const SCALE: u32> One for I128<SCALE>

Source§

fn one() -> Self

Returns the multiplicative identity for I128<SCALE>.

Equivalent to I128::ONE.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::One;

assert_eq!(I128s12::one(), I128s12::ONE);
Source§

fn is_one(&self) -> bool

Returns true if self equals the multiplicative identity.

Provided explicitly rather than relying on the default so that the check is a single integer comparison instead of going through the multiplication chain.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::One;

assert!(I128s12::ONE.is_one());
assert!(!I128s12::ZERO.is_one());
Source§

fn set_one(&mut self)

Sets self to the multiplicative identity element of Self, 1.
Source§

impl<const SCALE: u32> Ord for I128<SCALE>

Source§

fn cmp(&self, other: &I128<SCALE>) -> 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<const SCALE: u32> PartialEq for I128<SCALE>

Source§

fn eq(&self, other: &I128<SCALE>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

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

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<const SCALE: u32> PartialOrd for I128<SCALE>

Source§

fn partial_cmp(&self, other: &I128<SCALE>) -> 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<const SCALE: u32> Rem for I128<SCALE>

Source§

fn rem(self, rhs: Self) -> Self

Compute the remainder of dividing self by rhs, truncated toward zero.

Because both operands share the same SCALE, the raw remainder self.0 % rhs.0 already lives in value * 10^S form without any rescaling. Behavior matches i128 %: the result has the same sign as the dividend.

§Panics

Panics on rhs == ZERO (division by zero), matching i128 %.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(5_500_000_000_000); // 5.5
let b = I128s12::from_bits(2_000_000_000_000); // 2.0
assert_eq!((a % b).to_bits(), 1_500_000_000_000); // 1.5
Source§

type Output = I128<SCALE>

The resulting type after applying the % operator.
Source§

impl<const SCALE: u32> RemAssign for I128<SCALE>

Source§

fn rem_assign(&mut self, rhs: Self)

Compute the remainder of self / rhs and store it in self.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Serialize for I128<SCALE>

Source§

fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>

Serialise self as a base-10 integer string for human-readable formats, or as 16 little-endian bytes for binary formats.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Shl<u32> for I128<SCALE>

Source§

fn shl(self, n: u32) -> Self

Left-shift the underlying i128 storage by n bits.

Operates on raw bits, not the logical decimal value. Delegates to i128 << n.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

Panics in debug builds when n >= 128; wraps modulo 128 in release builds (standard Rust integer-shift contract).

§Examples
use decimal_scaled::I128s12;
assert_eq!(I128s12::from_bits(1) << 3u32, I128s12::from_bits(8));
Source§

type Output = I128<SCALE>

The resulting type after applying the << operator.
Source§

impl<const SCALE: u32> ShlAssign<u32> for I128<SCALE>

Source§

fn shl_assign(&mut self, n: u32)

In-place left-shift of the underlying i128 storage by n bits.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Shr<u32> for I128<SCALE>

Source§

fn shr(self, n: u32) -> Self

Arithmetic (sign-extending) right-shift of the underlying i128 storage by n bits.

Negative values remain negative: the vacated high bits are filled with the sign bit (ones for negative, zero for non-negative). Use I128::unsigned_shr for a logical (zero-fill) right shift.

Operates on raw bits, not the logical decimal value. Delegates to i128 >> n.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Panics

Panics in debug builds when n >= 128; wraps modulo 128 in release builds.

§Examples
use decimal_scaled::I128s12;
// Arithmetic shift: -8 >> 1 == -4.
assert_eq!(I128s12::from_bits(-8) >> 1u32, I128s12::from_bits(-4));
Source§

type Output = I128<SCALE>

The resulting type after applying the >> operator.
Source§

impl<const SCALE: u32> ShrAssign<u32> for I128<SCALE>

Source§

fn shr_assign(&mut self, n: u32)

In-place arithmetic (sign-extending) right-shift of the underlying i128 storage by n bits.

Operates on raw bits, not the logical decimal value.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> Signed for I128<SCALE>

Source§

fn abs(&self) -> Self

Returns the absolute value of self.

Delegates to the inherent I128::abs method.

§Panics

Panics in debug mode when called on I128::MIN because the positive counterpart of i128::MIN is not representable. In release mode the result wraps.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Signed;

let pos = I128s12::from_bits(1_500_000_000_000);
let neg = I128s12::from_bits(-1_500_000_000_000);
assert_eq!(neg.abs(), pos);
Source§

fn signum(&self) -> Self

Returns the sign of self as a scaled I128: -ONE, ZERO, or +ONE.

Delegates to the inherent I128::signum method.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Signed;

assert_eq!(I128s12::from_bits(5).signum(), I128s12::ONE);
assert_eq!(I128s12::from_bits(-5).signum(), -I128s12::ONE);
assert_eq!(I128s12::ZERO.signum(), I128s12::ZERO);
Source§

fn is_positive(&self) -> bool

Returns true if self is strictly greater than zero.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Signed;

assert!(I128s12::ONE.is_positive());
assert!(!I128s12::ZERO.is_positive());
assert!(!(-I128s12::ONE).is_positive());
Source§

fn is_negative(&self) -> bool

Returns true if self is strictly less than zero.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Signed;

assert!((-I128s12::ONE).is_negative());
assert!(!I128s12::ZERO.is_negative());
assert!(!I128s12::ONE.is_negative());
Source§

fn abs_sub(&self, other: &Self) -> Self

Returns self - other when self > other, otherwise ZERO.

Matches the num_traits::Signed::abs_sub contract: the result is never negative. This is not the same as (self - other).abs().

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Signed;

let two = I128s12::from_bits(2_000_000_000_000);
let five = I128s12::from_bits(5_000_000_000_000);
let three = I128s12::from_bits(3_000_000_000_000);

assert_eq!(five.abs_sub(&two), three);
assert_eq!(two.abs_sub(&five), I128s12::ZERO);
assert_eq!(five.abs_sub(&five), I128s12::ZERO);
Source§

impl<const SCALE: u32> Sub for I128<SCALE>

Source§

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

Subtract rhs from self.

No rescaling needed; raw storage values are subtracted directly.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let a = I128s12::from_bits(3_000_000_000_000); // 3.0
let b = I128s12::from_bits(1_500_000_000_000); // 1.5
assert_eq!((a - b).to_bits(), 1_500_000_000_000);
Source§

type Output = I128<SCALE>

The resulting type after applying the - operator.
Source§

impl<const SCALE: u32> SubAssign for I128<SCALE>

Source§

fn sub_assign(&mut self, rhs: Self)

Subtract rhs from self in place.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

Source§

impl<const SCALE: u32> ToPrimitive for I128<SCALE>

Source§

fn to_i64(&self) -> Option<i64>

Converts self to i64 by truncating the fractional part toward zero.

Returns None when the integer part of self falls outside i64’s range. Unlike to_int_lossy, which saturates, this method is contractually fallible.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

let v = I128s12::from_bits(2_500_000_000_000); // 2.5
assert_eq!(v.to_i64(), Some(2));
assert_eq!(I128s12::MAX.to_i64(), None);
Source§

fn to_u64(&self) -> Option<u64>

Converts self to u64 by truncating the fractional part toward zero.

Returns None for negative values and for values whose integer part exceeds u64::MAX.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

let v = I128s12::from_bits(42_000_000_000_000);
assert_eq!(v.to_u64(), Some(42));
assert_eq!((-I128s12::ONE).to_u64(), None);
Source§

fn to_i128(&self) -> Option<i128>

Converts self to i128 by truncating the fractional part toward zero.

Always returns Some because self.0 / 10^SCALE fits in i128 by construction.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

let v = I128s12::from_bits(42_000_000_000_000);
assert_eq!(v.to_i128(), Some(42));
assert!(I128s12::MAX.to_i128().is_some());
Source§

fn to_u128(&self) -> Option<u128>

Converts self to u128 by truncating the fractional part toward zero.

Returns None for negative values.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

assert_eq!(I128s12::ZERO.to_u128(), Some(0));
assert_eq!(I128s12::from_bits(-1).to_u128(), None);
Source§

fn to_f32(&self) -> Option<f32>

Converts self to f32.

Uses the I128::to_f32_lossy helper. Always returns Some; the result may be +/-inf for very large magnitudes.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

let v = I128s12::from_bits(1_500_000_000_000); // 1.5
assert_eq!(v.to_f32(), Some(1.5_f32));
Source§

fn to_f64(&self) -> Option<f64>

Converts self to f64.

Uses the I128::to_f64_lossy helper. Always returns Some; the result may be +/-inf for very large magnitudes.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::I128s12;
use num_traits::ToPrimitive;

let v = I128s12::from_bits(1_500_000_000_000); // 1.5
assert_eq!(v.to_f64(), Some(1.5_f64));
Source§

fn to_isize(&self) -> Option<isize>

Converts the value of self to an isize. If the value cannot be represented by an isize, then None is returned.
Source§

fn to_i8(&self) -> Option<i8>

Converts the value of self to an i8. If the value cannot be represented by an i8, then None is returned.
Source§

fn to_i16(&self) -> Option<i16>

Converts the value of self to an i16. If the value cannot be represented by an i16, then None is returned.
Source§

fn to_i32(&self) -> Option<i32>

Converts the value of self to an i32. If the value cannot be represented by an i32, then None is returned.
Source§

fn to_usize(&self) -> Option<usize>

Converts the value of self to a usize. If the value cannot be represented by a usize, then None is returned.
Source§

fn to_u8(&self) -> Option<u8>

Converts the value of self to a u8. If the value cannot be represented by a u8, then None is returned.
Source§

fn to_u16(&self) -> Option<u16>

Converts the value of self to a u16. If the value cannot be represented by a u16, then None is returned.
Source§

fn to_u32(&self) -> Option<u32>

Converts the value of self to a u32. If the value cannot be represented by a u32, then None is returned.
Source§

impl<const SCALE: u32> TryFrom<f32> for I128<SCALE>

Source§

fn try_from(value: f32) -> Result<Self, Self::Error>

Widens value to f64 and delegates to TryFrom<f64>.

Returns Err(NotFinite) for NaN and the infinities; Err(Overflow) for finite values whose magnitude exceeds I128::MAX after scaling.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::{I128s12, DecimalConvertError};

let v: I128s12 = 1.0_f32.try_into().unwrap();
assert_eq!(v, I128s12::ONE);

let nan: Result<I128s12, _> = f32::NAN.try_into();
assert_eq!(nan, Err(DecimalConvertError::NotFinite));
Source§

type Error = DecimalConvertError

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

impl<const SCALE: u32> TryFrom<f64> for I128<SCALE>

Source§

fn try_from(value: f64) -> Result<Self, Self::Error>

Multiplies value by 10^SCALE in f64 and truncates to i128.

Returns Err(NotFinite) for NaN/inf, and Err(Overflow) for finite inputs whose scaled value falls outside [i128::MIN, i128::MAX).

Note: i128::MAX as f64 rounds up to 2^127 because i128::MAX (2^127 - 1) is not exactly representable in f64. The range check uses a strict < on the upper bound to reject 2^127 itself.

§Precision

Lossy: involves f32 or f64 at some point; result may lose precision.

§Examples
use decimal_scaled::{I128s12, DecimalConvertError};

let v: I128s12 = 1.0_f64.try_into().unwrap();
assert_eq!(v, I128s12::ONE);

let nan: Result<I128s12, _> = f64::NAN.try_into();
assert_eq!(nan, Err(DecimalConvertError::NotFinite));

let overflow: Result<I128s12, _> = 1e30_f64.try_into();
assert_eq!(overflow, Err(DecimalConvertError::Overflow));
Source§

type Error = DecimalConvertError

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

impl<const SCALE: u32> TryFrom<i128> for I128<SCALE>

Source§

fn try_from(value: i128) -> Result<Self, Self::Error>

Scales value by 10^SCALE using checked multiplication.

Returns Err(Overflow) if the product exceeds i128::MAX or falls below i128::MIN.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::{I128s12, DecimalConvertError};

let v: I128s12 = 1_i128.try_into().unwrap();
assert_eq!(v, I128s12::ONE);

let overflow: Result<I128s12, _> = i128::MAX.try_into();
assert_eq!(overflow, Err(DecimalConvertError::Overflow));
Source§

type Error = DecimalConvertError

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

impl<const SCALE: u32> TryFrom<u128> for I128<SCALE>

Source§

fn try_from(value: u128) -> Result<Self, Self::Error>

Converts value to i128, then scales by 10^SCALE.

Returns Err(Overflow) if value > i128::MAX or if the scaled product overflows i128.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::{I128s12, DecimalConvertError};

let v: I128s12 = 42_u128.try_into().unwrap();
assert_eq!(v.to_bits(), 42_000_000_000_000);

let overflow: Result<I128s12, _> = u128::MAX.try_into();
assert_eq!(overflow, Err(DecimalConvertError::Overflow));
Source§

type Error = DecimalConvertError

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

impl<const SCALE: u32> UpperExp for I128<SCALE>

Source§

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

Formats the value in scientific notation with an uppercase E.

Identical to fmt::LowerExp except the exponent separator is E.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

let v = I128s12::from_bits(1_500_000_000_000);
assert_eq!(format!("{v:E}"), "1.5E0");
Source§

impl<const SCALE: u32> UpperHex for I128<SCALE>

Source§

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

Formats the raw i128 storage as uppercase hex.

See fmt::LowerHex for the storage-versus-value distinction.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;

assert_eq!(format!("{:X}", I128s12::ONE), "E8D4A51000");
Source§

impl<const SCALE: u32> Zero for I128<SCALE>

Source§

fn zero() -> Self

Returns the additive identity for I128<SCALE>.

Equivalent to I128::ZERO.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Zero;

assert_eq!(I128s12::zero(), I128s12::ZERO);
Source§

fn is_zero(&self) -> bool

Returns true if self equals the additive identity.

§Precision

Strict: all arithmetic is integer-only; result is bit-exact.

§Examples
use decimal_scaled::I128s12;
use num_traits::Zero;

assert!(I128s12::ZERO.is_zero());
assert!(!I128s12::ONE.is_zero());
Source§

fn set_zero(&mut self)

Sets self to the additive identity element of Self, 0.
Source§

impl<const SCALE: u32> Copy for I128<SCALE>

Source§

impl<const SCALE: u32> Eq for I128<SCALE>

Source§

impl<const SCALE: u32> StructuralPartialEq for I128<SCALE>

Auto Trait Implementations§

§

impl<const SCALE: u32> Freeze for I128<SCALE>

§

impl<const SCALE: u32> RefUnwindSafe for I128<SCALE>

§

impl<const SCALE: u32> Send for I128<SCALE>

§

impl<const SCALE: u32> Sync for I128<SCALE>

§

impl<const SCALE: u32> Unpin for I128<SCALE>

§

impl<const SCALE: u32> UnsafeUnpin for I128<SCALE>

§

impl<const SCALE: u32> UnwindSafe for I128<SCALE>

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> LowerBounded for T
where T: Bounded,

Source§

fn min_value() -> T

Returns the smallest finite number this type can represent
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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.
Source§

impl<T> UpperBounded for T
where T: Bounded,

Source§

fn max_value() -> T

Returns the largest finite number this type can represent
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> NumAssign for T
where T: Num + NumAssignOps,

Source§

impl<T, Rhs> NumAssignOps<Rhs> for T
where T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>,

Source§

impl<T, Rhs, Output> NumOps<Rhs, Output> for T
where T: Sub<Rhs, Output = Output> + Mul<Rhs, Output = Output> + Div<Rhs, Output = Output> + Add<Rhs, Output = Output> + Rem<Rhs, Output = Output>,