global: snapshot

This commit is contained in:
nym21
2026-03-14 18:27:25 +01:00
parent 9d365f4bbb
commit 0d177494d9
55 changed files with 1117 additions and 1006 deletions
@@ -224,20 +224,27 @@ impl SlidingWindowSorted {
let rank = p * last;
let lo = rank.floor() as usize;
let hi = rank.ceil() as usize;
let frac = rank - lo as f64;
lo_hi[i] = (lo, hi, frac);
lo_hi[i] = (lo, hi, rank - lo as f64);
// Insert unique ranks in sorted order (they're already ~sorted since ps is sorted)
if rank_count == 0 || rank_set[rank_count - 1] != lo {
rank_set[rank_count] = lo;
rank_count += 1;
}
if hi != lo && (rank_count == 0 || rank_set[rank_count - 1] != hi) {
rank_set[rank_count] = lo;
rank_count += 1;
if hi != lo {
rank_set[rank_count] = hi;
rank_count += 1;
}
}
// Sort and deduplicate (interleaved lo/hi values aren't necessarily sorted)
rank_set[..rank_count].sort_unstable();
let mut w = 1;
for r in 1..rank_count {
if rank_set[r] != rank_set[w - 1] {
rank_set[w] = rank_set[r];
w += 1;
}
}
rank_count = w;
// Single pass through blocks to get all values
let ranks = &rank_set[..rank_count];
let mut values = [0.0f64; 10];
+4 -4
View File
@@ -9,10 +9,10 @@ use crate::internal::AmountPerBlock;
/// All fields are lazy transforms from existing sources - no storage.
#[derive(Clone, Traversable)]
pub struct LazyAmount<I: VecIndex> {
pub sats: LazyVecFrom1<I, Sats, I, Sats>,
pub btc: LazyVecFrom1<I, Bitcoin, I, Sats>,
pub cents: LazyVecFrom1<I, Cents, I, Cents>,
pub sats: LazyVecFrom1<I, Sats, I, Sats>,
pub usd: LazyVecFrom1<I, Dollars, I, Dollars>,
pub cents: LazyVecFrom1<I, Cents, I, Cents>,
}
impl LazyAmount<Height> {
@@ -57,10 +57,10 @@ impl LazyAmount<Height> {
);
Self {
sats,
btc,
cents,
sats,
usd,
cents,
}
}
}
@@ -13,10 +13,10 @@ use crate::{
#[derive(Traversable)]
pub struct AmountPerBlock<M: StorageMode = Rw> {
pub sats: PerBlock<Sats, M>,
pub btc: LazyPerBlock<Bitcoin, Sats>,
pub cents: PerBlock<Cents, M>,
pub sats: PerBlock<Sats, M>,
pub usd: LazyPerBlock<Dollars, Cents>,
pub cents: PerBlock<Cents, M>,
}
impl AmountPerBlock {
@@ -47,10 +47,10 @@ impl AmountPerBlock {
);
Ok(Self {
sats,
btc,
cents,
sats,
usd,
cents,
})
}
@@ -6,10 +6,10 @@ use crate::internal::{AmountPerBlock, DerivedResolutions};
#[derive(Clone, Traversable)]
pub struct LazyAmountDerivedResolutions {
pub sats: DerivedResolutions<Sats, Sats>,
pub btc: DerivedResolutions<Bitcoin, Sats>,
pub cents: DerivedResolutions<Cents, Cents>,
pub sats: DerivedResolutions<Sats, Sats>,
pub usd: DerivedResolutions<Dollars, Dollars>,
pub cents: DerivedResolutions<Cents, Cents>,
}
impl LazyAmountDerivedResolutions {
@@ -54,10 +54,10 @@ impl LazyAmountDerivedResolutions {
);
Self {
sats,
btc,
cents,
sats,
usd,
cents,
}
}
}
@@ -14,10 +14,10 @@ use crate::{
/// Single window slot: lazy rolling sum for Amount (sats + btc + cents + usd).
#[derive(Clone, Traversable)]
pub struct LazyRollingSumAmountFromHeight {
pub sats: LazyRollingSumFromHeight<Sats>,
pub btc: LazyPerBlock<Bitcoin, Sats>,
pub cents: LazyRollingSumFromHeight<Cents>,
pub sats: LazyRollingSumFromHeight<Sats>,
pub usd: LazyPerBlock<Dollars, Cents>,
pub cents: LazyRollingSumFromHeight<Cents>,
}
/// Lazy rolling sums for all 4 windows, for Amount (sats + btc + cents + usd).
@@ -112,10 +112,10 @@ impl LazyRollingSumsAmountFromHeight {
};
LazyRollingSumAmountFromHeight {
sats,
btc,
cents,
sats,
usd,
cents,
}
};
@@ -29,8 +29,8 @@ impl CentsType for CentsSigned {
/// Generic over `C` to support both `Cents` (unsigned) and `CentsSigned` (signed).
#[derive(Traversable)]
pub struct FiatPerBlock<C: CentsType, M: StorageMode = Rw> {
pub cents: PerBlock<C, M>,
pub usd: LazyPerBlock<Dollars, C>,
pub cents: PerBlock<C, M>,
}
impl<C: CentsType> FiatPerBlock<C> {
@@ -48,6 +48,6 @@ impl<C: CentsType> FiatPerBlock<C> {
cents.height.read_only_boxed_clone(),
&cents,
);
Ok(Self { cents, usd })
Ok(Self { usd, cents })
}
}
@@ -8,8 +8,8 @@ use crate::internal::{CentsType, PerBlock, Identity, LazyPerBlock, NumericValue}
/// Zero extra stored vecs.
#[derive(Clone, Traversable)]
pub struct LazyFiatPerBlock<C: CentsType> {
pub cents: LazyPerBlock<C, C>,
pub usd: LazyPerBlock<Dollars, C>,
pub cents: LazyPerBlock<C, C>,
}
impl<C: CentsType> LazyFiatPerBlock<C> {
@@ -33,6 +33,6 @@ impl<C: CentsType> LazyFiatPerBlock<C> {
source.height.read_only_boxed_clone(),
source,
);
Self { cents, usd }
Self { usd, cents }
}
}
@@ -13,8 +13,8 @@ use crate::{
#[derive(Clone, Traversable)]
pub struct LazyRollingSumFiatFromHeight<C: CentsType> {
pub cents: LazyRollingSumFromHeight<C>,
pub usd: LazyPerBlock<Dollars, C>,
pub cents: LazyRollingSumFromHeight<C>,
}
#[derive(Clone, Deref, DerefMut, Traversable)]
@@ -69,7 +69,7 @@ impl<C: CentsType> LazyRollingSumsFiatFromHeight<C> {
)),
};
LazyRollingSumFiatFromHeight { cents, usd }
LazyRollingSumFiatFromHeight { usd, cents }
};
Self(cached_starts.0.map_with_suffix(make_slot))
@@ -19,8 +19,8 @@ use crate::{
/// Generic price metric with cents, USD, and sats representations.
#[derive(Clone, Traversable)]
pub struct Price<C> {
pub cents: C,
pub usd: LazyPerBlock<Dollars, Cents>,
pub cents: C,
pub sats: LazyPerBlock<SatsFract, Dollars>,
}
@@ -45,7 +45,7 @@ impl Price<PerBlock<Cents>> {
version,
&usd,
);
Ok(Self { cents, usd, sats })
Ok(Self { usd, cents, sats })
}
}
@@ -75,6 +75,6 @@ where
version,
&usd,
);
Self { cents, usd, sats }
Self { usd, cents, sats }
}
}
@@ -11,8 +11,8 @@ use super::{RatioPerBlock, RatioPerBlockPercentiles};
#[derive(Traversable)]
pub struct PriceWithRatioPerBlock<M: StorageMode = Rw> {
pub cents: PerBlock<Cents, M>,
pub usd: LazyPerBlock<Dollars, Cents>,
pub cents: PerBlock<Cents, M>,
pub sats: LazyPerBlock<SatsFract, Dollars>,
pub bps: PerBlock<BasisPoints32, M>,
pub ratio: LazyPerBlock<StoredF32, BasisPoints32>,
@@ -28,8 +28,8 @@ impl PriceWithRatioPerBlock {
let price = Price::forced_import(db, name, version, indexes)?;
let ratio = RatioPerBlock::forced_import(db, name, version, indexes)?;
Ok(Self {
cents: price.cents,
usd: price.usd,
cents: price.cents,
sats: price.sats,
bps: ratio.bps,
ratio: ratio.ratio,
@@ -44,7 +44,7 @@ where
/// Lazy rolling deltas for all 4 window durations (24h, 1w, 1m, 1y).
///
/// Tree shape: `change._24h/...`, `rate._24h/...` — matches old `RollingDelta`.
/// Tree shape: `absolute._24h/...`, `rate._24h/...` — matches old `RollingDelta`.
///
/// Replaces `RollingDelta`, `RollingDelta1m`, and `RollingDeltaExcept1m` — since
/// there is no storage cost, all 4 windows are always available.
@@ -55,7 +55,7 @@ where
C: NumericValue + JsonSchema,
B: BpsType,
{
pub change: Windows<LazyDeltaFromHeight<S, C, DeltaChange>>,
pub absolute: Windows<LazyDeltaFromHeight<S, C, DeltaChange>>,
pub rate: Windows<LazyDeltaPercentFromHeight<S, B>>,
}
@@ -96,7 +96,7 @@ where
version,
indexes,
);
let change = LazyDeltaFromHeight {
let absolute = LazyDeltaFromHeight {
height: change_vec,
resolutions: Box::new(change_resolutions),
};
@@ -154,12 +154,12 @@ where
percent,
};
(change, rate)
(absolute, rate)
};
let (change, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
let (absolute, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
Self { change, rate }
Self { absolute, rate }
}
}
@@ -174,13 +174,13 @@ where
S: VecValue,
C: CentsType,
{
pub cents: LazyDeltaFromHeight<S, C, DeltaChange>,
pub usd: LazyPerBlock<Dollars, C>,
pub cents: LazyDeltaFromHeight<S, C, DeltaChange>,
}
/// Lazy fiat rolling deltas for all 4 windows.
///
/// Tree shape: `change._24h.{cents,usd}/...`, `rate._24h/...` — matches old `FiatRollingDelta`.
/// Tree shape: `absolute._24h.{cents,usd}/...`, `rate._24h/...` — matches old `FiatRollingDelta`.
///
/// Replaces `FiatRollingDelta`, `FiatRollingDelta1m`, and `FiatRollingDeltaExcept1m`.
#[derive(Clone, Traversable)]
@@ -190,7 +190,7 @@ where
C: CentsType,
B: BpsType,
{
pub change: Windows<LazyDeltaFiatFromHeight<S, C>>,
pub absolute: Windows<LazyDeltaFiatFromHeight<S, C>>,
pub rate: Windows<LazyDeltaPercentFromHeight<S, B>>,
}
@@ -250,7 +250,7 @@ where
)),
};
let change = LazyDeltaFiatFromHeight { cents, usd };
let absolute = LazyDeltaFiatFromHeight { usd, cents };
// Rate BPS: (source[h] - source[ago]) / source[ago] as B (via f64)
let rate_vec = LazyDeltaVec::<Height, S, B, DeltaRate>::new(
@@ -303,11 +303,11 @@ where
percent,
};
(change, rate)
(absolute, rate)
};
let (change, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
let (absolute, rate) = cached_starts.0.map_with_suffix(make_slot).unzip();
Self { change, rate }
Self { absolute, rate }
}
}