code/primitives/share-pool/src/lib.rs

lib.rs

1,646 lines · 58,358 bytes · 19a6485969RawGitHub
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::result_unit_err, clippy::indexing_slicing)]

use codec::{Decode, Encode};
#[cfg(not(feature = "std"))]
use num_traits::float::FloatCore as _;
use scale_info::TypeInfo;
use sp_core::U256;
use sp_std::marker;
use sp_std::ops::Neg;
use substrate_fixed::types::U64F64;
use subtensor_macros::freeze_struct;

// Maximum mantissa that can be used with SafeFloat
pub const SAFE_FLOAT_MAX: u128 = 1_000_000_000_000_000_000_000_u128;
pub const SAFE_FLOAT_MAX_EXP: i64 = 21_i64;

/// Controlled precision floating point number with efficient storage
///
/// Precision is controlled in a way that keeps enough mantissa digits so
/// that updating hotkey stake by 1 rao makes difference in the resulting shared
/// pool variables (both coldkey share and share pool denominator), but also
/// precision should be limited so that updating by 0.1 rao does not make the
/// difference (because there's no such thing as 0.1 rao, rao is integer).
#[freeze_struct("9a55fbe2d60efb41")]
#[derive(Encode, Decode, Default, TypeInfo, Clone, PartialEq, Eq, Debug)]
pub struct SafeFloat {
    mantissa: u128,
    exponent: i64,
}

/// Capped power of 10 in U256
/// Cap at 10^SAFE_FLOAT_MAX_EXP+1, we don't need greater powers here
fn cappow10(e: u64) -> U256 {
    if e > (SAFE_FLOAT_MAX_EXP as u64).saturating_add(1) {
        return U256::from(SAFE_FLOAT_MAX.saturating_mul(10));
    }
    if e == 0 {
        return U256::from(1);
    }
    U256::from(10)
        .checked_pow(U256::from(e))
        .unwrap_or_default()
}

impl SafeFloat {
    pub fn zero() -> Self {
        SafeFloat {
            mantissa: 0_u128,
            exponent: 0_i64,
        }
    }

    pub fn new(mantissa: u128, exponent: i64) -> Option<Self> {
        // Cap mantissa at SAFE_FLOAT_MAX
        if mantissa > SAFE_FLOAT_MAX {
            return None;
        }

        let mut safe_float = SafeFloat::zero();

        if safe_float.normalize(&U256::from(mantissa), exponent) {
            Some(safe_float)
        } else {
            None
        }
    }

    /// Sets the new mantissa and exponent adjustsing mantissa and exponent so that
    /// SAFE_FLOAT_MAX / 10 < mantissa <= SAFE_FLOAT_MAX
    ///
    /// Returns true in case of success or false if exponent over- or underflows
    pub(crate) fn normalize(&mut self, new_mantissa: &U256, new_exponent: i64) -> bool {
        if new_mantissa.is_zero() {
            self.mantissa = 0;
            self.exponent = 0;
            return true;
        }

        let ten = U256::from(10);
        let max_mantissa = U256::from(SAFE_FLOAT_MAX);
        let min_mantissa = U256::from(SAFE_FLOAT_MAX)
            .checked_div(ten)
            .unwrap_or_default();

        // Loops are safe because they are bounded by U256 size and result
        // in no more than 78 iterations together
        let mut normalized_mantissa = *new_mantissa;
        let mut normalized_exponent = new_exponent;

        while normalized_mantissa > max_mantissa {
            let Some(next_mantissa) = normalized_mantissa.checked_div(ten) else {
                return false;
            };
            let Some(next_exponent) = normalized_exponent.checked_add(1) else {
                return false;
            };

            normalized_mantissa = next_mantissa;
            normalized_exponent = next_exponent;
        }

        while normalized_mantissa <= min_mantissa {
            let Some(next_mantissa) = normalized_mantissa.checked_mul(ten) else {
                return false;
            };
            let Some(next_exponent) = normalized_exponent.checked_sub(1) else {
                return false;
            };

            normalized_mantissa = next_mantissa;
            normalized_exponent = next_exponent;
        }

        self.mantissa = normalized_mantissa.low_u128();
        self.exponent = normalized_exponent;

        true
    }

    /// Divide current value by a preserving precision (SAFE_FLOAT_MAX digits in mantissa)
    ///   result = m1 * 10^e1 / m2 * 10^e2
    pub fn div(&self, a: &SafeFloat) -> Option<Self> {
        // - In m1 / m2 division we need enough digits for a u128.
        //   This can be calculated in a lossless way in U256 as m1 * MAX_MANTISSA / m2
        // - The new exponent is e1 - e2 - SAFE_FLOAT_MAX_EXP
        let maybe_m1_scaled_u256 =
            U256::from(self.mantissa).checked_mul(U256::from(SAFE_FLOAT_MAX));
        let m2_u256 = U256::from(a.mantissa);

        // Calculate new exponent
        let new_exponent_i128 = (self.exponent as i128)
            .saturating_sub(a.exponent as i128)
            .saturating_sub(SAFE_FLOAT_MAX_EXP as i128);
        if (new_exponent_i128 > i64::MAX as i128) || (new_exponent_i128 < i64::MIN as i128) {
            return None;
        }
        let new_exponent = new_exponent_i128 as i64;

        // Calcuate new mantissa, normalize, and return result
        if let Some(m1_scaled_u256) = maybe_m1_scaled_u256 {
            let maybe_new_mantissa_u256 = m1_scaled_u256.checked_div(m2_u256);
            if let Some(new_mantissa_u256) = maybe_new_mantissa_u256 {
                let mut safe_float = SafeFloat::zero();
                if safe_float.normalize(&new_mantissa_u256, new_exponent) {
                    Some(safe_float)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn add(&self, a: &SafeFloat) -> Option<Self> {
        if self.is_zero() {
            return Some(a.clone());
        }
        if a.is_zero() {
            return Some(self.clone());
        }

        let (new_mantissa, new_exponent) = if self.exponent >= a.exponent {
            let exp_diff = self.exponent.saturating_sub(a.exponent);
            let m1 = U256::from(self.mantissa);
            let m2 = U256::from(a.mantissa)
                .checked_div(cappow10(exp_diff as u64))
                .unwrap_or_default();
            (m1.saturating_add(m2), self.exponent)
        } else {
            let exp_diff = a.exponent.saturating_sub(self.exponent);
            let m1 = U256::from(self.mantissa)
                .checked_div(cappow10(exp_diff as u64))
                .unwrap_or_default();
            let m2 = U256::from(a.mantissa);
            (m1.saturating_add(m2), a.exponent)
        };

        let mut safe_float = SafeFloat::zero();
        if safe_float.normalize(&new_mantissa, new_exponent) {
            Some(safe_float)
        } else {
            None
        }
    }

    pub fn sub(&self, a: &SafeFloat) -> Option<Self> {
        if self.is_zero() && a.is_zero() {
            return Some(Self::zero());
        } else if self.is_zero() {
            return None;
        }
        if a.is_zero() {
            return Some(self.clone());
        }

        let (new_mantissa, new_exponent) = if self.exponent >= a.exponent {
            let exp_diff = self.exponent.saturating_sub(a.exponent);
            let m1 = U256::from(self.mantissa);
            let m2 = U256::from(a.mantissa)
                .checked_div(cappow10(exp_diff as u64))
                .unwrap_or_default();
            (m1.saturating_sub(m2), self.exponent)
        } else {
            let exp_diff = a.exponent.saturating_sub(self.exponent);
            let m1 = U256::from(self.mantissa)
                .checked_div(cappow10(exp_diff as u64))
                .unwrap_or_default();
            let m2 = U256::from(a.mantissa);
            (m1.saturating_sub(m2), a.exponent)
        };

        let mut safe_float = SafeFloat::zero();
        if safe_float.normalize(&new_mantissa, new_exponent) {
            Some(safe_float)
        } else {
            None
        }
    }

    /// Calculate self * a / b without loss of precision
    pub fn mul_div(&self, a: &SafeFloat, b: &SafeFloat) -> Option<Self> {
        if b.mantissa == 0_u128 {
            return None;
        }

        // No overflows here, just unwrap or default
        let self_a_mantissa_u256 = U256::from(self.mantissa)
            .checked_mul(U256::from(a.mantissa))
            .unwrap_or_default();
        let maybe_self_a_exponent = self.exponent.checked_add(a.exponent);

        if let Some(self_a_exponent) = maybe_self_a_exponent {
            // Divide by b in U256
            let maybe_new_exponent = self_a_exponent.checked_sub(b.exponent);
            if let Some(new_exponent) = maybe_new_exponent {
                let new_mantissa = self_a_mantissa_u256
                    .checked_div(U256::from(b.mantissa))
                    .unwrap_or_default();
                let mut result = SafeFloat::zero();
                if result.normalize(&new_mantissa, new_exponent) {
                    Some(result)
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn is_zero(&self) -> bool {
        self.mantissa == 0u128
    }

    /// Returns true if self > a
    /// Both values should be normalized
    pub fn gt(&self, a: &SafeFloat) -> bool {
        let ten = U256::from(10);

        if self.exponent == a.exponent {
            self.mantissa > a.mantissa
        } else if self.exponent > a.exponent {
            let exp_diff = self.exponent.saturating_sub(a.exponent);
            if exp_diff > 1_i64 {
                true
            } else {
                ten.saturating_mul(U256::from(self.mantissa)) > U256::from(a.mantissa)
            }
        } else {
            let exp_diff = a.exponent.saturating_sub(self.exponent);
            if exp_diff > 1_i64 {
                false
            } else {
                U256::from(self.mantissa) > ten.saturating_mul(U256::from(a.mantissa))
            }
        }
    }
}

// Saturating conversion: negatives -> 0, overflow -> u64::MAX
impl From<&SafeFloat> for u64 {
    fn from(value: &SafeFloat) -> Self {
        // If exponent is zero, it's just an integer mantissa
        if value.exponent == 0 {
            return u64::try_from(value.mantissa).unwrap_or(u64::MAX);
        }

        // scale = 10^exponent
        let scale = cappow10(value.exponent.unsigned_abs());

        // mantissa * 10^exponent
        let q: U256 = if value.exponent > 0 {
            U256::from(value.mantissa).saturating_mul(scale)
        } else {
            U256::from(value.mantissa)
                .checked_div(scale)
                .unwrap_or_default()
        };

        // Convert quotient to u64, saturating on overflow
        if q.is_zero() {
            0
        } else {
            q.try_into().unwrap_or(u64::MAX)
        }
    }
}

// Convenience impl for owning values
impl From<SafeFloat> for u64 {
    fn from(value: SafeFloat) -> Self {
        u64::from(&value)
    }
}

impl From<u64> for SafeFloat {
    fn from(value: u64) -> Self {
        SafeFloat::new(value as u128, 0).unwrap_or_default()
    }
}

impl From<U64F64> for SafeFloat {
    fn from(value: U64F64) -> Self {
        let bits = value.to_bits();
        // High 64 bits = integer part
        let int = (bits >> 64) as u64;
        // Low 64 bits = fractional part
        let frac = (bits & 0xFFFF_FFFF_FFFF_FFFF) as u64;

        // If strictly zero, shortcut
        if bits == 0 {
            return SafeFloat::zero();
        }

        // SafeFloat for integer part: int * 10^0
        let safe_int = SafeFloat::new(int as u128, 0).unwrap_or_default();

        // Numerator of fractional part: frac * 10^0
        let safe_frac_num = SafeFloat::new(frac as u128, 0).unwrap_or_default();

        // Denominator = 2^64 as an integer SafeFloat: (2^64) * 10^0
        let two64: u128 = 1u128 << 64;
        let safe_two64 = SafeFloat::new(two64, 0).unwrap_or_default();

        // frac_part = frac / 2^64
        let safe_frac = safe_frac_num.div(&safe_two64).unwrap_or_default();

        // int + frac/2^64, with all mantissa/exponent normalization
        safe_int.add(&safe_frac).unwrap_or_default()
    }
}

impl From<&SafeFloat> for f64 {
    #[allow(
        clippy::arithmetic_side_effects,
        reason = "This code is only used in tests"
    )]
    fn from(value: &SafeFloat) -> Self {
        let mant = value.mantissa as f64;

        // powi takes i32, so clamp i64 exponent into i32 range (test-only).
        let e = value.exponent.clamp(i32::MIN as i64, i32::MAX as i64) as i32;

        mant * 10_f64.powi(e)
    }
}

impl From<SafeFloat> for f64 {
    fn from(value: SafeFloat) -> Self {
        f64::from(&value)
    }
}

pub trait SharePoolDataOperations<Key> {
    /// Gets shared value (always "the real thing" measured in rao, not fractional)
    fn get_shared_value(&self) -> u64;
    /// Gets single share for a given key
    fn get_share(&self, key: &Key) -> SafeFloat;
    // Tries to get a single share for a given key, as a result.
    fn try_get_share(&self, key: &Key) -> Result<SafeFloat, ()>;
    /// Gets share pool denominator
    fn get_denominator(&self) -> SafeFloat;
    /// Updates shared value by provided signed value
    fn set_shared_value(&mut self, value: u64);
    /// Update single share for a given key by provided signed value
    fn set_share(&mut self, key: &Key, share: SafeFloat);
    /// Update share pool denominator by provided signed value
    fn set_denominator(&mut self, update: SafeFloat);
}

/// SharePool struct that depends on the Key type and uses the SharePoolDataOperations
#[derive(Debug)]
pub struct SharePool<K, Ops>
where
    K: Eq,
    Ops: SharePoolDataOperations<K>,
{
    state_ops: Ops,
    phantom_key: marker::PhantomData<K>,
}

impl<K, Ops> SharePool<K, Ops>
where
    K: Eq,
    Ops: SharePoolDataOperations<K>,
{
    pub fn new(ops: Ops) -> Self {
        SharePool {
            state_ops: ops,
            phantom_key: marker::PhantomData,
        }
    }

    pub fn get_value(&self, key: &K) -> u64 {
        let shared_value: SafeFloat =
            SafeFloat::new(self.state_ops.get_shared_value() as u128, 0).unwrap_or_default();
        let current_share: SafeFloat = self.state_ops.get_share(key);
        let denominator: SafeFloat = self.state_ops.get_denominator();
        shared_value
            .mul_div(&current_share, &denominator)
            .unwrap_or_default()
            .into()
    }

    pub fn get_value_from_shares(&self, current_share: SafeFloat) -> u64 {
        let shared_value: SafeFloat =
            SafeFloat::new(self.state_ops.get_shared_value() as u128, 0).unwrap_or_default();
        let denominator: SafeFloat = self.state_ops.get_denominator();
        shared_value
            .mul_div(&current_share, &denominator)
            .unwrap_or_default()
            .into()
    }

    pub fn try_get_value(&self, key: &K) -> Result<u64, ()> {
        match self.state_ops.try_get_share(key) {
            Ok(_) => Ok(self.get_value(key)),
            Err(i) => Err(i),
        }
    }

    /// Update the total shared value.
    /// Every key's associated value effectively updates with this operation
    pub fn update_value_for_all(&mut self, update: i64) {
        let shared_value: u64 = self.state_ops.get_shared_value();
        self.state_ops.set_shared_value(if update >= 0 {
            shared_value.saturating_add(update as u64)
        } else {
            shared_value.saturating_sub(update.neg() as u64)
        });
    }

    pub fn sim_update_value_for_one(&mut self, update: i64) -> bool {
        let shared_value: u64 = self.state_ops.get_shared_value();
        let denominator: SafeFloat = self.state_ops.get_denominator();

        // Then, update this key's share
        if denominator.mantissa == 0 {
            true
        } else {
            // There are already keys in the pool, set or update this key
            let shares_per_update = self.get_shares_per_update(update, shared_value, &denominator);

            !shares_per_update.is_zero()
        }
    }

    fn get_shares_per_update(
        &self,
        update: i64,
        shared_value: u64,
        denominator: &SafeFloat,
    ) -> SafeFloat {
        let shared_value: SafeFloat = SafeFloat::new(shared_value as u128, 0).unwrap_or_default();
        let update_sf: SafeFloat =
            SafeFloat::new(update.unsigned_abs() as u128, 0).unwrap_or_default();
        update_sf
            .mul_div(denominator, &shared_value)
            .unwrap_or_default()
    }

    /// Update the value associated with an item identified by the Key
    /// Returns actual update
    ///
    pub fn update_value_for_one(&mut self, key: &K, update: i64) {
        let shared_value: u64 = self.state_ops.get_shared_value();
        let current_share: SafeFloat = self.state_ops.get_share(key);
        let denominator: SafeFloat = self.state_ops.get_denominator();

        // Then, update this key's share
        if denominator.is_zero() {
            // Initialize the pool. The first key gets all.
            let update_float: SafeFloat =
                SafeFloat::new(update.unsigned_abs() as u128, 0).unwrap_or_default();
            self.state_ops.set_denominator(update_float.clone());
            self.state_ops.set_share(key, update_float);
        } else {
            let new_denominator;
            let new_current_share;

            let shares_per_update: SafeFloat =
                self.get_shares_per_update(update, shared_value, &denominator);

            // Handle SafeFloat overflows quietly here because this overflow of i64 exponent
            // is extremely hypothetical and should never happen in practice.
            if update > 0 {
                new_denominator = match denominator.add(&shares_per_update) {
                    Some(new_denominator) => new_denominator,
                    None => {
                        log::error!(
                            "SafeFloat::add overflow when adding {:?} to {:?}; keeping old denominator",
                            shares_per_update,
                            denominator,
                        );
                        // Return the value as it was before the failed addition
                        denominator
                    }
                };

                new_current_share = match current_share.add(&shares_per_update) {
                    Some(new_current_share) => new_current_share,
                    None => {
                        log::error!(
                            "SafeFloat::add overflow when adding {:?} to {:?}; keeping old current_share",
                            shares_per_update,
                            current_share,
                        );
                        // Return the value as it was before the failed addition
                        current_share
                    }
                };
            } else {
                new_denominator = match denominator.sub(&shares_per_update) {
                    Some(new_denominator) => new_denominator,
                    None => {
                        log::error!(
                            "SafeFloat::add overflow when adding {:?} to {:?}; keeping old denominator",
                            shares_per_update,
                            denominator,
                        );
                        // Return the value as it was before the failed addition
                        denominator
                    }
                };

                new_current_share = match current_share.sub(&shares_per_update) {
                    Some(new_current_share) => new_current_share,
                    None => {
                        log::error!(
                            "SafeFloat::add overflow when adding {:?} to {:?}; keeping old current_share",
                            shares_per_update,
                            current_share,
                        );
                        // Return the value as it was before the failed addition
                        current_share
                    }
                };
            }

            self.state_ops.set_denominator(new_denominator);
            self.state_ops.set_share(key, new_current_share);
        }

        // Update shared value
        self.update_value_for_all(update);
    }
}

// cargo test --package share-pool --lib -- tests --nocapture
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
    use super::*;
    use approx::assert_abs_diff_eq;
    use std::collections::BTreeMap;
    use substrate_fixed::types::U64F64;

    struct MockSharePoolDataOperations {
        shared_value: u64,
        share: BTreeMap<u16, SafeFloat>,
        denominator: SafeFloat,
    }

    impl MockSharePoolDataOperations {
        fn new() -> Self {
            MockSharePoolDataOperations {
                shared_value: 0u64,
                share: BTreeMap::new(),
                denominator: SafeFloat::zero(),
            }
        }
    }

    impl SharePoolDataOperations<u16> for MockSharePoolDataOperations {
        fn get_shared_value(&self) -> u64 {
            self.shared_value
        }

        fn get_share(&self, key: &u16) -> SafeFloat {
            self.share.get(key).cloned().unwrap_or_else(SafeFloat::zero)
        }

        fn try_get_share(&self, key: &u16) -> Result<SafeFloat, ()> {
            match self.share.get(key).cloned() {
                Some(value) => Ok(value),
                None => Err(()),
            }
        }

        fn get_denominator(&self) -> SafeFloat {
            self.denominator.clone()
        }

        fn set_shared_value(&mut self, value: u64) {
            self.shared_value = value;
        }

        fn set_share(&mut self, key: &u16, share: SafeFloat) {
            self.share.insert(*key, share);
        }

        fn set_denominator(&mut self, update: SafeFloat) {
            self.denominator = update;
        }
    }

    #[test]
    fn test_get_value() {
        let mut mock_ops = MockSharePoolDataOperations::new();
        mock_ops.set_denominator(10u64.into());
        mock_ops.set_share(&1_u16, 3u64.into());
        mock_ops.set_share(&2_u16, 7u64.into());
        mock_ops.set_shared_value(100u64.into());
        let share_pool = SharePool::new(mock_ops);
        let result1 = share_pool.get_value(&1);
        let result2 = share_pool.get_value(&2);
        assert_eq!(result1, 30);
        assert_eq!(result2, 70);
    }

    #[test]
    fn test_division_by_zero() {
        let mut mock_ops = MockSharePoolDataOperations::new();
        mock_ops.set_denominator(SafeFloat::zero()); // Zero denominator
        let pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        let value = pool.get_value(&1);
        assert_eq!(value, 0, "Value should be 0 when denominator is zero");
    }

    #[test]
    fn test_max_shared_value() {
        let mut mock_ops = MockSharePoolDataOperations::new();
        mock_ops.set_shared_value(u64::MAX.into());
        mock_ops.set_share(&1, 3u64.into()); // Use a neutral value for share
        mock_ops.set_share(&2, 7u64.into()); // Use a neutral value for share
        mock_ops.set_denominator(10u64.into()); // Neutral value to see max effect
        let pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        let max_value = pool.get_value(&1) + pool.get_value(&2);
        assert!(u64::MAX - max_value <= 5, "Max value should map to u64 MAX");
    }

    #[test]
    fn test_max_share_value() {
        let mut mock_ops = MockSharePoolDataOperations::new();
        mock_ops.set_shared_value(1_000_000_000u64); // Use a neutral value for shared value
        mock_ops.set_share(&1, (u64::MAX / 2).into());
        mock_ops.set_share(&2, (u64::MAX / 2).into());
        mock_ops.set_denominator((u64::MAX).into());
        let pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        let value1 = pool.get_value(&1) as i128;
        let value2 = pool.get_value(&2) as i128;

        assert_abs_diff_eq!(value1 as f64, 500_000_000_f64, epsilon = 1.);
        assert!((value2 - 500_000_000).abs() <= 1);
    }

    #[test]
    fn test_denom_precision() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        pool.update_value_for_one(&1, 1000);

        let value_tmp = pool.get_value(&1) as i128;
        assert_eq!(value_tmp, 1000);

        pool.update_value_for_one(&1, -990);
        pool.update_value_for_one(&2, 1000);
        pool.update_value_for_one(&2, -990);

        let value1 = pool.get_value(&1) as i128;
        let value2 = pool.get_value(&2) as i128;

        assert_eq!(value1, 10);
        assert_eq!(value2, 10);
    }

    // cargo test --package share-pool --lib -- tests::test_denom_high_precision --exact --show-output
    #[test]
    fn test_denom_high_precision() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        // 50%/50% stakes consisting of 1 rao each
        pool.update_value_for_one(&1, 1);
        pool.update_value_for_one(&2, 1);

        // Huge emission resulting in 1M Alpha
        // Both stakers should have 500k Alpha each
        pool.update_value_for_all(999_999_999_999_998);

        // Everyone unstakes almost everything, leaving 10 rao in the stake
        pool.update_value_for_one(&1, -499_999_999_999_990);
        pool.update_value_for_one(&2, -499_999_999_999_990);

        // Huge emission resulting in 1M Alpha
        // Both stakers should have 500k Alpha each
        pool.update_value_for_all(999_999_999_999_980);

        // Stakers add 1k Alpha each
        pool.update_value_for_one(&1, 1_000_000_000_000);
        pool.update_value_for_one(&2, 1_000_000_000_000);

        let value1 = pool.get_value(&1) as f64;
        let value2 = pool.get_value(&2) as f64;
        assert_abs_diff_eq!(value1, 501_000_000_000_000_f64, epsilon = 1.);
        assert_abs_diff_eq!(value2, 501_000_000_000_000_f64, epsilon = 1.);
    }

    // cargo test --package share-pool --lib -- tests::test_denom_high_precision_many_small_unstakes --exact --show-output
    #[test]
    fn test_denom_high_precision_many_small_unstakes() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        // 50%/50% stakes consisting of 1 rao each
        pool.update_value_for_one(&1, 1);
        pool.update_value_for_one(&2, 1);

        // Huge emission resulting in 1M Alpha
        // Both stakers should have 500k Alpha + 1 rao each
        pool.update_value_for_all(1_000_000_000_000_000);

        // Run X number of small unstake transactions
        let tx_count = 1000;
        let unstake_amount = -500_000_000;
        for _ in 0..tx_count {
            pool.update_value_for_one(&1, unstake_amount);
            pool.update_value_for_one(&2, unstake_amount);
        }

        // Emit 1M - each gets 500k Alpha
        pool.update_value_for_all(1_000_000_000_000_000);

        // Each adds 1k Alpha
        pool.update_value_for_one(&1, 1_000_000_000_000);
        pool.update_value_for_one(&2, 1_000_000_000_000);

        // Result, each should get
        //   (500k+1) + tx_count * unstake_amount + 500k + 1k
        let value1 = pool.get_value(&1) as i128;
        let value2 = pool.get_value(&2) as i128;
        let expected = 1_001_000_000_000_000 + tx_count * unstake_amount;

        assert_abs_diff_eq!(value1 as f64, expected as f64, epsilon = 1.);
        assert_abs_diff_eq!(value2 as f64, expected as f64, epsilon = 1.);
    }

    #[test]
    fn test_update_value_for_one() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        pool.update_value_for_one(&1, 1000);

        let value = pool.get_value(&1) as i128;
        assert_eq!(value, 1000);
    }

    #[test]
    fn test_update_value_for_all() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        pool.update_value_for_all(1000);
        assert_eq!(
            pool.state_ops.shared_value,
            U64F64::saturating_from_num(1000)
        );
    }

    // cargo test --package share-pool --lib -- tests::test_get_shares_per_update --exact --show-output
    #[test]
    fn test_get_shares_per_update() {
        // Test case (update, shared_value, denominator_mantissa, denominator_exponent)
        [
            (1_i64, 1_u64, 1_u64, 0_i64),
            (1, 1_000_000_000_000_000_000, 1, 0),
            (1, 21_000_000_000_000_000, 1, 5),
            (1, 21_000_000_000_000_000, 1, -1_000_000),
            (1, 21_000_000_000_000_000, 1, -1_000_000_000),
            (1, 21_000_000_000_000_000, 1, -1_000_000_001),
            (1_000, 21_000_000_000_000_000, 1, 5),
            (21_000_000_000_000_000, 21_000_000_000_000_000, 1, 5),
            (21_000_000_000_000_000, 21_000_000_000_000_000, 1, -5),
            (21_000_000_000_000_000, 21_000_000_000_000_000, 1, -100),
            (21_000_000_000_000_000, 21_000_000_000_000_000, 1, 100),
            (210_000_000_000_000_000, 21_000_000_000_000_000, 1, 5),
            (1_000, 1_000, 21_000_000_000_000_000, 0),
            (1_000, 1_000, 21_000_000_000_000_000, -1),
        ]
        .into_iter()
        .for_each(
            |(update, shared_value, denominator_mantissa, denominator_exponent)| {
                let mock_ops = MockSharePoolDataOperations::new();
                let pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

                let denominator_float =
                    SafeFloat::new(denominator_mantissa as u128, denominator_exponent)
                        .unwrap_or_default();
                let denominator_f64: f64 = denominator_float.clone().into();
                let spu: f64 = pool
                    .get_shares_per_update(update, shared_value, &denominator_float)
                    .into();
                let expected = update as f64 * denominator_f64 / shared_value as f64;
                let precision = 1000.;
                assert_abs_diff_eq!(expected, spu, epsilon = expected / precision);
            },
        );
    }

    #[test]
    fn test_safefloat_normalize() {
        // Test case: mantissa, exponent, expected mantissa, expected exponent
        [
            (1_u128, 0, 1_000_000_000_000_000_000_000_u128, -21_i64),
            (0, 0, 0, 0),
            (10_u128, 0, 1_000_000_000_000_000_000_000_u128, -20),
            (1_000_u128, 0, 1_000_000_000_000_000_000_000_u128, -18),
            (
                100_000_000_000_000_000_000_u128,
                0,
                1_000_000_000_000_000_000_000_u128,
                -1,
            ),
            (SAFE_FLOAT_MAX, 0, SAFE_FLOAT_MAX, 0),
        ]
        .into_iter()
        .for_each(|(m, e, expected_m, expected_e)| {
            let a = SafeFloat::new(m, e).unwrap();
            assert_eq!(a.mantissa, expected_m);
            assert_eq!(a.exponent, expected_e);
        });
    }

    #[test]
    fn test_safefloat_add() {
        // Test case: man_a, exp_a, man_b, exp_b, expected mantissa of a+b, expected exponent of a+b
        [
            // 1 + 1 = 2
            (
                1_u128,
                0,
                1_u128,
                0,
                200_000_000_000_000_000_000_u128,
                -20_i64,
            ),
            // 0 + 1 = 1
            (0, 0, 1, 0, 1_000_000_000_000_000_000_000_u128, -21_i64),
            // 0 + 0.1 = 0.1
            (0, 0, 1, -1, 1_000_000_000_000_000_000_000_u128, -22_i64),
            // 1e-1000 + 0.1 = 0.1
            (1, -1000, 1, -1, 1_000_000_000_000_000_000_000_u128, -22_i64),
            // SAFE_FLOAT_MAX + SAFE_FLOAT_MAX
            (
                SAFE_FLOAT_MAX,
                0,
                SAFE_FLOAT_MAX,
                0,
                SAFE_FLOAT_MAX * 2 / 10,
                1_i64,
            ),
            // Expected loss of precision: tiny + huge
            (
                1_u128,
                0,
                1_000_000_000_000_000_000_000_u128,
                1,
                1_000_000_000_000_000_000_000_u128,
                1_i64,
            ),
            (
                1_u128,
                0,
                1_u128,
                22,
                1_000_000_000_000_000_000_000_u128,
                1_i64,
            ),
            (
                1_u128,
                0,
                1_u128,
                23,
                1_000_000_000_000_000_000_000_u128,
                2_i64,
            ),
            (
                123_u128,
                0,
                1_u128,
                23,
                1_000_000_000_000_000_000_000_u128,
                2_i64,
            ),
            (
                123_u128,
                1,
                1_u128,
                23,
                100_000_000_000_000_000_001_u128,
                3_i64,
            ),
            // Small-ish + very large (10^22 + 42)
            // 42 * 10^0 + 1 * 10^22 ≈ 1e22 + 42
            // Normalized ≈ (1e21 + 4) * 10^1
            (
                42_u128,
                0,
                1_u128,
                22,
                1_000_000_000_000_000_000_000_u128,
                1_i64,
            ),
            // "Almost 10^21" + 10^22
            // (10^21 - 1) + 10^22 → floor((10^22 + 10^21 - 1) / 100) * 10^2
            (
                999_999_999_999_999_999_999_u128,
                0,
                1_u128,
                22,
                109_999_999_999_999_999_999_u128,
                2_i64,
            ),
            // Small-ish + 10^23 where the small part is completely lost
            // 42 + 10^23 -> floor((10^23 + 42)/100) * 10^2 ≈ 1e21 * 10^2
            (
                42_u128,
                0,
                1_u128,
                23,
                1_000_000_000_000_000_000_000_u128,
                2_i64,
            ),
            // Small-ish + 10^23 where tiny part slightly affects mantissa
            // 4200 + 10^23 -> floor((10^23 + 4200)/100) * 10^2 = (1e21 + 42) * 10^2
            (
                4_200_u128,
                0,
                1_u128,
                23,
                100_000_000_000_000_000_004_u128,
                3_i64,
            ),
            // (10^21 - 1) + 10^23
            // -> floor((10^23 + 10^21 - 1)/100) = 1e21 + 1e19 - 1
            (
                999_999_999_999_999_999_999_u128,
                0,
                1_u128,
                23,
                100_999_999_999_999_999_999_u128,
                3_i64,
            ),
            // Medium + 10^23 with exponent 1 on the smaller term
            // 999_999 * 10^1 + 1 * 10^23 -> (10^22 + 999_999) * 10^1
            // Normalized ≈ (1e21 + 99_999) * 10^2
            (
                999_999_u128,
                1,
                1_u128,
                23,
                100_000_000_000_000_009_999_u128,
                3_i64,
            ),
            // Check behaviour with exponent 24, tiny second term
            // 1 * 10^24 + 1 -> floor((10^24 + 1)/1000) * 10^3 ≈ 1e21 * 10^3
            (
                1_u128,
                24,
                1_u128,
                0,
                1_000_000_000_000_000_000_000_u128,
                3_i64,
            ),
            // 1 * 10^24 + a non-trivial small mantissa
            // 1e24 + 123456789012345678901 -> floor(/1000) = 1e21 + 123456789012345678
            (
                1_u128,
                24,
                123_456_789_012_345_678_901_u128,
                0,
                100_012_345_678_901_234_567_u128,
                4_i64,
            ),
            // 10^22 and 10^23 combined:
            // 1 * 10^22 + 1 * 10^23 = 11 * 10^22 = (1.1 * 10^23)
            // Normalized → (1.1e20) * 10^3
            (
                1_u128,
                22,
                1_u128,
                23,
                110_000_000_000_000_000_000_u128,
                3_i64,
            ),
            // Both operands already aligned at a huge scale:
            // (10^21 - 1) * 10^22 + 1 * 10^22 = 10^21 * 10^22 = 10^43
            // Canonical form: (1e21) * 10^22
            (
                999_999_999_999_999_999_999_u128,
                22,
                1_u128,
                22,
                1_000_000_000_000_000_000_000_u128,
                22_i64,
            ),
        ]
        .into_iter()
        .for_each(|(m_a, e_a, m_b, e_b, expected_m, expected_e)| {
            let a = SafeFloat::new(m_a, e_a).unwrap();
            let b = SafeFloat::new(m_b, e_b).unwrap();

            let a_plus_b = a.add(&b).unwrap();
            let b_plus_a = b.add(&a).unwrap();

            assert_eq!(a_plus_b.mantissa, expected_m);
            assert_eq!(a_plus_b.exponent, expected_e);
            assert_eq!(b_plus_a.mantissa, expected_m);
            assert_eq!(b_plus_a.exponent, expected_e);
        });
    }

    #[test]
    fn test_safefloat_div_by_zero_is_none() {
        let a = SafeFloat::new(1u128, 0).unwrap();
        assert!(a.div(&SafeFloat::zero()).is_none());
    }

    #[test]
    fn test_safefloat_div() {
        // Test case: man_a, exp_a, man_b, exp_b
        [
            (1_u128, 0_i64, 100_000_000_000_000_000_000_u128, -20_i64),
            (1_u128, 0, 1_u128, 0),
            (1_u128, 1, 1_u128, 0),
            (1_u128, 7, 1_u128, 0),
            (1_u128, 50, 1_u128, 0),
            (1_u128, 100, 1_u128, 0),
            (1_u128, 0, 7_u128, 0),
            (1_u128, 1, 7_u128, 0),
            (1_u128, 7, 7_u128, 0),
            (1_u128, 50, 7_u128, 0),
            (1_u128, 100, 7_u128, 0),
            (1_u128, 0, 3_u128, 0),
            (1_u128, 1, 3_u128, 0),
            (1_u128, 7, 3_u128, 0),
            (1_u128, 50, 3_u128, 0),
            (1_u128, 100, 3_u128, 0),
            (2_u128, 0, 3_u128, 0),
            (2_u128, 1, 3_u128, 0),
            (2_u128, 7, 3_u128, 0),
            (2_u128, 50, 3_u128, 0),
            (2_u128, 100, 3_u128, 0),
            (5_u128, 0, 3_u128, 0),
            (5_u128, 1, 3_u128, 0),
            (5_u128, 7, 3_u128, 0),
            (5_u128, 50, 3_u128, 0),
            (5_u128, 100, 3_u128, 0),
            (10_u128, 0, 100_000_000_000_000_000_000_u128, -19),
            (1_000_u128, 0, 100_000_000_000_000_000_000_u128, -17),
            (
                100_000_000_000_000_000_000_u128,
                0,
                1_000_000_000_000_000_000_000_u128,
                -1,
            ),
            (SAFE_FLOAT_MAX, 0, SAFE_FLOAT_MAX, 0),
            (SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX, -100),
            (SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX - 1, -100),
            (SAFE_FLOAT_MAX - 1, 100, SAFE_FLOAT_MAX, -100),
            (SAFE_FLOAT_MAX - 2, 100, SAFE_FLOAT_MAX, -100),
            (SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX / 2 - 1, -100),
            (SAFE_FLOAT_MAX, 100, SAFE_FLOAT_MAX / 2 - 1, 100),
            (1_u128, 0, 100_000_000_000_000_000_000_u128, -20_i64),
            (
                123_456_789_123_456_789_123_u128,
                20_i64,
                87_654_321_987_654_321_987_u128,
                -20_i64,
            ),
            (
                123_456_789_123_456_789_123_u128,
                100_i64,
                87_654_321_987_654_321_987_u128,
                -100_i64,
            ),
            (
                123_456_789_123_456_789_123_u128,
                -100_i64,
                87_654_321_987_654_321_987_u128,
                100_i64,
            ),
            (
                123_456_789_123_456_789_123_u128,
                -99_i64,
                87_654_321_987_654_321_987_u128,
                99_i64,
            ),
            (
                123_456_789_123_456_789_123_u128,
                123_i64,
                87_654_321_987_654_321_987_u128,
                -32_i64,
            ),
            (
                123_456_789_123_456_789_123_u128,
                -123_i64,
                87_654_321_987_654_321_987_u128,
                32_i64,
            ),
        ]
        .into_iter()
        .for_each(|(ma, ea, mb, eb)| {
            let a = SafeFloat::new(ma, ea).unwrap();
            let b = SafeFloat::new(mb, eb).unwrap();

            let actual: f64 = a.div(&b).unwrap().into();
            let expected =
                ma as f64 * (10_f64).powi(ea as i32) / (mb as f64 * (10_f64).powi(eb as i32));

            assert_abs_diff_eq!(actual, expected, epsilon = actual / 100_000_000_000_000_f64);
        });
    }

    #[test]
    fn test_safefloat_mul_div() {
        // result = a * b / c
        // should not lose precision gained in a * b
        // Test case: man_a, exp_a, man_b, exp_b, man_c, exp_c
        [
            (1_u128, -20_i64, 1_u128, -20_i64, 1_u128, -20_i64),
            (123_u128, 20_i64, 123_u128, -20_i64, 321_u128, 0_i64),
            (
                123_123_123_123_123_123_u128,
                20_i64,
                321_321_321_321_321_321_u128,
                -20_i64,
                777_777_777_777_777_777_u128,
                0_i64,
            ),
            (
                11_111_111_111_111_111_111_u128,
                20_i64,
                99_321_321_321_321_321_321_u128,
                -20_i64,
                77_777_777_777_777_777_777_u128,
                0_i64,
            ),
        ]
        .into_iter()
        .for_each(|(ma, ea, mb, eb, mc, ec)| {
            let a = SafeFloat::new(ma, ea).unwrap();
            let b = SafeFloat::new(mb, eb).unwrap();
            let c = SafeFloat::new(mc, ec).unwrap();

            let actual: f64 = a.mul_div(&b, &c).unwrap().into();
            let expected = (ma as f64 * (10_f64).powi(ea as i32))
                * (mb as f64 * (10_f64).powi(eb as i32))
                / (mc as f64 * (10_f64).powi(ec as i32));

            assert_abs_diff_eq!(actual, expected, epsilon = actual / 100_000_000_000_000_f64);
        });
    }

    #[test]
    fn test_safefloat_from_u64f64() {
        [
            // U64F64::from_num(1000.0),
            // U64F64::from_num(10.0),
            // U64F64::from_num(1.0),
            U64F64::from_num(0.1),
            // U64F64::from_num(0.00000001),
            // U64F64::from_num(123_456_789_123_456u128),
            // // Exact zero
            // U64F64::from_num(0.0),
            // // Very small positive value (well above Q64.64 resolution)
            // U64F64::from_num(1e-18),
            // // Value just below 1
            // U64F64::from_num(0.999_999_999_999_999_f64),
            // // Value just above 1
            // U64F64::from_num(1.000_000_000_000_001_f64),
            // // "Random-looking" fractional with many digits
            // U64F64::from_num(1.234_567_890_123_45_f64),
            // // Large integer, but smaller than the max integer part of U64F64
            // U64F64::from_num(999_999_999_999_999_999u128),
            // // Very large integer near the upper bound of integer range
            // U64F64::from_num(u64::MAX as u128),
            // // Large number with fractional part
            // U64F64::from_num(123_456_789_123_456.78_f64),
            // // Medium-large with tiny fractional part to test precision on tail digits
            // U64F64::from_num(1_000_000_000_000.000_001_f64),
            // // Smallish with long fractional part
            // U64F64::from_num(0.123_456_789_012_345_f64),
        ]
        .into_iter()
        .for_each(|f| {
            let safe_float: SafeFloat = f.into();
            let actual: f64 = safe_float.into();
            let expected = f.to_num::<f64>();

            // Relative epsilon ~1e-14 of the magnitude
            let epsilon = if actual == 0.0 {
                0.0
            } else {
                actual.abs() / 100_000_000_000_000_f64
            };

            assert_abs_diff_eq!(actual, expected, epsilon = epsilon);
        });
    }

    /// This is a real-life scenario test when someone lost 7 TAO on Chutes (SN64)
    /// when paying fees in Alpha. The scenario occured because the update of share value
    /// of one coldkey (update_value_for_one) hit the scenario of full unstake.
    ///
    /// Specifically, the following condition was triggered:
    ///
    ///    `(shared_value + 2_628_000_000_000_000_u64).checked_div(new_denominator)`
    ///
    /// returned None because new_denominator was too low and division of
    /// `shared_value + 2_628_000_000_000_000_u64` by new_denominator has overflown U64F64.
    ///
    /// This test fails on the old version of share pool (with much lower tolerances).
    ///
    /// cargo test --package share-pool --lib -- tests::test_loss_due_to_precision --exact --nocapture
    #[test]
    fn test_loss_due_to_precision() {
        let mock_ops = MockSharePoolDataOperations::new();
        let mut pool = SharePool::<u16, MockSharePoolDataOperations>::new(mock_ops);

        // Setup pool so that initial coldkey's alpha is 10% of 1e12 = 1e11 rao.
        let low_denominator = SafeFloat::new(1u128, -14).unwrap();
        let low_share = SafeFloat::new(1u128, -15).unwrap();
        pool.state_ops.set_denominator(low_denominator);
        pool.state_ops.set_shared_value(1_000_000_000_000_u64);
        pool.state_ops.set_share(&1, low_share);

        let value_before = pool.get_value(&1) as i128;
        assert_abs_diff_eq!(value_before as f64, 100_000_000_000., epsilon = 0.1);

        // Remove a little stake
        let unstake_amount = 1000i64;
        pool.update_value_for_one(&1, unstake_amount.neg());

        let value_after = pool.get_value(&1) as i128;
        assert_abs_diff_eq!(
            (value_before - value_after) as f64,
            unstake_amount as f64,
            epsilon = unstake_amount as f64 / 1_000_000_000.
        );
    }

    fn rel_err(a: f64, b: f64) -> f64 {
        let denom = a.abs().max(b.abs()).max(1.0);
        (a - b).abs() / denom
    }

    fn push_unique(v: &mut Vec<u128>, x: u128) {
        if x != 0 && !v.contains(&x) {
            v.push(x);
        }
    }

    // cargo test --package share-pool --lib -- tests::test_safefloat_mul_div_wide_range --exact --include-ignored --show-output
    #[test]
    #[ignore = "long-running sweep test; run explicitly when needed"]
    fn test_safefloat_mul_div_wide_range() {
        use rayon::prelude::*;
        use std::sync::Arc;
        use std::sync::atomic::{AtomicUsize, Ordering};

        // Build mantissa corpus
        let mut mantissas = Vec::<u128>::new();

        let linear_steps: u128 = 200;
        let linear_step = (SAFE_FLOAT_MAX / linear_steps).max(1);
        let mut m = 1u128;
        while m <= SAFE_FLOAT_MAX {
            push_unique(&mut mantissas, m);
            match m.checked_add(linear_step) {
                Some(next) if next > m => m = next,
                _ => break,
            }
        }
        push_unique(&mut mantissas, SAFE_FLOAT_MAX);

        let mut p = 1u128;
        while p <= SAFE_FLOAT_MAX {
            push_unique(&mut mantissas, p);
            if p > 1 {
                push_unique(&mut mantissas, p - 1);
            }
            if let Some(next) = p.checked_add(1)
                && next <= SAFE_FLOAT_MAX
            {
                push_unique(&mut mantissas, next);
            }

            match p.checked_mul(10) {
                Some(next) if next > p && next <= SAFE_FLOAT_MAX => p = next,
                _ => break,
            }
        }

        for delta in [
            0u128, 1, 2, 3, 7, 9, 10, 11, 99, 100, 101, 999, 1_000, 10_000,
        ] {
            if SAFE_FLOAT_MAX > delta {
                push_unique(&mut mantissas, SAFE_FLOAT_MAX - delta);
            }
        }

        mantissas.sort_unstable();
        mantissas.dedup();

        let exp_min: i64 = -120;
        let exp_max: i64 = 120;
        let exp_step: usize = 5;
        let exponents: Vec<i64> = (exp_min..=exp_max).step_by(exp_step).collect();

        // Precompute all (a, b) pairs as outer work items.
        // Each Rayon task will then iterate all c's sequentially.
        let mut outer_cases: Vec<(u128, i64, u128, i64)> = Vec::new();

        for &ma in &mantissas {
            for &ea in &exponents {
                for &mb in &mantissas {
                    for &eb in &exponents {
                        outer_cases.push((ma, ea, mb, eb));
                    }
                }
            }
        }

        let checked = Arc::new(AtomicUsize::new(0));
        let skipped_non_finite = Arc::new(AtomicUsize::new(0));
        let skipped_invalid_sf = Arc::new(AtomicUsize::new(0));

        let progress_step = 10_000usize;
        let total_outer = outer_cases.len();

        outer_cases.into_par_iter().for_each(|(ma, ea, mb, eb)| {
            let a = match SafeFloat::new(ma, ea) {
                Some(x) => x,
                None => {
                    skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                    return;
                }
            };

            let b = match SafeFloat::new(mb, eb) {
                Some(x) => x,
                None => {
                    skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                    return;
                }
            };

            for &mc in &mantissas {
                for &ec in &exponents {
                    let c = match SafeFloat::new(mc, ec) {
                        Some(x) => x,
                        None => {
                            skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                            continue;
                        }
                    };

                    let actual_sf = a.mul_div(&b, &c).unwrap();
                    let actual: f64 = actual_sf.into();

                    let expected =
                        (ma as f64 * 10_f64.powi(ea as i32))
                        * (mb as f64 * 10_f64.powi(eb as i32))
                        / (mc as f64 * 10_f64.powi(ec as i32));

                    if !expected.is_finite() || !actual.is_finite() {
                        skipped_non_finite.fetch_add(1, Ordering::Relaxed);
                        continue;
                    }

                    let err = rel_err(actual, expected);

                    assert!(
                        err <= 1e-12,
                        concat!(
                            "mul_div mismatch:\n",
                            "  a = {}e{}\n",
                            "  b = {}e{}\n",
                            "  c = {}e{}\n",
                            "  actual   = {:.20e}\n",
                            "  expected = {:.20e}\n",
                            "  rel_err  = {:.20e}"
                        ),
                        ma, ea, mb, eb, mc, ec, actual, expected, err
                    );

                    checked.fetch_add(1, Ordering::Relaxed);
                }
            }

            let done_outer = checked.load(Ordering::Relaxed);
            if done_outer % progress_step == 0 {
                let invalid = skipped_invalid_sf.load(Ordering::Relaxed);
                let non_finite = skipped_non_finite.load(Ordering::Relaxed);
                log::debug!(
                    "progress: checked={}, skipped_invalid_sf={}, skipped_non_finite={}, outer_total={}",
                    done_outer,
                    invalid,
                    non_finite,
                    total_outer,
                );
            }
        });

        let checked = checked.load(Ordering::Relaxed);
        let skipped_non_finite = skipped_non_finite.load(Ordering::Relaxed);
        let skipped_invalid_sf = skipped_invalid_sf.load(Ordering::Relaxed);

        println!(
            "checked={}, skipped_non_finite={}, skipped_invalid_sf={}, mantissas={}, exponents={}, outer_cases={}",
            checked,
            skipped_non_finite,
            skipped_invalid_sf,
            mantissas.len(),
            exponents.len(),
            total_outer,
        );

        assert!(checked > 0, "test did not validate any finite cases");
    }

    #[test]
    #[ignore = "long-running broad-range test; run explicitly when needed"]
    fn test_safefloat_div_wide_range() {
        use rayon::prelude::*;
        use std::sync::Arc;
        use std::sync::atomic::{AtomicUsize, Ordering};

        fn rel_err(a: f64, b: f64) -> f64 {
            let denom = a.abs().max(b.abs()).max(1.0);
            (a - b).abs() / denom
        }

        fn push_unique(v: &mut Vec<u128>, x: u128) {
            if x != 0 && !v.contains(&x) {
                v.push(x);
            }
        }

        // Build a broad mantissa corpus:
        // - coarse linear sweep
        // - powers of 10 and neighbors
        // - values near SAFE_FLOAT_MAX
        let mut mantissas = Vec::<u128>::new();

        let linear_steps: u128 = 200;
        let linear_step = (SAFE_FLOAT_MAX / linear_steps).max(1);
        let mut m = 1u128;
        while m <= SAFE_FLOAT_MAX {
            push_unique(&mut mantissas, m);
            match m.checked_add(linear_step) {
                Some(next) if next > m => m = next,
                _ => break,
            }
        }
        push_unique(&mut mantissas, SAFE_FLOAT_MAX);

        let mut p = 1u128;
        while p <= SAFE_FLOAT_MAX {
            push_unique(&mut mantissas, p);
            if p > 1 {
                push_unique(&mut mantissas, p - 1);
            }
            if let Some(next) = p.checked_add(1)
                && next <= SAFE_FLOAT_MAX
            {
                push_unique(&mut mantissas, next);
            }

            match p.checked_mul(10) {
                Some(next) if next > p && next <= SAFE_FLOAT_MAX => p = next,
                _ => break,
            }
        }

        for delta in [
            0u128, 1, 2, 3, 7, 9, 10, 11, 99, 100, 101, 999, 1_000, 10_000,
        ] {
            if SAFE_FLOAT_MAX > delta {
                push_unique(&mut mantissas, SAFE_FLOAT_MAX - delta);
            }
        }

        mantissas.sort_unstable();
        mantissas.dedup();

        // Exponent sweep.
        // Keep it large enough to stress normalization / exponent math,
        // but still practical for f64 reference calculations.
        let exp_min: i64 = -120;
        let exp_max: i64 = 120;
        let exp_step: usize = 5;
        let exponents: Vec<i64> = (exp_min..=exp_max).step_by(exp_step).collect();

        let m_len = mantissas.len();
        let e_len = exponents.len();
        let total_cases = m_len * e_len * m_len * e_len;

        let checked = Arc::new(AtomicUsize::new(0));
        let skipped_non_finite = Arc::new(AtomicUsize::new(0));
        let skipped_invalid_sf = Arc::new(AtomicUsize::new(0));
        let done_counter = Arc::new(AtomicUsize::new(0));

        (0..total_cases).into_par_iter().for_each(|idx| {
            let mut rem = idx;

            let eb_idx = rem % e_len;
            rem /= e_len;

            let mb_idx = rem % m_len;
            rem /= m_len;

            let ea_idx = rem % e_len;
            rem /= e_len;

            let ma_idx = rem % m_len;

            let ma = mantissas[ma_idx];
            let ea = exponents[ea_idx];
            let mb = mantissas[mb_idx];
            let eb = exponents[eb_idx];

            let a = match SafeFloat::new(ma, ea) {
                Some(x) => x,
                None => {
                    skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                    done_counter.fetch_add(1, Ordering::Relaxed);
                    return;
                }
            };

            let b = match SafeFloat::new(mb, eb) {
                Some(x) => x,
                None => {
                    skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                    done_counter.fetch_add(1, Ordering::Relaxed);
                    return;
                }
            };

            let actual_sf = match a.div(&b) {
                Some(x) => x,
                None => {
                    skipped_invalid_sf.fetch_add(1, Ordering::Relaxed);
                    done_counter.fetch_add(1, Ordering::Relaxed);
                    return;
                }
            };

            let actual: f64 = actual_sf.into();
            let expected =
                (ma as f64 * 10_f64.powi(ea as i32)) / (mb as f64 * 10_f64.powi(eb as i32));

            if !actual.is_finite() || !expected.is_finite() {
                skipped_non_finite.fetch_add(1, Ordering::Relaxed);
            } else {
                let err = rel_err(actual, expected);

                assert!(
                    err <= 1e-12,
                    concat!(
                        "div mismatch:\n",
                        "  a = {}e{}\n",
                        "  b = {}e{}\n",
                        "  actual   = {:.20e}\n",
                        "  expected = {:.20e}\n",
                        "  rel_err  = {:.20e}"
                    ),
                    ma,
                    ea,
                    mb,
                    eb,
                    actual,
                    expected,
                    err
                );

                checked.fetch_add(1, Ordering::Relaxed);
            }

            let done = done_counter.fetch_add(1, Ordering::Relaxed) + 1;
            if done % 10_000 == 0 {
                let progress = done as f64 / total_cases as f64 * 100.0;
                log::debug!("div progress = {progress:.4}%");
            }
        });

        let checked = checked.load(Ordering::Relaxed);
        let skipped_non_finite = skipped_non_finite.load(Ordering::Relaxed);
        let skipped_invalid_sf = skipped_invalid_sf.load(Ordering::Relaxed);

        println!(
            "div checked={}, skipped_non_finite={}, skipped_invalid_sf={}, mantissas={}, exponents={}, total_cases={}",
            checked,
            skipped_non_finite,
            skipped_invalid_sf,
            mantissas.len(),
            exponents.len(),
            total_cases,
        );

        assert!(checked > 0, "div test did not validate any finite cases");
    }
}