mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-08-08 08:33:06 -07:00
211 lines
4.9 KiB
Rust
211 lines
4.9 KiB
Rust
use std::marker::PhantomData;
|
|
|
|
use brk_types::{
|
|
Bitcoin, Cents, Dollars, PartsPerMillion32, Sats, StoredF32, StoredF64, StoredI8, StoredU16,
|
|
StoredU32, StoredU64, VSize, Weight,
|
|
};
|
|
use vecdb::{BinaryTransform, UnaryTransform, VecValue};
|
|
|
|
pub struct Identity<T>(PhantomData<T>);
|
|
|
|
impl<T: VecValue> UnaryTransform<T, T> for Identity<T> {
|
|
#[inline(always)]
|
|
fn apply(v: T) -> T {
|
|
v
|
|
}
|
|
}
|
|
|
|
pub struct HalveSats;
|
|
|
|
impl UnaryTransform<Sats, Sats> for HalveSats {
|
|
#[inline(always)]
|
|
fn apply(sats: Sats) -> Sats {
|
|
sats / 2
|
|
}
|
|
}
|
|
|
|
pub struct HalveSatsToBitcoin;
|
|
|
|
impl UnaryTransform<Sats, Bitcoin> for HalveSatsToBitcoin {
|
|
#[inline(always)]
|
|
fn apply(sats: Sats) -> Bitcoin {
|
|
Bitcoin::from(sats / 2)
|
|
}
|
|
}
|
|
|
|
pub struct HalveCents;
|
|
|
|
impl UnaryTransform<Cents, Cents> for HalveCents {
|
|
#[inline(always)]
|
|
fn apply(cents: Cents) -> Cents {
|
|
cents / 2u64
|
|
}
|
|
}
|
|
|
|
pub struct HalveDollars;
|
|
|
|
impl UnaryTransform<Dollars, Dollars> for HalveDollars {
|
|
#[inline(always)]
|
|
fn apply(dollars: Dollars) -> Dollars {
|
|
dollars.halved()
|
|
}
|
|
}
|
|
|
|
pub struct MaskSats;
|
|
|
|
impl BinaryTransform<StoredU32, Sats, Sats> for MaskSats {
|
|
#[inline(always)]
|
|
fn apply(mask: StoredU32, value: Sats) -> Sats {
|
|
if mask == StoredU32::ONE {
|
|
value
|
|
} else {
|
|
Sats::ZERO
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BinaryTransform<StoredU64, Sats, Sats> for MaskSats {
|
|
#[inline]
|
|
fn apply(mask: StoredU64, value: Sats) -> Sats {
|
|
if u64::from(mask) != 0 {
|
|
value
|
|
} else {
|
|
Sats::ZERO
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct ReturnF32Tenths<const V: u16>;
|
|
|
|
impl<S, const V: u16> UnaryTransform<S, StoredF32> for ReturnF32Tenths<V> {
|
|
#[inline(always)]
|
|
fn apply(_: S) -> StoredF32 {
|
|
StoredF32::from(V as f32 / 10.0)
|
|
}
|
|
}
|
|
|
|
pub struct ReturnU16<const V: u16>;
|
|
|
|
impl<S, const V: u16> UnaryTransform<S, StoredU16> for ReturnU16<V> {
|
|
#[inline(always)]
|
|
fn apply(_: S) -> StoredU16 {
|
|
StoredU16::new(V)
|
|
}
|
|
}
|
|
|
|
pub struct ReturnI8<const V: i8>;
|
|
|
|
impl<S, const V: i8> UnaryTransform<S, StoredI8> for ReturnI8<V> {
|
|
#[inline(always)]
|
|
fn apply(_: S) -> StoredI8 {
|
|
StoredI8::new(V)
|
|
}
|
|
}
|
|
|
|
pub struct ThsToPhsF32;
|
|
|
|
impl UnaryTransform<StoredF32, StoredF32> for ThsToPhsF32 {
|
|
#[inline(always)]
|
|
fn apply(ths: StoredF32) -> StoredF32 {
|
|
(*ths * 1000.0).into()
|
|
}
|
|
}
|
|
|
|
pub struct BlocksToDaysF32;
|
|
|
|
impl UnaryTransform<StoredU32, StoredF32> for BlocksToDaysF32 {
|
|
#[inline(always)]
|
|
fn apply(blocks: StoredU32) -> StoredF32 {
|
|
(*blocks as f32 / crate::blocks::TARGET_BLOCKS_PER_DAY_F32).into()
|
|
}
|
|
}
|
|
|
|
pub struct StoredU64ToStoredU32;
|
|
|
|
impl UnaryTransform<StoredU64, StoredU32> for StoredU64ToStoredU32 {
|
|
#[inline(always)]
|
|
fn apply(value: StoredU64) -> StoredU32 {
|
|
StoredU32::new(
|
|
u32::try_from(u64::from(value))
|
|
.expect("per-block value reconstructed from StoredU64 must fit StoredU32"),
|
|
)
|
|
}
|
|
}
|
|
|
|
pub struct PerSecond<const SECONDS: u32>;
|
|
|
|
impl<const SECONDS: u32> UnaryTransform<StoredU64, StoredF32> for PerSecond<SECONDS> {
|
|
#[inline(always)]
|
|
fn apply(value: StoredU64) -> StoredF32 {
|
|
StoredF32::from(u64::from(value) as f64 / SECONDS as f64)
|
|
}
|
|
}
|
|
|
|
pub struct OneMinusF64;
|
|
|
|
impl UnaryTransform<StoredF64, StoredF64> for OneMinusF64 {
|
|
#[inline(always)]
|
|
fn apply(v: StoredF64) -> StoredF64 {
|
|
StoredF64::from(1.0 - *v)
|
|
}
|
|
}
|
|
|
|
pub struct OddsF64;
|
|
|
|
impl UnaryTransform<StoredF64, StoredF64> for OddsF64 {
|
|
#[inline(always)]
|
|
fn apply(value: StoredF64) -> StoredF64 {
|
|
value / StoredF64::from(1.0 - *value)
|
|
}
|
|
}
|
|
|
|
pub struct DifficultyToHashF64;
|
|
|
|
impl UnaryTransform<StoredF64, StoredF64> for DifficultyToHashF64 {
|
|
#[inline(always)]
|
|
fn apply(difficulty: StoredF64) -> StoredF64 {
|
|
const MULTIPLIER: f64 = 4_294_967_296.0 / 600.0; // 2^32 / 600
|
|
StoredF64::from(*difficulty * MULTIPLIER)
|
|
}
|
|
}
|
|
|
|
pub struct OneMinusPpm;
|
|
|
|
impl UnaryTransform<PartsPerMillion32, PartsPerMillion32> for OneMinusPpm {
|
|
#[inline(always)]
|
|
fn apply(value: PartsPerMillion32) -> PartsPerMillion32 {
|
|
PartsPerMillion32::ONE - value
|
|
}
|
|
}
|
|
|
|
pub struct VBytesToWeight;
|
|
|
|
impl UnaryTransform<StoredU64, Weight> for VBytesToWeight {
|
|
#[inline(always)]
|
|
fn apply(vbytes: StoredU64) -> Weight {
|
|
Weight::from(VSize::new(*vbytes))
|
|
}
|
|
}
|
|
|
|
pub struct WeightToVSize;
|
|
|
|
impl UnaryTransform<Weight, VSize> for WeightToVSize {
|
|
#[inline(always)]
|
|
fn apply(weight: Weight) -> VSize {
|
|
VSize::from(weight)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn odds_are_the_ratio_to_the_complement() {
|
|
assert_eq!(OddsF64::apply(StoredF64::from(0.0)), StoredF64::from(0.0));
|
|
assert_eq!(OddsF64::apply(StoredF64::from(0.5)), StoredF64::from(1.0));
|
|
assert_eq!(OddsF64::apply(StoredF64::from(0.75)), StoredF64::from(3.0));
|
|
assert_eq!(OddsF64::apply(StoredF64::from(1.0)), StoredF64::NAN);
|
|
}
|
|
}
|