Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/types/decimal/coefficient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@ impl Coefficient {
self.repr.is_zero()
}

/// Returns `true` if this value is stored without a heap allocation.
///
/// Magnitudes that fit in 126 bits are stored inline; larger magnitudes are heap-allocated.
/// This reflects the current in-memory representation, which may change.
#[cfg(feature = "experimental")]
#[inline]
pub fn is_inline(&self) -> bool {
self.repr.is_inline()
}

/// Returns the coefficient as an `Int`, or `None` for negative zero.
///
/// This is a **lossless** query, not a value query: an `Int` cannot represent negative zero,
Expand Down Expand Up @@ -332,4 +342,22 @@ mod coefficient_tests {
"Coefficient(-340282366920938463463374607431768211456)"
);
}

#[cfg(feature = "experimental")]
#[rstest::rstest]
#[case::zero(Coefficient::ZERO, true)]
#[case::negative_zero(Coefficient::NEGATIVE_ZERO, true)]
#[case::max_inline(Coefficient::new((1u128 << 126) - 1), true)]
#[case::negative_max_inline(
Coefficient::from_sign_and_value(Sign::Negative, (1u128 << 126) - 1),
true
)]
#[case::smallest_heap(Coefficient::new(1u128 << 126), false)]
#[case::negative_smallest_heap(
Coefficient::from_sign_and_value(Sign::Negative, 1u128 << 126),
false
)]
fn coefficient_is_inline(#[case] value: Coefficient, #[case] expected: bool) {
assert_eq!(value.is_inline(), expected);
}
}
25 changes: 25 additions & 0 deletions src/types/decimal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ impl Decimal {
self.coefficient.is_zero()
}

/// Returns `true` if this value is stored without a heap allocation.
///
/// Coefficient magnitudes that fit in 126 bits are stored inline; larger magnitudes are
/// heap-allocated. This reflects the current in-memory representation, which may change.
#[cfg(feature = "experimental")]
#[inline]
pub fn is_inline(&self) -> bool {
self.coefficient.is_inline()
}

/// Returns true if this Decimal's coefficient has a negative sign AND a magnitude greater than
/// zero. Otherwise, returns false. (Negative zero returns false.)
pub fn is_less_than_zero(&self) -> bool {
Expand Down Expand Up @@ -1041,4 +1051,19 @@ mod decimal_tests {
assert_eq!(c.cmp(&d), Ordering::Greater);
assert_eq!(d.cmp(&c), Ordering::Less);
}

#[cfg(feature = "experimental")]
#[rstest]
#[case::zero(Decimal::ZERO, true)]
#[case::negative_zero(Decimal::NEGATIVE_ZERO, true)]
#[case::small(Decimal::new(-123, -2), true)]
#[case::max_inline(Decimal::new((1u128 << 126) - 1, 5), true)]
#[case::smallest_heap(Decimal::new(1u128 << 126, 5), false)]
#[case::negative_smallest_heap(
Decimal::new(Coefficient::from_sign_and_value(Sign::Negative, 1u128 << 126), -5),
false
)]
fn decimal_is_inline(#[case] value: Decimal, #[case] expected: bool) {
assert_eq!(value.is_inline(), expected);
}
}
44 changes: 44 additions & 0 deletions src/types/integer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ impl UInt {
pub fn is_zero(&self) -> bool {
self.data.is_zero()
}

/// Returns `true` if this value is stored without a heap allocation.
///
/// Magnitudes that fit in 126 bits are stored inline; larger magnitudes are heap-allocated.
/// This reflects the current in-memory representation, which may change.
#[cfg(feature = "experimental")]
#[inline]
pub fn is_inline(&self) -> bool {
self.data.is_inline()
}
}

// This macro makes it possible to turn unsigned int primitives into a UInteger using `.into()`.
Expand Down Expand Up @@ -383,6 +393,16 @@ impl Int {
self.data.is_zero()
}

/// Returns `true` if this value is stored without a heap allocation.
///
/// Magnitudes that fit in 126 bits are stored inline; larger magnitudes are heap-allocated.
/// This reflects the current in-memory representation, which may change.
#[cfg(feature = "experimental")]
#[inline]
pub fn is_inline(&self) -> bool {
self.data.is_inline()
}

/// Returns the negation of this value.
#[allow(clippy::should_implement_trait)]
pub fn neg(self) -> Self {
Expand Down Expand Up @@ -1065,4 +1085,28 @@ mod integer_tests {
assert_eq!(UInt::try_from(int), Ok(uint));
assert!(UInt::try_from(Int::from(-1)).is_err());
}

#[cfg(feature = "experimental")]
#[rstest]
#[case::zero(Int::ZERO, true)]
#[case::max_inline(Int::from((1i128 << 126) - 1), true)]
#[case::min_inline(Int::from(-((1i128 << 126) - 1)), true)]
#[case::smallest_heap(Int::from(1i128 << 126), false)]
#[case::negative_smallest_heap(Int::from(-(1i128 << 126)), false)]
#[case::i128_min(Int::from(i128::MIN), false)]
#[case::beyond_u128(Int::from(UInt::from_le_bytes(&[0xFF; 17])), false)]
fn int_is_inline(#[case] value: Int, #[case] expected: bool) {
assert_eq!(value.is_inline(), expected);
}

#[cfg(feature = "experimental")]
#[rstest]
#[case::zero(UInt::ZERO, true)]
#[case::max_inline(UInt::from((1u128 << 126) - 1), true)]
#[case::smallest_heap(UInt::from(1u128 << 126), false)]
#[case::u128_max(UInt::from(u128::MAX), false)]
#[case::beyond_u128(UInt::from_le_bytes(&[0xFF; 17]), false)]
fn uint_is_inline(#[case] value: UInt, #[case] expected: bool) {
assert_eq!(value.is_inline(), expected);
}
}
2 changes: 1 addition & 1 deletion src/types/overflowing_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl OverflowingInt {
}

#[inline]
fn is_inline(&self) -> bool {
pub(crate) fn is_inline(&self) -> bool {
(self.raw0() >> TAG_BIT) & 1 == 1
}

Expand Down
Loading