computer: renames

This commit is contained in:
nym21
2026-01-10 10:23:29 +01:00
parent 69729842a4
commit 3bc0615000
229 changed files with 3203 additions and 3944 deletions

View File

@@ -0,0 +1,64 @@
//! ComputedDateAverage - dateindex storage + lazy periods for average-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, LazyPeriodsAverage};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDateAverage<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyPeriodsAverage<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDateAverage<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
Ok(Self {
rest: LazyPeriodsAverage::from_source(
name,
version + VERSION,
dateindex.boxed_clone(),
indexes,
),
dateindex,
})
}
pub fn compute_all<F>(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
}

View File

@@ -0,0 +1,628 @@
//! Binary transform composite from DateIndex - Last aggregation only.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
use crate::internal::{
ComputedBlockLast, ComputedBlockSum, ComputedDateLast, ComputedVecValue, LazyBinaryTransformLast,
LazyPeriodsLast, LazyPeriodsSumCum, NumericValue,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDateLast<T, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub dateindex: LazyVecFrom2<DateIndex, T, DateIndex, S1T, DateIndex, S2T>,
pub weekindex: LazyBinaryTransformLast<WeekIndex, T, S1T, S2T>,
pub monthindex: LazyBinaryTransformLast<MonthIndex, T, S1T, S2T>,
pub quarterindex: LazyBinaryTransformLast<QuarterIndex, T, S1T, S2T>,
pub semesterindex: LazyBinaryTransformLast<SemesterIndex, T, S1T, S2T>,
pub yearindex: LazyBinaryTransformLast<YearIndex, T, S1T, S2T>,
pub decadeindex: LazyBinaryTransformLast<DecadeIndex, T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryDateLast<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn from_computed_both_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDateLast<S1T>,
source2: &ComputedDateLast<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_derived_last_and_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
source1: &LazyPeriodsLast<S1T>,
source2: &ComputedDateLast<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
dateindex_source1,
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_derived_last_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
source1: &LazyPeriodsLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
dateindex_source1,
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_both_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
source1: &LazyPeriodsLast<S1T>,
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
source2: &LazyPeriodsLast<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
dateindex_source1,
dateindex_source2,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_height_and_dateindex_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockLast<S1T>,
source2: &ComputedDateLast<S2T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.0.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_dateindex_and_height_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDateLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_both_block_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_lazy_last::<F, _, _, _, _>(
name,
v,
&source1.$p,
&source2.$p,
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.0.boxed_clone(),
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_dateindex_last_and_height_sum<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDateLast<S1T>,
source2: &ComputedBlockSum<S2T>,
) -> Self
where
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_block_last_and_height_sum<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockLast<S1T>,
source2: &ComputedBlockSum<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.0.boxed_clone(),
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_both_sum_cum_cumulatives<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
dates1: &LazyPeriodsSumCum<S1T>,
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
dates2: &LazyPeriodsSumCum<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
dates1.$p.cumulative.boxed_clone(),
dates2.$p.cumulative.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
dateindex_source1,
dateindex_source2,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a LazyPeriodsLast source and a BinaryDateLast source.
pub fn from_derived_last_and_binary_last<F, S2aT, S2bT>(
name: &str,
version: Version,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
source1: &LazyPeriodsLast<S1T>,
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S2aT: ComputedVecValue + JsonSchema,
S2bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
dateindex_source1,
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a BinaryDateLast source and a ComputedDateLast source.
pub fn from_binary_and_computed_last<F, S1aT, S1bT>(
name: &str,
version: Version,
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
source2: &ComputedDateLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a BinaryDateLast source and a ComputedBlockLast source.
pub fn from_binary_and_block_last<F, S1aT, S1bT>(
name: &str,
version: Version,
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from a ComputedDateLast source and a BinaryDateLast source.
pub fn from_computed_and_binary_last<F, S2aT, S2bT>(
name: &str,
version: Version,
source1: &ComputedDateLast<S1T>,
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S2aT: ComputedVecValue + JsonSchema,
S2bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
/// Create from two BinaryDateLast sources.
pub fn from_both_binary_last<F, S1aT, S1bT, S2aT, S2bT>(
name: &str,
version: Version,
source1: &LazyBinaryDateLast<S1T, S1aT, S1bT>,
source2: &LazyBinaryDateLast<S2T, S2aT, S2bT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
S2aT: ComputedVecValue + JsonSchema,
S2bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.$p.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyVecFrom2::transformed::<F>(
name,
v,
source1.dateindex.boxed_clone(),
source2.dateindex.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,61 @@
//! Binary transform for Sum-only pattern across date periods.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, LazyBinaryTransformSum, NumericValue};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDateSum<T, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub dateindex: LazyBinaryTransformSum<DateIndex, T, S1T, S2T>,
pub weekindex: LazyBinaryTransformSum<WeekIndex, T, S1T, S2T>,
pub monthindex: LazyBinaryTransformSum<MonthIndex, T, S1T, S2T>,
pub quarterindex: LazyBinaryTransformSum<QuarterIndex, T, S1T, S2T>,
pub semesterindex: LazyBinaryTransformSum<SemesterIndex, T, S1T, S2T>,
pub yearindex: LazyBinaryTransformSum<YearIndex, T, S1T, S2T>,
pub decadeindex: LazyBinaryTransformSum<DecadeIndex, T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryDateSum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: NumericValue + JsonSchema,
S2T: NumericValue + JsonSchema,
{
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSum<S1T>,
source2: &ComputedDerivedBlockSum<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSum::from_boxed::<F>(name, v, source1.$p.boxed_clone(), source2.$p.boxed_clone())
};
}
Self {
dateindex: LazyBinaryTransformSum::from_sum::<F>(name, v, &source1.dateindex, &source2.dateindex),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,281 @@
//! Binary transform for SumCum pattern across date periods.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec};
use crate::internal::{
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast,
ComputedDerivedBlockSumCum, ComputedVecValue, LazyBinaryTransformSumCum, LazyPeriodsFull,
LazyPeriodsSumCum, NumericValue, SumCum,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDateSumCum<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub dateindex: LazyBinaryTransformSumCum<DateIndex, T, S1T, S2T>,
pub weekindex: LazyBinaryTransformSumCum<WeekIndex, T, S1T, S2T>,
pub monthindex: LazyBinaryTransformSumCum<MonthIndex, T, S1T, S2T>,
pub quarterindex: LazyBinaryTransformSumCum<QuarterIndex, T, S1T, S2T>,
pub semesterindex: LazyBinaryTransformSumCum<SemesterIndex, T, S1T, S2T>,
pub yearindex: LazyBinaryTransformSumCum<YearIndex, T, S1T, S2T>,
pub decadeindex: LazyBinaryTransformSumCum<DecadeIndex, T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryDateSumCum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
#[allow(clippy::too_many_arguments)]
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex1: &SumCum<DateIndex, S1T>,
periods1: &LazyPeriodsSumCum<S1T>,
dateindex2: &SumCum<DateIndex, S2T>,
periods2: &LazyPeriodsSumCum<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources::<F>(
name, v,
periods1.$p.sum.boxed_clone(), periods2.$p.sum.boxed_clone(),
periods1.$p.cumulative.boxed_clone(), periods2.$p.cumulative.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum::<F>(name, v, dateindex1, dateindex2),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_derived_full<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex1: &SumCum<DateIndex, S1T>,
dates1: &LazyPeriodsFull<S1T>,
dateindex2: &SumCum<DateIndex, S2T>,
dates2: &LazyPeriodsFull<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_lazy_stats_aggregate::<F, _, _, _, _>(
name, v, &dates1.$p, &dates2.$p,
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum::<F>(name, v, dateindex1, dateindex2),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
// --- Raw variants (no _sum suffix) for pure SumCum types ---
#[allow(clippy::too_many_arguments)]
pub fn from_computed_sum_raw<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex1: &SumCum<DateIndex, S1T>,
periods1: &LazyPeriodsSumCum<S1T>,
dateindex2: &SumCum<DateIndex, S2T>,
periods2: &LazyPeriodsSumCum<S2T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources_sum_raw::<F>(
name, v,
periods1.$p.sum.boxed_clone(), periods2.$p.sum.boxed_clone(),
periods1.$p.cumulative.boxed_clone(), periods2.$p.cumulative.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum_sum_raw::<F>(name, v, dateindex1, dateindex2),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
// --- Methods accepting SumCum + Last sources ---
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name, v,
source1.rest.$p.sum.boxed_clone(),
source1.rest.$p.cumulative.boxed_clone(),
source2.rest.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
name, v, &source1.dateindex, &source2.dateindex,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name, v,
source1.$p.sum.boxed_clone(),
source1.$p.cumulative.boxed_clone(),
source2.rest.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
name, v, &source1.dateindex, &source2.dateindex,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name, v,
source1.rest.$p.sum.boxed_clone(),
source1.rest.$p.cumulative.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
name, v, &source1.dateindex, &source2.dateindex,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name, v,
source1.$p.sum.boxed_clone(),
source1.$p.cumulative.boxed_clone(),
source2.$p.boxed_clone(),
)
};
}
Self {
dateindex: LazyBinaryTransformSumCum::from_sum_cum_last_sum_raw::<F>(
name, v, &source1.dateindex, &source2.dateindex,
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,64 @@
//! ComputedVecsDate using only first-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, LazyPeriodsFirst};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDateFirst<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyPeriodsFirst<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDateFirst<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
Ok(Self {
rest: LazyPeriodsFirst::from_source(
name,
version + VERSION,
dateindex.boxed_clone(),
indexes,
),
dateindex,
})
}
pub fn compute_all<F>(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
}

View File

@@ -0,0 +1,73 @@
//! ComputedVecsDate using only last-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, IterableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, LazyPeriodsLast};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDateLast<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyPeriodsLast<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDateLast<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
Ok(Self {
rest: LazyPeriodsLast::from_source(
name,
version + VERSION,
dateindex.boxed_clone(),
indexes,
),
dateindex,
})
}
pub fn compute_all<F>(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
pub fn compute_rest(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
_dateindex: Option<&impl IterableVec<DateIndex, T>>,
) -> Result<()> {
Ok(())
}
}

View File

@@ -0,0 +1,62 @@
//! Lazy transform for Full date sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedVecValue, Full, LazyPeriodsFull, LazyTransformFull, LazyTransformStats};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDateFull<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub dateindex: LazyTransformFull<DateIndex, T, S1T>,
pub weekindex: LazyTransformStats<WeekIndex, T, S1T>,
pub monthindex: LazyTransformStats<MonthIndex, T, S1T>,
pub quarterindex: LazyTransformStats<QuarterIndex, T, S1T>,
pub semesterindex: LazyTransformStats<SemesterIndex, T, S1T>,
pub yearindex: LazyTransformStats<YearIndex, T, S1T>,
pub decadeindex: LazyTransformStats<DecadeIndex, T, S1T>,
}
impl<T, S1T> LazyDateFull<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_full<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex: &Full<DateIndex, S1T>,
source: &LazyPeriodsFull<S1T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformStats::from_boxed::<F>(
name, v,
source.$p.average.boxed_clone(), source.$p.min.boxed_clone(),
source.$p.max.boxed_clone(), source.$p.sum.boxed_clone(),
source.$p.cumulative.boxed_clone(),
)
};
}
Self {
dateindex: LazyTransformFull::from_stats_aggregate::<F>(name, v, dateindex),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,87 @@
//! Lazy transform for Last-only date sources.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedBlockLast, ComputedDateLast, ComputedVecValue, LazyPeriodsLast, LazyTransformLast, NumericValue};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDateLast<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub dateindex: LazyTransformLast<DateIndex, T, S1T>,
pub weekindex: LazyTransformLast<WeekIndex, T, S1T>,
pub monthindex: LazyTransformLast<MonthIndex, T, S1T>,
pub quarterindex: LazyTransformLast<QuarterIndex, T, S1T>,
pub semesterindex: LazyTransformLast<SemesterIndex, T, S1T>,
pub yearindex: LazyTransformLast<YearIndex, T, S1T>,
pub decadeindex: LazyTransformLast<DecadeIndex, T, S1T>,
}
impl<T, S1T> LazyDateLast<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_source<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedDateLast<S1T>,
) -> Self {
Self::from_computed::<F>(name, version, source.dateindex.boxed_clone(), source)
}
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
source: &ComputedDateLast<S1T>,
) -> Self {
Self::from_derived::<F>(name, version, dateindex_source, &source.rest)
}
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
source: &LazyPeriodsLast<S1T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformLast::from_lazy_last::<F, _, _>(name, v, &source.$p)
};
}
Self {
dateindex: LazyTransformLast::from_boxed::<F>(name, v, dateindex_source),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
pub fn from_block_source<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedBlockLast<S1T>,
) -> Self
where
S1T: NumericValue,
{
Self::from_derived::<F>(name, version, source.dateindex.0.boxed_clone(), &source.dates)
}
}

View File

@@ -0,0 +1,57 @@
//! Lazy transform for Sum-only date sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedVecValue, LazyPeriodsSum, LazyTransformSum};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDateSum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub dateindex: LazyTransformSum<DateIndex, T, S1T>,
pub weekindex: LazyTransformSum<WeekIndex, T, S1T>,
pub monthindex: LazyTransformSum<MonthIndex, T, S1T>,
pub quarterindex: LazyTransformSum<QuarterIndex, T, S1T>,
pub semesterindex: LazyTransformSum<SemesterIndex, T, S1T>,
pub yearindex: LazyTransformSum<YearIndex, T, S1T>,
pub decadeindex: LazyTransformSum<DecadeIndex, T, S1T>,
}
impl<T, S1T> LazyDateSum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, S1T>,
source: &LazyPeriodsSum<S1T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformSum::from_boxed::<F>(name, v, source.$p.boxed_clone())
};
}
Self {
dateindex: LazyTransformSum::from_boxed::<F>(name, v, dateindex_source),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,59 @@
//! Lazy transform for SumCum date sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedVecValue, LazyPeriodsSumCum, LazyTransformSumCum, SumCum};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDateSumCum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub dateindex: LazyTransformSumCum<DateIndex, T, S1T>,
pub weekindex: LazyTransformSumCum<WeekIndex, T, S1T>,
pub monthindex: LazyTransformSumCum<MonthIndex, T, S1T>,
pub quarterindex: LazyTransformSumCum<QuarterIndex, T, S1T>,
pub semesterindex: LazyTransformSumCum<SemesterIndex, T, S1T>,
pub yearindex: LazyTransformSumCum<YearIndex, T, S1T>,
pub decadeindex: LazyTransformSumCum<DecadeIndex, T, S1T>,
}
impl<T, S1T> LazyDateSumCum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_sum_cum<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex: &SumCum<DateIndex, S1T>,
source: &LazyPeriodsSumCum<S1T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformSumCum::from_boxed_sum_raw::<F>(
name, v, source.$p.sum.boxed_clone(), source.$p.cumulative.boxed_clone(),
)
};
}
Self {
dateindex: LazyTransformSumCum::from_sum_cum_sum_raw::<F>(name, v, dateindex),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,64 @@
//! ComputedVecsDate using only max-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, LazyPeriodsMax};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDateMax<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyPeriodsMax<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDateMax<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
Ok(Self {
rest: LazyPeriodsMax::from_source(
name,
version + VERSION,
dateindex.boxed_clone(),
indexes,
),
dateindex,
})
}
pub fn compute_all<F>(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
}

View File

@@ -0,0 +1,64 @@
//! ComputedVecsDate using only min-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, LazyPeriodsMin};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDateMin<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: EagerVec<PcoVec<DateIndex, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyPeriodsMin<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDateMin<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
Ok(Self {
rest: LazyPeriodsMin::from_source(
name,
version + VERSION,
dateindex.boxed_clone(),
indexes,
),
dateindex,
})
}
pub fn compute_all<F>(
&mut self,
_starting_indexes: &ComputeIndexes,
_exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
}

View File

@@ -0,0 +1,25 @@
mod average;
mod binary_last;
mod binary_sum;
mod binary_sum_cum;
mod first;
mod last;
mod lazy_full;
mod lazy_last;
mod lazy_sum;
mod lazy_sum_cum;
mod max;
mod min;
pub use average::*;
pub use binary_last::*;
pub use binary_sum::*;
pub use binary_sum_cum::*;
pub use first::*;
pub use last::*;
pub use lazy_full::*;
pub use lazy_last::*;
pub use lazy_sum::*;
pub use lazy_sum_cum::*;
pub use max::*;
pub use min::*;

View File

@@ -0,0 +1,58 @@
//! Derived date periods with average-value aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyAverage};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsAverage<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyAverage<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyAverage<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyAverage<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyAverage<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyAverage<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyAverage<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsAverage<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyAverage::from_source_raw(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,63 @@
//! Derived date periods with distribution aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyDistribution};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsDistribution<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyDistribution<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyDistribution<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyDistribution<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyDistribution<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyDistribution<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyDistribution<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsDistribution<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from external dateindex sources for distribution stats.
pub fn from_sources(
name: &str,
version: Version,
average_source: IterableBoxedVec<DateIndex, T>,
min_source: IterableBoxedVec<DateIndex, T>,
max_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyDistribution::from_distribution(
name, v, average_source.clone(), min_source.clone(), max_source.clone(),
indexes.$idx.identity.boxed_clone(),
)
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,58 @@
//! Derived date periods with first-value aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyFirst};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsFirst<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyFirst<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyFirst<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyFirst<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyFirst<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyFirst<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyFirst<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsFirst<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyFirst::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,68 @@
//! Derived date periods with full stats aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyFull};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsFull<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyFull<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyFull<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyFull<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyFull<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyFull<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyFull<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsFull<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from external dateindex sources for full stats.
#[allow(clippy::too_many_arguments)]
pub fn from_sources(
name: &str,
version: Version,
average_source: IterableBoxedVec<DateIndex, T>,
min_source: IterableBoxedVec<DateIndex, T>,
max_source: IterableBoxedVec<DateIndex, T>,
sum_source: IterableBoxedVec<DateIndex, T>,
cumulative_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyFull::from_stats_aggregate(
name, v,
average_source.clone(), min_source.clone(), max_source.clone(),
sum_source.clone(), cumulative_source.clone(),
indexes.$idx.identity.boxed_clone(),
)
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,58 @@
//! Derived date periods with last-value aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyLast};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsLast<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyLast<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyLast<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyLast<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyLast<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyLast<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyLast<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsLast<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyLast::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,88 @@
//! Generic lazy vecs for all time period indexes.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{ComputeFrom1, Formattable, IterableCloneableVec, LazyVecFrom1, VecValue};
use crate::indexes;
/// Lazy vecs for all time period indexes (no height).
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodVecs<T>
where
T: VecValue + Formattable + Serialize + JsonSchema,
{
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, DateIndex>,
pub weekindex: LazyVecFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
pub monthindex: LazyVecFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
pub quarterindex: LazyVecFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
pub semesterindex: LazyVecFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
pub yearindex: LazyVecFrom1<YearIndex, T, YearIndex, YearIndex>,
pub decadeindex: LazyVecFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
}
impl<T: VecValue + Formattable + Serialize + JsonSchema> LazyPeriodVecs<T> {
#[allow(clippy::too_many_arguments)]
pub fn new(
name: &str,
version: Version,
indexes: &indexes::Vecs,
dateindex_fn: ComputeFrom1<DateIndex, T, DateIndex, DateIndex>,
weekindex_fn: ComputeFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
monthindex_fn: ComputeFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
quarterindex_fn: ComputeFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
semesterindex_fn: ComputeFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
yearindex_fn: ComputeFrom1<YearIndex, T, YearIndex, YearIndex>,
decadeindex_fn: ComputeFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
) -> Self {
Self {
dateindex: LazyVecFrom1::init(
name,
version,
indexes.dateindex.identity.boxed_clone(),
dateindex_fn,
),
weekindex: LazyVecFrom1::init(
name,
version,
indexes.weekindex.identity.boxed_clone(),
weekindex_fn,
),
monthindex: LazyVecFrom1::init(
name,
version,
indexes.monthindex.identity.boxed_clone(),
monthindex_fn,
),
quarterindex: LazyVecFrom1::init(
name,
version,
indexes.quarterindex.identity.boxed_clone(),
quarterindex_fn,
),
semesterindex: LazyVecFrom1::init(
name,
version,
indexes.semesterindex.identity.boxed_clone(),
semesterindex_fn,
),
yearindex: LazyVecFrom1::init(
name,
version,
indexes.yearindex.identity.boxed_clone(),
yearindex_fn,
),
decadeindex: LazyVecFrom1::init(
name,
version,
indexes.decadeindex.identity.boxed_clone(),
decadeindex_fn,
),
}
}
}

View File

@@ -0,0 +1,58 @@
//! Derived date periods with max-value aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyMax};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsMax<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyMax<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyMax<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyMax<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyMax<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyMax<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyMax<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsMax<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyMax::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,58 @@
//! Derived date periods with min-value aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazyMin};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsMin<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazyMin<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazyMin<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazyMin<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazyMin<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazyMin<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazyMin<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsMin<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazyMin::from_source(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,21 @@
mod average;
mod distribution;
mod first;
mod full;
mod last;
mod lazy;
mod max;
mod min;
mod sum;
mod sum_cum;
pub use average::*;
pub use distribution::*;
pub use first::*;
pub use full::*;
pub use last::*;
pub use lazy::*;
pub use max::*;
pub use min::*;
pub use sum::*;
pub use sum_cum::*;

View File

@@ -0,0 +1,58 @@
//! Derived date periods with sum aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazySum};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsSum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazySum<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazySum<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazySum<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazySum<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazySum<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazySum<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsSum<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from an external dateindex source.
pub fn from_source(
name: &str,
version: Version,
dateindex_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazySum::from_source_raw(name, v, dateindex_source.clone(), indexes.$idx.identity.boxed_clone())
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,62 @@
//! Derived date periods with sum+cumulative aggregation.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec};
use crate::{indexes, internal::LazySumCum};
use crate::internal::ComputedVecValue;
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyPeriodsSumCum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub weekindex: LazySumCum<WeekIndex, T, DateIndex, WeekIndex>,
pub monthindex: LazySumCum<MonthIndex, T, DateIndex, MonthIndex>,
pub quarterindex: LazySumCum<QuarterIndex, T, DateIndex, QuarterIndex>,
pub semesterindex: LazySumCum<SemesterIndex, T, DateIndex, SemesterIndex>,
pub yearindex: LazySumCum<YearIndex, T, DateIndex, YearIndex>,
pub decadeindex: LazySumCum<DecadeIndex, T, DateIndex, DecadeIndex>,
}
const VERSION: Version = Version::ZERO;
impl<T> LazyPeriodsSumCum<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
/// Create from external dateindex sum and cumulative sources.
pub fn from_sources(
name: &str,
version: Version,
sum_source: IterableBoxedVec<DateIndex, T>,
cumulative_source: IterableBoxedVec<DateIndex, T>,
indexes: &indexes::Vecs,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($idx:ident) => {
LazySumCum::from_sources_sum_raw(
name, v, sum_source.clone(), cumulative_source.clone(),
indexes.$idx.identity.boxed_clone(),
)
};
}
Self {
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,144 @@
//! Lazy binary transform for derived block with Last aggregation only.
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec};
use crate::internal::{
ComputedBlockLast, ComputedBlockSumCum, ComputedHeightDateLast, ComputedVecValue,
LazyBinaryDateLast, LazyBinaryTransformLast, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDerivedBlockLast<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyBinaryDateLast<T, S1T, S2T>,
pub difficultyepoch: LazyBinaryTransformLast<DifficultyEpoch, T, S1T, S2T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T, S2T> LazyBinaryDerivedBlockLast<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn from_computed_sum_cum<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockSumCum<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateLast::from_both_sum_cum_cumulatives::<F>(
name,
v,
source1.dateindex.cumulative.boxed_clone(),
&source1.dates,
source2.dateindex.cumulative.boxed_clone(),
&source2.dates,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.difficultyepoch.cumulative.boxed_clone(),
source2.difficultyepoch.cumulative.boxed_clone(),
),
}
}
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateLast::from_both_block_last::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.difficultyepoch.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedHeightDateLast<S1T>,
source2: &ComputedHeightDateLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateLast::from_computed_both_last::<F>(
name,
v,
&source1.rest,
&source2.rest,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.difficultyepoch.0.boxed_clone(),
source2.difficultyepoch.0.boxed_clone(),
),
}
}
pub fn from_computed_height_date_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedHeightDateLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateLast::from_dateindex_and_height_last::<F>(
name,
v,
&source1.rest,
source2,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.difficultyepoch.0.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,51 @@
//! Lazy aggregated binary transform for Sum-only pattern across all time periods.
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, LazyBinaryDateSum, LazyBinaryTransformSum, NumericValue};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDerivedBlockSum<T, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyBinaryDateSum<T, S1T, S2T>,
pub difficultyepoch: LazyBinaryTransformSum<DifficultyEpoch, T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryDerivedBlockSum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: NumericValue + JsonSchema,
S2T: NumericValue + JsonSchema,
{
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSum<S1T>,
source2: &ComputedDerivedBlockSum<S2T>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyBinaryDateSum::from_derived::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformSum::from_boxed::<F>(
name,
v,
source1.difficultyepoch.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,224 @@
//! Lazy aggregated SumCum - binary transform version.
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableCloneableVec};
use crate::internal::{
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast, ComputedDerivedBlockSumCum,
ComputedVecValue, LazyBinaryDateSumCum, LazyBinaryTransformSumCum, LazyFull, LazyPeriodsFull,
LazyPeriodsSumCum, LazySumCum, NumericValue, SumCum,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryDerivedBlockSumCum<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyBinaryDateSumCum<T, S1T, S2T>,
pub difficultyepoch: LazyBinaryTransformSumCum<DifficultyEpoch, T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryDerivedBlockSumCum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
#[allow(clippy::too_many_arguments)]
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
periods1: &LazyPeriodsSumCum<S1T>,
difficultyepoch1: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
periods2: &LazyPeriodsSumCum<S2T>,
difficultyepoch2: &LazySumCum<DifficultyEpoch, S2T, Height, DifficultyEpoch>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_computed::<F>(
name, v, dateindex1, periods1, dateindex2, periods2,
),
difficultyepoch: LazyBinaryTransformSumCum::from_sources::<F>(
name,
v,
difficultyepoch1.sum.boxed_clone(),
difficultyepoch2.sum.boxed_clone(),
difficultyepoch1.cumulative.boxed_clone(),
difficultyepoch2.cumulative.boxed_clone(),
),
}
}
#[allow(clippy::too_many_arguments)]
pub fn from_derived_full<F, S1I, S1L, S2I, S2L>(
name: &str,
version: Version,
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
dates1: &LazyPeriodsFull<S1T>,
difficultyepoch1: &LazyFull<DifficultyEpoch, S1T, S1I, S1L>,
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
dates2: &LazyPeriodsFull<S2T>,
difficultyepoch2: &LazyFull<DifficultyEpoch, S2T, S2I, S2L>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1I: vecdb::VecIndex + 'static,
S1L: ComputedVecValue,
S2I: vecdb::VecIndex + 'static,
S2L: ComputedVecValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_derived_full::<F>(
name, v, dateindex1, dates1, dateindex2, dates2,
),
difficultyepoch: LazyBinaryTransformSumCum::from_lazy_stats_aggregate::<F, _, _, _, _>(
name,
v,
difficultyepoch1,
difficultyepoch2,
),
}
}
/// Without _sum suffix for pure SumCum types.
#[allow(clippy::too_many_arguments)]
pub fn from_computed_sum_raw<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
dateindex1: &SumCum<brk_types::DateIndex, S1T>,
periods1: &LazyPeriodsSumCum<S1T>,
difficultyepoch1: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
dateindex2: &SumCum<brk_types::DateIndex, S2T>,
periods2: &LazyPeriodsSumCum<S2T>,
difficultyepoch2: &LazySumCum<DifficultyEpoch, S2T, Height, DifficultyEpoch>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_computed_sum_raw::<F>(
name, v, dateindex1, periods1, dateindex2, periods2,
),
difficultyepoch: LazyBinaryTransformSumCum::from_sources_sum_raw::<F>(
name,
v,
difficultyepoch1.sum.boxed_clone(),
difficultyepoch2.sum.boxed_clone(),
difficultyepoch1.cumulative.boxed_clone(),
difficultyepoch2.cumulative.boxed_clone(),
),
}
}
// --- Methods accepting SumCum + Last sources ---
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_computed_last::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name,
v,
source1.difficultyepoch.sum.boxed_clone(),
source1.difficultyepoch.cumulative.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_derived_computed_last::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name,
v,
source1.difficultyepoch.sum.boxed_clone(),
source1.difficultyepoch.cumulative.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_computed_derived_last::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name,
v,
source1.difficultyepoch.sum.boxed_clone(),
source1.difficultyepoch.cumulative.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyBinaryDateSumCum::from_derived_last::<F>(name, v, source1, source2),
difficultyepoch: LazyBinaryTransformSumCum::from_sources_last_sum_raw::<F>(
name,
v,
source1.difficultyepoch.sum.boxed_clone(),
source1.difficultyepoch.cumulative.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,89 @@
//! ComputedDerivedBlockDistribution - dateindex storage + lazy time periods + difficultyepoch.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedVecValue, LazyPeriodsDistribution, Distribution, LazyDistribution, NumericValue,
},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockDistribution<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: Distribution<DateIndex, T>,
#[deref]
#[deref_mut]
pub dates: LazyPeriodsDistribution<T>,
pub difficultyepoch: LazyDistribution<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockDistribution<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = Distribution::forced_import(db, name, version + VERSION)?;
let v = version + VERSION;
let dates = LazyPeriodsDistribution::from_sources(
name,
v,
dateindex.average.0.boxed_clone(),
dateindex.minmax.min.0.boxed_clone(),
dateindex.minmax.max.0.boxed_clone(),
indexes,
);
let difficultyepoch = LazyDistribution::from_distribution(
name,
v,
height_source.boxed_clone(),
height_source.boxed_clone(),
height_source,
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
dateindex,
dates,
difficultyepoch,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
self.dateindex.compute(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,82 @@
//! ComputedDerivedBlockFirst - dateindex storage + difficultyepoch + lazy time periods (first value).
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, LazyPeriodsFirst, FirstVec, LazyFirst, NumericValue},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockFirst<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: FirstVec<DateIndex, T>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyPeriodsFirst<T>,
pub difficultyepoch: LazyFirst<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockFirst<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = FirstVec::forced_import(db, name, version + VERSION)?;
let v = version + VERSION;
Ok(Self {
dates: LazyPeriodsFirst::from_source(name, v, dateindex.0.boxed_clone(), indexes),
difficultyepoch: LazyFirst::from_source(
name,
v,
height_source,
indexes.difficultyepoch.identity.boxed_clone(),
),
dateindex,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
self.dateindex.compute_first(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
pub fn compute_all<F>(&mut self, mut compute: F) -> Result<()>
where
F: FnMut(&mut FirstVec<DateIndex, T>) -> Result<()>,
{
compute(&mut self.dateindex)?;
Ok(())
}
}

View File

@@ -0,0 +1,107 @@
//! ComputedDerivedBlockFull - height_cumulative + dateindex storage + difficultyepoch + lazy time periods.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedVecValue, CumulativeVec, LazyPeriodsFull, Full, LazyFull, NumericValue,
compute_cumulative_extend,
},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockFull<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(rename = "cumulative")]
pub height_cumulative: CumulativeVec<Height, T>,
pub dateindex: Full<DateIndex, T>,
#[deref]
#[deref_mut]
pub dates: LazyPeriodsFull<T>,
pub difficultyepoch: LazyFull<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockFull<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height_cumulative = CumulativeVec::forced_import(db, name, v)?;
let dateindex = Full::forced_import(db, name, v)?;
Ok(Self {
dates: LazyPeriodsFull::from_sources(
name,
v,
dateindex.distribution.average.0.boxed_clone(),
dateindex.distribution.minmax.min.0.boxed_clone(),
dateindex.distribution.minmax.max.0.boxed_clone(),
dateindex.sum_cum.sum.0.boxed_clone(),
dateindex.sum_cum.cumulative.0.boxed_clone(),
indexes,
),
difficultyepoch: LazyFull::from_stats_aggregate(
name,
v,
height_source.boxed_clone(),
height_source.boxed_clone(),
height_source.boxed_clone(),
height_source.boxed_clone(),
height_cumulative.0.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
),
height_cumulative,
dateindex,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
// Compute height_cumulative from external source
self.compute_height_cumulative(starting_indexes.height, height_source, exit)?;
// Compute dateindex aggregations
self.dateindex.compute(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
fn compute_height_cumulative(
&mut self,
max_from: Height,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
compute_cumulative_extend(max_from, height_source, &mut self.height_cumulative.0, exit)
}
}

View File

@@ -0,0 +1,74 @@
//! ComputedDerivedBlockLast - dateindex storage + difficultyepoch + lazy time periods.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, LazyPeriodsLast, LastVec, LazyLast, NumericValue},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockLast<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: LastVec<DateIndex, T>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyPeriodsLast<T>,
pub difficultyepoch: LazyLast<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockLast<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = LastVec::forced_import(db, name, version + VERSION)?;
let v = version + VERSION;
Ok(Self {
dates: LazyPeriodsLast::from_source(name, v, dateindex.0.boxed_clone(), indexes),
difficultyepoch: LazyLast::from_source(
name,
v,
height_source,
indexes.difficultyepoch.identity.boxed_clone(),
),
dateindex,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
self.dateindex.compute_last(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,85 @@
//! Lazy aggregated Full for block-level sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{
ComputedDerivedBlockFull, ComputedVecValue, Full, LazyDateFull, LazyPeriodsFull,
LazyTransformStats, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyDerivedBlockFull<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyDateFull<T, S1T>,
pub difficultyepoch: LazyTransformStats<DifficultyEpoch, T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyDerivedBlockFull<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex: &Full<DateIndex, S1T>,
periods: &LazyPeriodsFull<S1T>,
difficultyepoch: &crate::internal::LazyFull<
DifficultyEpoch,
S1T,
brk_types::Height,
DifficultyEpoch,
>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyDateFull::from_full::<F>(name, v, dateindex, periods),
difficultyepoch: LazyTransformStats::from_boxed::<F>(
name,
v,
difficultyepoch.average.boxed_clone(),
difficultyepoch.min.boxed_clone(),
difficultyepoch.max.boxed_clone(),
difficultyepoch.sum.boxed_clone(),
difficultyepoch.cumulative.boxed_clone(),
),
}
}
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedDerivedBlockFull<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyDateFull::from_full::<F>(name, v, &source.dateindex, &source.dates),
difficultyepoch: LazyTransformStats::from_boxed::<F>(
name,
v,
source.difficultyepoch.average.boxed_clone(),
source.difficultyepoch.min.boxed_clone(),
source.difficultyepoch.max.boxed_clone(),
source.difficultyepoch.sum.boxed_clone(),
source.difficultyepoch.cumulative.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,108 @@
//! Lazy aggregated Last for block-level sources.
use brk_traversable::Traversable;
use brk_types::{DifficultyEpoch, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{
ComputedBlockLast, ComputedDerivedBlockLast, ComputedHeightDateLast, ComputedVecValue,
LazyDateLast, LazyTransformLast, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyDerivedBlockLast<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyDateLast<T, S1T>,
pub difficultyepoch: LazyTransformLast<DifficultyEpoch, T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyDerivedBlockLast<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedBlockLast<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyDateLast::from_derived::<F>(
name,
v,
source.dateindex.0.boxed_clone(),
&source.rest,
),
difficultyepoch: LazyTransformLast::from_boxed::<F>(
name,
v,
source.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedDerivedBlockLast<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyDateLast::from_derived::<F>(
name,
v,
source.dateindex.0.boxed_clone(),
&source.dates,
),
difficultyepoch: LazyTransformLast::from_boxed::<F>(
name,
v,
source.difficultyepoch.boxed_clone(),
),
}
}
pub fn from_computed_height_date<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedHeightDateLast<S1T>,
) -> Self
where
S1T: PartialOrd,
{
let v = version + VERSION;
Self {
dates: LazyDateLast::from_derived::<F>(
name,
v,
source.dateindex.boxed_clone(),
&source.rest.rest,
),
difficultyepoch: LazyTransformLast::from_boxed::<F>(
name,
v,
source.difficultyepoch.0.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,77 @@
//! Lazy aggregated Sum for block-level sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{
ComputedDerivedBlockSum, ComputedVecValue, LazyDateSum, LazyPeriodsSum, LazySum,
LazyTransformSum, NumericValue, SumVec,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyDerivedBlockSum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyDateSum<T, S1T>,
pub difficultyepoch: LazyTransformSum<DifficultyEpoch, T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyDerivedBlockSum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex: &SumVec<DateIndex, S1T>,
periods: &LazyPeriodsSum<S1T>,
difficultyepoch: &LazySum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyDateSum::from_derived::<F>(name, v, dateindex.0.boxed_clone(), periods),
difficultyepoch: LazyTransformSum::from_boxed::<F>(
name,
v,
difficultyepoch.boxed_clone(),
),
}
}
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedDerivedBlockSum<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyDateSum::from_derived::<F>(
name,
v,
source.dateindex.0.boxed_clone(),
&source.dates,
),
difficultyepoch: LazyTransformSum::from_boxed::<F>(
name,
v,
source.difficultyepoch.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,74 @@
//! Lazy aggregated SumCum for block-level sources.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{
ComputedDerivedBlockSumCum, ComputedVecValue, LazyDateSumCum, LazyPeriodsSumCum, LazySumCum,
LazyTransformSumCum, NumericValue, SumCum,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyDerivedBlockSumCum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[deref]
#[deref_mut]
pub dates: LazyDateSumCum<T, S1T>,
pub difficultyepoch: LazyTransformSumCum<DifficultyEpoch, T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyDerivedBlockSumCum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
dateindex: &SumCum<DateIndex, S1T>,
periods: &LazyPeriodsSumCum<S1T>,
difficultyepoch: &LazySumCum<DifficultyEpoch, S1T, Height, DifficultyEpoch>,
) -> Self {
let v = version + VERSION;
Self {
dates: LazyDateSumCum::from_sum_cum::<F>(name, v, dateindex, periods),
difficultyepoch: LazyTransformSumCum::from_boxed_sum_raw::<F>(
name,
v,
difficultyepoch.sum.boxed_clone(),
difficultyepoch.cumulative.boxed_clone(),
),
}
}
pub fn from_derived_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedDerivedBlockSumCum<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
dates: LazyDateSumCum::from_sum_cum::<F>(name, v, &source.dateindex, &source.dates),
difficultyepoch: LazyTransformSumCum::from_boxed_sum_raw::<F>(
name,
v,
source.difficultyepoch.sum.boxed_clone(),
source.difficultyepoch.cumulative.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,27 @@
mod binary_last;
mod binary_sum;
mod binary_sum_cum;
mod distribution;
mod first;
mod full;
mod last;
mod lazy_full;
mod lazy_last;
mod lazy_sum;
mod lazy_sum_cum;
mod sum;
mod sum_cum;
pub use binary_last::*;
pub use binary_sum::*;
pub use binary_sum_cum::*;
pub use distribution::*;
pub use first::*;
pub use full::*;
pub use last::*;
pub use lazy_full::*;
pub use lazy_last::*;
pub use lazy_sum::*;
pub use lazy_sum_cum::*;
pub use sum::*;
pub use sum_cum::*;

View File

@@ -0,0 +1,115 @@
//! ComputedDerivedBlockSum - dateindex storage + difficultyepoch + lazy time periods.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, StoredU64, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{
AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, IterableBoxedVec, IterableCloneableVec,
IterableVec, VecIndex,
};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, LazyPeriodsSum, LazySum, NumericValue, SumVec},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockSum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub dateindex: SumVec<DateIndex, T>,
#[deref]
#[deref_mut]
pub dates: LazyPeriodsSum<T>,
pub difficultyepoch: LazySum<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockSum<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let dateindex = SumVec::forced_import_raw(db, name, version + VERSION)?;
let v = version + VERSION;
Ok(Self {
dates: LazyPeriodsSum::from_source(name, v, dateindex.0.boxed_clone(), indexes),
difficultyepoch: LazySum::from_source_raw(
name,
v,
height_source,
indexes.difficultyepoch.identity.boxed_clone(),
),
dateindex,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
self.compute_from(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)
}
fn compute_from(
&mut self,
starting_dateindex: DateIndex,
height_source: &impl IterableVec<Height, T>,
first_indexes: &impl IterableVec<DateIndex, Height>,
count_indexes: &impl IterableVec<DateIndex, StoredU64>,
exit: &Exit,
) -> Result<()> {
let sum_vec = &mut self.dateindex.0;
let combined_version =
height_source.version() + first_indexes.version() + count_indexes.version();
sum_vec.validate_computed_version_or_reset(combined_version)?;
let index = starting_dateindex.to_usize().min(sum_vec.len());
let mut source_iter = height_source.iter();
let mut count_iter = count_indexes.iter().skip(index);
first_indexes.iter().enumerate().skip(index).try_for_each(
|(idx, first_height)| -> Result<()> {
let count = *count_iter.next().unwrap() as usize;
source_iter.set_position(first_height);
let sum: T = (&mut source_iter)
.take(count)
.fold(T::from(0_usize), |acc, v| acc + v);
sum_vec.truncate_push_at(idx, sum)?;
Ok(())
},
)?;
let _lock = exit.lock();
sum_vec.write()?;
Ok(())
}
}

View File

@@ -0,0 +1,158 @@
//! ComputedDerivedBlockSumCum - aggregates derived from an external height source.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, StoredU64, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{
AnyStoredVec, AnyVec, Database, Exit, GenericStoredVec, IterableBoxedVec, IterableCloneableVec,
IterableVec, VecIndex,
};
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedVecValue, CumulativeVec, LazyPeriodsSumCum, LazySumCum, NumericValue, SumCum,
compute_cumulative_extend,
},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedDerivedBlockSumCum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(rename = "cumulative")]
pub height_cumulative: CumulativeVec<Height, T>,
pub dateindex: SumCum<DateIndex, T>,
#[deref]
#[deref_mut]
pub dates: LazyPeriodsSumCum<T>,
pub difficultyepoch: LazySumCum<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedDerivedBlockSumCum<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
height_source: IterableBoxedVec<Height, T>,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height_cumulative = CumulativeVec::forced_import(db, name, v)?;
let dateindex = SumCum::forced_import_sum_raw(db, name, v)?;
let dates = LazyPeriodsSumCum::from_sources(
name,
v,
dateindex.sum.0.boxed_clone(),
dateindex.cumulative.0.boxed_clone(),
indexes,
);
let difficultyepoch = LazySumCum::from_sources_sum_raw(
name,
v,
height_source.boxed_clone(),
height_cumulative.0.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
height_cumulative,
dateindex,
dates,
difficultyepoch,
})
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
height_source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
self.compute_height_cumulative(starting_indexes.height, height_source, exit)?;
self.compute_dateindex_sum_cum(
starting_indexes.dateindex,
height_source,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)
}
fn compute_height_cumulative(
&mut self,
max_from: Height,
source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
compute_cumulative_extend(max_from, source, &mut self.height_cumulative.0, exit)
}
fn compute_dateindex_sum_cum(
&mut self,
starting_dateindex: DateIndex,
height_source: &impl IterableVec<Height, T>,
first_indexes: &impl IterableVec<DateIndex, Height>,
count_indexes: &impl IterableVec<DateIndex, StoredU64>,
exit: &Exit,
) -> Result<()> {
let sum_vec = &mut self.dateindex.sum.0;
let cumulative_vec = &mut self.dateindex.cumulative.0;
let combined_version =
height_source.version() + first_indexes.version() + count_indexes.version();
sum_vec.validate_computed_version_or_reset(combined_version)?;
cumulative_vec.validate_computed_version_or_reset(combined_version)?;
let index = starting_dateindex
.to_usize()
.min(sum_vec.len())
.min(cumulative_vec.len());
let mut cumulative = if index > 0 {
cumulative_vec.iter().get_unwrap((index - 1).into())
} else {
T::from(0_usize)
};
let mut source_iter = height_source.iter();
let mut count_iter = count_indexes.iter().skip(index);
first_indexes.iter().enumerate().skip(index).try_for_each(
|(idx, first_height)| -> Result<()> {
let count = *count_iter.next().unwrap() as usize;
source_iter.set_position(first_height);
let sum: T = (&mut source_iter)
.take(count)
.fold(T::from(0_usize), |acc, v| acc + v);
cumulative += sum;
sum_vec.truncate_push_at(idx, sum)?;
cumulative_vec.truncate_push_at(idx, cumulative)?;
Ok(())
},
)?;
let _lock = exit.lock();
sum_vec.write()?;
cumulative_vec.write()?;
Ok(())
}
}

View File

@@ -0,0 +1,108 @@
//! ComputedTxDistribution - computes TxIndex data to height Distribution + dateindex MinMaxAverage + lazy aggregations.
//!
//! Note: Percentiles are computed at height level only. DateIndex and coarser
//! periods only have average+min+max since computing percentiles across all
//! transactions per day would be expensive.
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, TxIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedVecValue, LazyPeriodsDistribution, Distribution, LazyDistribution, MinMaxAverage,
NumericValue,
},
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct DerivedTxDistribution<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: Distribution<Height, T>,
pub difficultyepoch: LazyDistribution<DifficultyEpoch, T, Height, DifficultyEpoch>,
pub dateindex: MinMaxAverage<DateIndex, T>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyPeriodsDistribution<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> DerivedTxDistribution<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let height = Distribution::forced_import(db, name, version + VERSION)?;
let dateindex = MinMaxAverage::forced_import(db, name, version + VERSION)?;
let v = version + VERSION;
let difficultyepoch =
LazyDistribution::<DifficultyEpoch, T, Height, DifficultyEpoch>::from_distribution(
name,
v,
height.average.0.boxed_clone(),
height.minmax.min.0.boxed_clone(),
height.minmax.max.0.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
let dates = LazyPeriodsDistribution::from_sources(
name,
v,
dateindex.average.0.boxed_clone(),
dateindex.minmax.min.0.boxed_clone(),
dateindex.minmax.max.0.boxed_clone(),
indexes,
);
Ok(Self {
height,
difficultyepoch,
dateindex,
dates,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
txindex_source: &impl CollectableVec<TxIndex, T>,
exit: &Exit,
) -> Result<()> {
self.height.compute(
starting_indexes.height,
txindex_source,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
exit,
)?;
self.dateindex.compute(
starting_indexes.dateindex,
&self.height.average.0,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,106 @@
//! DerivedTxFull - aggregates from TxIndex to height Full + dateindex Stats + lazy date periods.
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, TxIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
use crate::{
indexes, ComputeIndexes,
internal::{ComputedVecValue, LazyPeriodsFull, Full, LazyFull, NumericValue, Stats},
};
/// Aggregates from TxIndex to height/dateindex with full stats.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct DerivedTxFull<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: Full<Height, T>,
pub difficultyepoch: LazyFull<DifficultyEpoch, T, Height, DifficultyEpoch>,
pub dateindex: Stats<DateIndex, T>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyPeriodsFull<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> DerivedTxFull<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let height = Full::forced_import(db, name, version + VERSION)?;
let dateindex = Stats::forced_import(db, name, version + VERSION)?;
let v = version + VERSION;
let difficultyepoch =
LazyFull::<DifficultyEpoch, T, Height, DifficultyEpoch>::from_stats_aggregate(
name,
v,
height.distribution.average.0.boxed_clone(),
height.distribution.minmax.min.0.boxed_clone(),
height.distribution.minmax.max.0.boxed_clone(),
height.sum_cum.sum.0.boxed_clone(),
height.sum_cum.cumulative.0.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
let dates = LazyPeriodsFull::from_sources(
name,
v,
dateindex.average.0.boxed_clone(),
dateindex.minmax.min.0.boxed_clone(),
dateindex.minmax.max.0.boxed_clone(),
dateindex.sum_cum.sum.0.boxed_clone(),
dateindex.sum_cum.cumulative.0.boxed_clone(),
indexes,
);
Ok(Self {
height,
difficultyepoch,
dateindex,
dates,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
txindex_source: &impl CollectableVec<TxIndex, T>,
exit: &Exit,
) -> Result<()> {
self.height.compute(
starting_indexes.height,
txindex_source,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
exit,
)?;
self.dateindex.compute(
starting_indexes.dateindex,
&self.height.distribution.average.0,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
}

View File

@@ -0,0 +1,67 @@
//! LazyTxDistribution - lazy txindex source + computed distribution.
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{TxIndex, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{CollectableVec, Database, Exit, LazyVecFrom2};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, DerivedTxDistribution, NumericValue},
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyTxDistribution<T, S1, S2>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1: ComputedVecValue,
S2: ComputedVecValue,
{
pub txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub distribution: DerivedTxDistribution<T>,
}
impl<T, S1, S2> LazyTxDistribution<T, S1, S2>
where
T: NumericValue + JsonSchema,
S1: ComputedVecValue + JsonSchema,
S2: ComputedVecValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
txindex: LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let distribution = DerivedTxDistribution::forced_import(db, name, v, indexes)?;
Ok(Self {
txindex,
distribution,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()>
where
LazyVecFrom2<TxIndex, T, TxIndex, S1, TxIndex, S2>: CollectableVec<TxIndex, T>,
{
self.distribution
.derive_from(indexer, indexes, starting_indexes, &self.txindex, exit)
}
}

View File

@@ -0,0 +1,75 @@
//! Lazy transform of DerivedTxFull.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
Version, WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{ComputedVecValue, DerivedTxFull, LazyTransformFull, LazyTransformStats};
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct LazyDerivedTxFull<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub height: LazyTransformFull<Height, T, S1T>,
pub difficultyepoch: LazyTransformStats<DifficultyEpoch, T, S1T>,
pub dateindex: LazyTransformStats<DateIndex, T, S1T>,
pub weekindex: LazyTransformStats<WeekIndex, T, S1T>,
pub monthindex: LazyTransformStats<MonthIndex, T, S1T>,
pub quarterindex: LazyTransformStats<QuarterIndex, T, S1T>,
pub semesterindex: LazyTransformStats<SemesterIndex, T, S1T>,
pub yearindex: LazyTransformStats<YearIndex, T, S1T>,
pub decadeindex: LazyTransformStats<DecadeIndex, T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyDerivedTxFull<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &DerivedTxFull<S1T>,
) -> Self {
let v = version + VERSION;
macro_rules! period {
($p:ident) => {
LazyTransformStats::from_boxed::<F>(
name, v,
source.$p.average.boxed_clone(), source.$p.min.boxed_clone(),
source.$p.max.boxed_clone(), source.$p.sum.boxed_clone(),
source.$p.cumulative.boxed_clone(),
)
};
}
Self {
height: LazyTransformFull::from_stats_aggregate::<F>(name, v, &source.height),
difficultyepoch: period!(difficultyepoch),
dateindex: LazyTransformStats::from_boxed::<F>(
name, v,
source.dateindex.average.0.boxed_clone(),
source.dateindex.minmax.min.0.boxed_clone(),
source.dateindex.minmax.max.0.boxed_clone(),
source.dateindex.sum_cum.sum.0.boxed_clone(),
source.dateindex.sum_cum.cumulative.0.boxed_clone(),
),
weekindex: period!(weekindex),
monthindex: period!(monthindex),
quarterindex: period!(quarterindex),
semesterindex: period!(semesterindex),
yearindex: period!(yearindex),
decadeindex: period!(decadeindex),
}
}
}

View File

@@ -0,0 +1,9 @@
mod distribution;
mod full;
mod lazy_distribution;
mod lazy_full;
pub use distribution::*;
pub use full::*;
pub use lazy_distribution::*;
pub use lazy_full::*;

View File

@@ -0,0 +1,60 @@
//! Lazy binary transform from Full sources.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, LazyVecFrom2};
use crate::internal::{
ComputedBlockFull, ComputedVecValue, DerivedTxFull, LazyBinaryDerivedBlockSumCum, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryBlockFull<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[traversable(wrap = "base")]
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[deref]
#[deref_mut]
pub rest: LazyBinaryDerivedBlockSumCum<T, S1T, S2T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T, S2T> LazyBinaryBlockFull<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: NumericValue + JsonSchema,
S2T: NumericValue + JsonSchema,
{
pub fn from_height_and_txindex<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedBlockFull<S1T>,
source2: &DerivedTxFull<S2T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
rest: LazyBinaryDerivedBlockSumCum::from_derived_full::<F, _, _, _, _>(
name,
v,
&source1.dateindex.sum_cum,
&source1.rest,
&source1.difficultyepoch,
&source2.dateindex.sum_cum,
&source2.dates,
&source2.difficultyepoch,
),
}
}
}

View File

@@ -0,0 +1,76 @@
//! LazyBinaryHeightDateLast - height storage + binary transform lazy date periods.
//!
//! Use this when height is stored as EagerVec and date periods are lazy binary transforms.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, EagerVec, PcoVec};
use crate::internal::{
ComputedDateLast, ComputedHeightDateLast, ComputedVecValue, LazyBinaryDateLast,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryHeightDateLast<T, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyBinaryDateLast<T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryHeightDateLast<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn from_computed_both_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height: EagerVec<PcoVec<Height, T>>,
source1: &ComputedDateLast<S1T>,
source2: &ComputedDateLast<S2T>,
) -> Self {
let v = version + VERSION;
Self {
height,
rest: LazyBinaryDateLast::from_computed_both_last::<F>(name, v, source1, source2),
}
}
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height: EagerVec<PcoVec<Height, T>>,
source1: &ComputedHeightDateLast<S1T>,
source2: &ComputedHeightDateLast<S2T>,
) -> Self
where
S1T: JsonSchema + 'static,
S2T: JsonSchema + 'static,
{
let v = version + VERSION;
Self {
height,
rest: LazyBinaryDateLast::from_computed_both_last::<F>(
name,
v,
&source1.rest,
&source2.rest,
),
}
}
}

View File

@@ -0,0 +1,290 @@
//! Lazy binary transform from two SumCum sources, producing Last (cumulative) ratios only.
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
use crate::internal::{
ComputedBlockLast, ComputedBlockSumCum, ComputedHeightDateLast, ComputedVecValue,
LazyBinaryDateLast, LazyBinaryDerivedBlockLast, LazyBinaryTransformLast, LazyPeriodsLast,
NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryBlockLast<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[deref]
#[deref_mut]
pub rest: LazyBinaryDerivedBlockLast<T, S1T, S2T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T, S2T> LazyBinaryBlockLast<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn from_computed_sum_cum<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockSumCum<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height_cumulative.0.boxed_clone(),
source2.height_cumulative.0.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast::from_computed_sum_cum::<F>(name, v, source1, source2),
}
}
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast::from_computed_last::<F>(name, v, source1, source2),
}
}
pub fn from_computed_height_date_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedHeightDateLast<S1T>,
source2: &ComputedHeightDateLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast::from_computed_height_date_last::<F>(
name, v, source1, source2,
),
}
}
/// Create from a ComputedHeightDateLast and a LazyBinaryBlockLast.
pub fn from_computed_height_date_and_binary_block<F, S2aT, S2bT>(
name: &str,
version: Version,
source1: &ComputedHeightDateLast<S1T>,
source2: &LazyBinaryBlockLast<S2T, S2aT, S2bT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1T: PartialOrd,
S2aT: ComputedVecValue + JsonSchema,
S2bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast {
dates: LazyBinaryDateLast::from_computed_and_binary_last::<F, _, _>(
name,
v,
&source1.rest,
&source2.rest.dates,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.difficultyepoch.0.boxed_clone(),
source2.rest.difficultyepoch.boxed_clone(),
),
},
}
}
/// Create from a ComputedHeightDateLast and a ComputedBlockLast.
pub fn from_computed_height_date_and_block_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedHeightDateLast<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast::from_computed_height_date_and_block_last::<F>(
name, v, source1, source2,
),
}
}
/// Create from a LazyBinaryBlockLast and a ComputedBlockLast.
pub fn from_binary_block_and_computed_block_last<F, S1aT, S1bT>(
name: &str,
version: Version,
source1: &LazyBinaryBlockLast<S1T, S1aT, S1bT>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast {
dates: LazyBinaryDateLast::from_binary_and_block_last::<F, _, _>(
name,
v,
&source1.rest.dates,
source2,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.rest.difficultyepoch.boxed_clone(),
source2.difficultyepoch.boxed_clone(),
),
},
}
}
/// Create from two LazyBinaryBlockLast sources.
pub fn from_both_binary_block<F, S1aT, S1bT, S2aT, S2bT>(
name: &str,
version: Version,
source1: &LazyBinaryBlockLast<S1T, S1aT, S1bT>,
source2: &LazyBinaryBlockLast<S2T, S2aT, S2bT>,
) -> Self
where
F: BinaryTransform<S1T, S2T, T>,
S1aT: ComputedVecValue + JsonSchema,
S1bT: ComputedVecValue + JsonSchema,
S2aT: ComputedVecValue + JsonSchema,
S2bT: ComputedVecValue + JsonSchema,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockLast {
dates: LazyBinaryDateLast::from_both_binary_last::<F, _, _, _, _>(
name,
v,
&source1.rest.dates,
&source2.rest.dates,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
source1.rest.difficultyepoch.boxed_clone(),
source2.rest.difficultyepoch.boxed_clone(),
),
},
}
}
/// Create from separate height, difficultyepoch, and date sources.
///
/// Use when sources are split across different types (e.g., ValueHeightDateLast + ComputedBlockLast).
#[allow(clippy::too_many_arguments)]
pub fn from_height_difficultyepoch_dates<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
difficultyepoch_source1: IterableBoxedVec<DifficultyEpoch, S1T>,
difficultyepoch_source2: IterableBoxedVec<DifficultyEpoch, S2T>,
dateindex_source1: IterableBoxedVec<DateIndex, S1T>,
dates_source1: &LazyPeriodsLast<S1T>,
dateindex_source2: IterableBoxedVec<DateIndex, S2T>,
dates_source2: &LazyPeriodsLast<S2T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
rest: LazyBinaryDerivedBlockLast {
dates: LazyBinaryDateLast::from_both_derived_last::<F>(
name,
v,
dateindex_source1,
dates_source1,
dateindex_source2,
dates_source2,
),
difficultyepoch: LazyBinaryTransformLast::from_vecs::<F>(
name,
v,
difficultyepoch_source1,
difficultyepoch_source2,
),
},
}
}
}

View File

@@ -0,0 +1,71 @@
//! Lazy binary transform from two Sum-only sources with height level.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
use crate::internal::{
ComputedBlockSum, ComputedDerivedBlockSum, ComputedVecValue, LazyBinaryDerivedBlockSum,
NumericValue,
};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryBlockSum<T, S1T, S2T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[traversable(rename = "sum")]
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[deref]
#[deref_mut]
pub rest: LazyBinaryDerivedBlockSum<T, S1T, S2T>,
}
impl<T, S1T, S2T> LazyBinaryBlockSum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: NumericValue + JsonSchema,
S2T: NumericValue + JsonSchema,
{
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedDerivedBlockSum<S1T>,
source2: &ComputedDerivedBlockSum<S2T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
rest: LazyBinaryDerivedBlockSum::from_derived::<F>(name, v, source1, source2),
}
}
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
source1: &ComputedBlockSum<S1T>,
source2: &ComputedBlockSum<S2T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(
name,
v,
source1.height.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockSum::from_derived::<F>(name, v, &source1.rest, &source2.rest),
}
}
}

View File

@@ -0,0 +1,210 @@
//! Lazy binary transform from two SumCum sources.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2};
use crate::internal::{
ComputedBlockLast, ComputedBlockSumCum, ComputedDerivedBlockLast, ComputedDerivedBlockSumCum,
ComputedVecValue, LazyBinaryDerivedBlockSumCum, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBinaryBlockSumCum<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[traversable(rename = "sum")]
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[traversable(rename = "cumulative")]
pub height_cumulative: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[deref]
#[deref_mut]
pub rest: LazyBinaryDerivedBlockSumCum<T, S1T, S2T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T, S2T> LazyBinaryBlockSumCum<T, S1T, S2T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockSumCum<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
source2.height_cumulative.0.boxed_clone(),
),
rest: LazyBinaryDerivedBlockSumCum::from_computed_sum_raw::<F>(
name,
v,
&source1.dateindex,
&source1.rest,
&source1.difficultyepoch,
&source2.dateindex,
&source2.rest,
&source2.difficultyepoch,
),
}
}
pub fn from_derived<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockSumCum<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: PartialOrd,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
source2.height_cumulative.0.boxed_clone(),
),
rest: LazyBinaryDerivedBlockSumCum::from_computed_sum_raw::<F>(
name,
v,
&source1.dateindex,
source1,
&source1.difficultyepoch,
&source2.dateindex,
source2,
&source2.difficultyepoch,
),
}
}
// --- Methods accepting SumCum + Last sources ---
pub fn from_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockSumCum::from_computed_last::<F>(name, v, source1, source2),
}
}
pub fn from_derived_computed_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1, height_source2),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
source2.height.boxed_clone(),
),
rest: LazyBinaryDerivedBlockSumCum::from_derived_computed_last::<F>(name, v, source1, source2),
}
}
pub fn from_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedDerivedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: NumericValue,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1.clone(), height_source2.clone()),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
height_source2,
),
rest: LazyBinaryDerivedBlockSumCum::from_derived_last::<F>(name, v, source1, source2),
}
}
pub fn from_computed_derived_last<F: BinaryTransform<S1T, S2T, T>>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, S1T>,
height_source2: IterableBoxedVec<Height, S2T>,
source1: &ComputedBlockSumCum<S1T>,
source2: &ComputedDerivedBlockLast<S2T>,
) -> Self
where
S1T: PartialOrd,
S2T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom2::transformed::<F>(name, v, height_source1.clone(), height_source2.clone()),
height_cumulative: LazyVecFrom2::transformed::<F>(
&format!("{name}_cumulative"),
v,
source1.height_cumulative.0.boxed_clone(),
height_source2,
),
rest: LazyBinaryDerivedBlockSumCum::from_computed_derived_last::<F>(name, v, source1, source2),
}
}
}

View File

@@ -0,0 +1,68 @@
//! ComputedBlock with full stats aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockFull, NumericValue};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedBlockFull<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(wrap = "base")]
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
pub rest: ComputedDerivedBlockFull<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedBlockFull<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDerivedBlockFull::forced_import(
db,
name,
height.boxed_clone(),
v,
indexes,
)?;
Ok(Self { height, rest })
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
{
compute(&mut self.height)?;
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,37 @@
//! ComputedHeightDateBytes - height + dateindex BytesVec storage.
//!
//! Use this for simple cases where both height and dateindex are stored BytesVecs
//! without any lazy derivations. For OHLC-type data.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Height, Version};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{BytesVec, BytesVecValue, Database, Formattable, ImportableVec};
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct ComputedHeightDateBytes<T>
where
T: BytesVecValue + Formattable + Serialize + JsonSchema,
{
pub height: BytesVec<Height, T>,
pub dateindex: BytesVec<DateIndex, T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedHeightDateBytes<T>
where
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
{
pub fn forced_import(db: &Database, name: &str, version: Version) -> Result<Self> {
let v = version + VERSION;
Ok(Self {
height: BytesVec::forced_import(db, name, v)?,
dateindex: BytesVec::forced_import(db, name, v)?,
})
}
}

View File

@@ -0,0 +1,72 @@
//! ComputedHeightDateFirst - height storage + dateindex storage + lazy periods.
//!
//! Use this when both height and dateindex are stored EagerVecs with first-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedDateFirst, ComputedVecValue, LazyFirst};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedHeightDateFirst<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDateFirst<T>,
pub difficultyepoch: LazyFirst<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedHeightDateFirst<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDateFirst::forced_import(db, name, v, indexes)?;
let difficultyepoch = LazyFirst::from_source(
name,
v,
height.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
height,
rest,
difficultyepoch,
})
}
/// Compute rest (dateindex + periods) with the given compute function.
pub fn compute_rest<F>(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
self.rest.compute_all(starting_indexes, exit, compute)
}
}

View File

@@ -0,0 +1,72 @@
//! ComputedHeightDateLast - height storage + dateindex storage + lazy periods.
//!
//! Use this when both height and dateindex are stored EagerVecs with last-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{indexes, internal::ComputedDateLast, ComputeIndexes};
use crate::internal::{ComputedVecValue, LazyLast};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedHeightDateLast<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDateLast<T>,
pub difficultyepoch: LazyLast<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedHeightDateLast<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDateLast::forced_import(db, name, v, indexes)?;
let difficultyepoch = LazyLast::from_source(
name,
v,
height.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
height,
rest,
difficultyepoch,
})
}
/// Compute rest (dateindex + periods) with the given compute function.
pub fn compute_rest<F>(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
self.rest.compute_all(starting_indexes, exit, compute)
}
}

View File

@@ -0,0 +1,72 @@
//! ComputedHeightDateMax - height storage + dateindex storage + lazy periods.
//!
//! Use this when both height and dateindex are stored EagerVecs with max-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedDateMax, ComputedVecValue, LazyMax};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedHeightDateMax<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDateMax<T>,
pub difficultyepoch: LazyMax<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedHeightDateMax<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDateMax::forced_import(db, name, v, indexes)?;
let difficultyepoch = LazyMax::from_source(
name,
v,
height.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
height,
rest,
difficultyepoch,
})
}
/// Compute rest (dateindex + periods) with the given compute function.
pub fn compute_rest<F>(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
self.rest.compute_all(starting_indexes, exit, compute)
}
}

View File

@@ -0,0 +1,72 @@
//! ComputedHeightDateMin - height storage + dateindex storage + lazy periods.
//!
//! Use this when both height and dateindex are stored EagerVecs with min-value aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, DifficultyEpoch, Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedDateMin, ComputedVecValue, LazyMin};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedHeightDateMin<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDateMin<T>,
pub difficultyepoch: LazyMin<DifficultyEpoch, T, Height, DifficultyEpoch>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedHeightDateMin<T>
where
T: ComputedVecValue + JsonSchema + 'static,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDateMin::forced_import(db, name, v, indexes)?;
let difficultyepoch = LazyMin::from_source(
name,
v,
height.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
Ok(Self {
height,
rest,
difficultyepoch,
})
}
/// Compute rest (dateindex + periods) with the given compute function.
pub fn compute_rest<F>(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, T>>) -> Result<()>,
{
self.rest.compute_all(starting_indexes, exit, compute)
}
}

View File

@@ -0,0 +1,74 @@
//! ComputedBlock using only LastVec aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockLast, NumericValue};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedBlockLast<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDerivedBlockLast<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedBlockLast<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest =
ComputedDerivedBlockLast::forced_import(db, name, height.boxed_clone(), v, indexes)?;
Ok(Self { height, rest })
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
{
compute(&mut self.height)?;
self.compute_rest(indexes, starting_indexes, exit)
}
/// Compute rest from self.height (for stateful computation patterns).
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,95 @@
//! LazyBlockDistribution - lazy height + derived distribution (avg/min/max) for indexes.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{ComputeFrom1, Database, Exit, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, ComputedDerivedBlockDistribution, NumericValue},
};
const VERSION: Version = Version::ZERO;
/// Lazy height + derived distribution for indexes.
///
/// Height is a lazy transform from a source.
/// Indexes (dateindex + periods + difficultyepoch) store distribution stats (avg/min/max).
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockDistribution<T, S = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S: ComputedVecValue,
{
#[traversable(rename = "base")]
pub height: LazyVecFrom1<Height, T, Height, S>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDerivedBlockDistribution<T>,
}
impl<T, S> LazyBlockDistribution<T, S>
where
T: NumericValue + JsonSchema,
S: ComputedVecValue + JsonSchema,
{
pub fn forced_import<F: UnaryTransform<S, T>>(
db: &Database,
name: &str,
version: Version,
source: impl IterableCloneableVec<Height, S>,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height = LazyVecFrom1::transformed::<F>(name, v, source.boxed_clone());
let rest = ComputedDerivedBlockDistribution::forced_import(
db,
name,
height.boxed_clone(),
v,
indexes,
)?;
Ok(Self { height, rest })
}
pub fn forced_import_with_init(
db: &Database,
name: &str,
version: Version,
source: impl IterableCloneableVec<Height, S>,
indexes: &indexes::Vecs,
init_fn: ComputeFrom1<Height, T, Height, S>,
) -> Result<Self> {
let v = version + VERSION;
let height = LazyVecFrom1::init(name, v, source.boxed_clone(), init_fn);
let rest = ComputedDerivedBlockDistribution::forced_import(
db,
name,
height.boxed_clone(),
v,
indexes,
)?;
Ok(Self { height, rest })
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,68 @@
//! Lazy unary transform from height with Full aggregation.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{
ComputedBlockFull, ComputedDerivedBlockFull, ComputedVecValue, LazyDerivedBlockFull,
NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockFull<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[traversable(wrap = "base")]
pub height: LazyVecFrom1<Height, T, Height, S1T>,
#[deref]
#[deref_mut]
pub rest: LazyDerivedBlockFull<T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyBlockFull<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedBlockFull<S1T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockFull::from_computed::<F>(
name,
v,
&source.dateindex,
&source.rest,
&source.difficultyepoch,
),
}
}
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedDerivedBlockFull<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockFull::from_derived_computed::<F>(name, v, source),
}
}
}

View File

@@ -0,0 +1,81 @@
//! LazyBlockFullHeight - block full with lazy height transform.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedVecValue, ComputedDerivedBlockFull, NumericValue},
};
const VERSION: Version = Version::ZERO;
/// Block full aggregation with lazy height transform + computed derived indexes.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockFullHeight<T, S = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S: ComputedVecValue,
{
#[traversable(rename = "base")]
pub height: LazyVecFrom1<Height, T, Height, S>,
#[deref]
#[deref_mut]
pub rest: ComputedDerivedBlockFull<T>,
}
impl<T, S> LazyBlockFullHeight<T, S>
where
T: NumericValue + JsonSchema,
S: ComputedVecValue + JsonSchema,
{
pub fn forced_import<F: UnaryTransform<S, T>>(
db: &Database,
name: &str,
version: Version,
source: impl IterableCloneableVec<Height, S>,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height = LazyVecFrom1::transformed::<F>(name, v, source.boxed_clone());
let rest =
ComputedDerivedBlockFull::forced_import(db, name, height.boxed_clone(), v, indexes)?;
Ok(Self { height, rest })
}
pub fn forced_import_with_init(
db: &Database,
name: &str,
version: Version,
source: impl IterableCloneableVec<Height, S>,
indexes: &indexes::Vecs,
init_fn: vecdb::ComputeFrom1<Height, T, Height, S>,
) -> Result<Self> {
let v = version + VERSION;
let height = LazyVecFrom1::init(name, v, source.boxed_clone(), init_fn);
let rest =
ComputedDerivedBlockFull::forced_import(db, name, height.boxed_clone(), v, indexes)?;
Ok(Self { height, rest })
}
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,77 @@
//! LazyBlockSumCumHeight - block sum+cumulative with lazy height transform.
//!
//! Use this when you need:
//! - Lazy height (binary transform from two sources)
//! - Stored cumulative and dateindex aggregates
//! - Lazy coarser period lookups
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom2};
use crate::{indexes, ComputeIndexes};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSumCum, NumericValue};
/// Block sum+cumulative with lazy binary height transform + computed derived indexes.
///
/// Height is a lazy binary transform (e.g., mask × source, or price × sats).
/// Cumulative and dateindex are stored (computed from lazy height).
/// Coarser periods are lazy lookups.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockSumCumHeight<T, S1T = T, S2T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
S2T: ComputedVecValue,
{
#[traversable(rename = "sum")]
pub height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
#[deref]
#[deref_mut]
pub rest: ComputedDerivedBlockSumCum<T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T, S2T> LazyBlockSumCumHeight<T, S1T, S2T>
where
T: NumericValue + JsonSchema,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
height: LazyVecFrom2<Height, T, Height, S1T, Height, S2T>,
) -> Result<Self> {
let v = version + VERSION;
let rest = ComputedDerivedBlockSumCum::forced_import(
db,
name,
height.boxed_clone(),
v,
indexes,
)?;
Ok(Self { height, rest })
}
/// Derive aggregates from the lazy height source.
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,79 @@
//! Lazy unary transform from height with Last aggregation.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{
ComputedBlockLast, ComputedDerivedBlockLast, ComputedHeightDateLast, ComputedVecValue,
LazyDerivedBlockLast, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockLast<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub height: LazyVecFrom1<Height, T, Height, S1T>,
#[deref]
#[deref_mut]
pub rest: LazyDerivedBlockLast<T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyBlockLast<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedBlockLast<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockLast::from_computed::<F>(name, v, source),
}
}
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedDerivedBlockLast<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockLast::from_derived_computed::<F>(name, v, source),
}
}
pub fn from_computed_height_date<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
source: &ComputedHeightDateLast<S1T>,
) -> Self
where
S1T: PartialOrd,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, source.height.boxed_clone()),
rest: LazyDerivedBlockLast::from_computed_height_date::<F>(name, v, source),
}
}
}

View File

@@ -0,0 +1,67 @@
//! Lazy unary transform from height with Sum aggregation.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{
ComputedBlockSum, ComputedDerivedBlockSum, ComputedVecValue, LazyDerivedBlockSum, NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockSum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
pub height: LazyVecFrom1<Height, T, Height, S1T>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: LazyDerivedBlockSum<T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyBlockSum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedBlockSum<S1T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockSum::from_computed::<F>(
name,
v,
&source.dateindex,
&source.rest,
&source.difficultyepoch,
),
}
}
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedDerivedBlockSum<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockSum::from_derived_computed::<F>(name, v, source),
}
}
}

View File

@@ -0,0 +1,68 @@
//! Lazy unary transform from height with SumCum aggregation.
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{IterableBoxedVec, LazyVecFrom1, UnaryTransform};
use crate::internal::{
ComputedBlockSumCum, ComputedDerivedBlockSumCum, ComputedVecValue, LazyDerivedBlockSumCum,
NumericValue,
};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockSumCum<T, S1T = T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
S1T: ComputedVecValue,
{
#[traversable(rename = "sum")]
pub height: LazyVecFrom1<Height, T, Height, S1T>,
#[deref]
#[deref_mut]
pub rest: LazyDerivedBlockSumCum<T, S1T>,
}
const VERSION: Version = Version::ZERO;
impl<T, S1T> LazyBlockSumCum<T, S1T>
where
T: ComputedVecValue + JsonSchema + 'static,
S1T: ComputedVecValue + JsonSchema,
{
pub fn from_computed<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedBlockSumCum<S1T>,
) -> Self {
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockSumCum::from_computed::<F>(
name,
v,
&source.dateindex,
&source.rest,
&source.difficultyepoch,
),
}
}
pub fn from_derived<F: UnaryTransform<S1T, T>>(
name: &str,
version: Version,
height_source: IterableBoxedVec<Height, S1T>,
source: &ComputedDerivedBlockSumCum<S1T>,
) -> Self
where
S1T: NumericValue,
{
let v = version + VERSION;
Self {
height: LazyVecFrom1::transformed::<F>(name, v, height_source),
rest: LazyDerivedBlockSumCum::from_derived_computed::<F>(name, v, source),
}
}
}

View File

@@ -0,0 +1,43 @@
mod binary_full;
mod binary_height_date_last;
mod binary_last;
mod binary_sum;
mod binary_sum_cum;
mod full;
mod height_date_bytes;
mod height_date_first;
mod height_date_last;
mod height_date_max;
mod height_date_min;
mod last;
mod lazy_distribution;
mod lazy_full;
mod lazy_height_full;
mod lazy_height_sum_cum;
mod lazy_last;
mod lazy_sum;
mod lazy_sum_cum;
mod sum;
mod sum_cum;
pub use binary_full::*;
pub use binary_height_date_last::*;
pub use binary_last::*;
pub use binary_sum::*;
pub use binary_sum_cum::*;
pub use full::*;
pub use height_date_bytes::*;
pub use height_date_first::*;
pub use height_date_last::*;
pub use height_date_max::*;
pub use height_date_min::*;
pub use last::*;
pub use lazy_distribution::*;
pub use lazy_full::*;
pub use lazy_height_full::*;
pub use lazy_height_sum_cum::*;
pub use lazy_last::*;
pub use lazy_sum::*;
pub use lazy_sum_cum::*;
pub use sum::*;
pub use sum_cum::*;

View File

@@ -0,0 +1,74 @@
//! ComputedBlock using Sum-only aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSum, NumericValue};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedBlockSum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub rest: ComputedDerivedBlockSum<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedBlockSum<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest =
ComputedDerivedBlockSum::forced_import(db, name, height.boxed_clone(), v, indexes)?;
Ok(Self { height, rest })
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
{
compute(&mut self.height)?;
self.compute_rest(indexes, starting_indexes, exit)
}
/// Compute rest from self.height (for stateful computation patterns).
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,106 @@
//! ComputedBlock using SumCum aggregation.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Version};
use derive_more::{Deref, DerefMut};
use schemars::JsonSchema;
use vecdb::{
AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, ImportableVec,
IterableCloneableVec, IterableVec, PcoVec, VecIndex,
};
use crate::{indexes, ComputeIndexes};
use crate::internal::{ComputedVecValue, ComputedDerivedBlockSumCum, NumericValue};
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ComputedBlockSumCum<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema,
{
#[traversable(rename = "sum")]
pub height: EagerVec<PcoVec<Height, T>>,
#[deref]
#[deref_mut]
pub rest: ComputedDerivedBlockSumCum<T>,
}
const VERSION: Version = Version::ZERO;
impl<T> ComputedBlockSumCum<T>
where
T: NumericValue + JsonSchema,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, T>> = EagerVec::forced_import(db, name, v)?;
let rest = ComputedDerivedBlockSumCum::forced_import(
db,
name,
height.boxed_clone(),
v,
indexes,
)?;
Ok(Self { height, rest })
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, T>>) -> Result<()>,
{
compute(&mut self.height)?;
self.compute_rest(indexes, starting_indexes, exit)
}
/// Compute rest from self.height (for stateful computation patterns).
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
}
/// Derive from an external height source (e.g., a LazyVec).
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
source: &impl IterableVec<Height, T>,
exit: &Exit,
) -> Result<()> {
let target_len = source.len();
let starting_height = starting_indexes.height.to_usize().min(self.height.len());
self.height
.validate_computed_version_or_reset(source.version())?;
let mut source_iter = source.iter();
for h_idx in starting_height..target_len {
let height = Height::from(h_idx);
let value = source_iter.get_unwrap(height);
self.height.truncate_push(height, value)?;
}
self.height.write()?;
self.rest.derive_from(indexes, starting_indexes, &self.height, exit)
}
}

View File

@@ -0,0 +1,17 @@
//! Multi-index composite types.
mod date;
mod derived_date;
mod derived_height;
mod derived_tx;
mod height;
mod specialized;
mod value;
pub use date::*;
pub use derived_date::*;
pub use derived_height::*;
pub use derived_tx::*;
pub use height::*;
pub use specialized::*;
pub use value::*;

View File

@@ -0,0 +1,87 @@
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, Height, MonthIndex, QuarterIndex, SemesterIndex, Version, WeekIndex,
YearIndex,
};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{Formattable, IterableCloneableVec, LazyVecFrom1, UnaryTransform, VecValue};
use crate::indexes;
/// Lazy constant vecs for all index levels.
/// Uses const generic transforms to return the same value for every index.
#[derive(Clone, Traversable)]
#[traversable(merge)]
pub struct ConstantVecs<T>
where
T: VecValue + Formattable + Serialize + JsonSchema,
{
pub height: LazyVecFrom1<Height, T, Height, Height>,
pub dateindex: LazyVecFrom1<DateIndex, T, DateIndex, DateIndex>,
pub weekindex: LazyVecFrom1<WeekIndex, T, WeekIndex, WeekIndex>,
pub monthindex: LazyVecFrom1<MonthIndex, T, MonthIndex, MonthIndex>,
pub quarterindex: LazyVecFrom1<QuarterIndex, T, QuarterIndex, QuarterIndex>,
pub semesterindex: LazyVecFrom1<SemesterIndex, T, SemesterIndex, SemesterIndex>,
pub yearindex: LazyVecFrom1<YearIndex, T, YearIndex, YearIndex>,
pub decadeindex: LazyVecFrom1<DecadeIndex, T, DecadeIndex, DecadeIndex>,
}
impl<T: VecValue + Formattable + Serialize + JsonSchema> ConstantVecs<T> {
/// Create constant vecs using a transform that ignores input and returns a constant.
pub fn new<F>(name: &str, version: Version, indexes: &indexes::Vecs) -> Self
where
F: UnaryTransform<Height, T>
+ UnaryTransform<DateIndex, T>
+ UnaryTransform<WeekIndex, T>
+ UnaryTransform<MonthIndex, T>
+ UnaryTransform<QuarterIndex, T>
+ UnaryTransform<SemesterIndex, T>
+ UnaryTransform<YearIndex, T>
+ UnaryTransform<DecadeIndex, T>,
{
Self {
height: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.height.identity.boxed_clone(),
),
dateindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.dateindex.identity.boxed_clone(),
),
weekindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.weekindex.identity.boxed_clone(),
),
monthindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.monthindex.identity.boxed_clone(),
),
quarterindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.quarterindex.identity.boxed_clone(),
),
semesterindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.semesterindex.identity.boxed_clone(),
),
yearindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.yearindex.identity.boxed_clone(),
),
decadeindex: LazyVecFrom1::transformed::<F>(
name,
version,
indexes.decadeindex.identity.boxed_clone(),
),
}
}
}

View File

@@ -0,0 +1,11 @@
mod constant;
mod ohlc;
mod percentiles;
mod ratio;
mod stddev;
pub use constant::*;
pub use ohlc::*;
pub use percentiles::*;
pub use ratio::*;
pub use stddev::*;

View File

@@ -0,0 +1,68 @@
//! OHLC computed aggregations combining height, dateindex, and period indexes.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Close, High, Low, Open, Version};
use schemars::JsonSchema;
use vecdb::Database;
use crate::indexes;
use crate::internal::{
ComputedHeightDateFirst, ComputedHeightDateLast, ComputedHeightDateMax, ComputedHeightDateMin,
ComputedVecValue,
};
/// Combined OHLC computed vecs with all indexes (height + dateindex + periods + difficultyepoch).
///
/// Access pattern: `ohlc.{open,high,low,close}.{height,dateindex,weekindex,...,difficultyepoch}`
#[derive(Clone, Traversable)]
pub struct OHLCComputedVecs<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema + From<f64>,
f64: From<T>,
{
pub open: ComputedHeightDateFirst<Open<T>>,
pub high: ComputedHeightDateMax<High<T>>,
pub low: ComputedHeightDateMin<Low<T>>,
pub close: ComputedHeightDateLast<Close<T>>,
}
impl<T> OHLCComputedVecs<T>
where
T: ComputedVecValue + PartialOrd + JsonSchema + From<f64> + 'static,
f64: From<T>,
{
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
) -> Result<Self> {
Ok(Self {
open: ComputedHeightDateFirst::forced_import(
db,
&format!("{name}_open"),
version,
indexes,
)?,
high: ComputedHeightDateMax::forced_import(
db,
&format!("{name}_high"),
version,
indexes,
)?,
low: ComputedHeightDateMin::forced_import(
db,
&format!("{name}_low"),
version,
indexes,
)?,
close: ComputedHeightDateLast::forced_import(
db,
&format!("{name}_close"),
version,
indexes,
)?,
})
}
}

View File

@@ -0,0 +1,32 @@
//! Lazy OHLC component extractors for height + dateindex.
use brk_traversable::Traversable;
use brk_types::{Close, DateIndex, Height, High, Low, Open};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{BytesVecValue, Formattable, LazyVecFrom1, VecIndex};
/// Lazy OHLC component extractors for a single index type.
#[derive(Clone, Traversable)]
pub struct LazyOHLC<I, T, SourceT>
where
I: VecIndex + BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
SourceT: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
{
pub open: LazyVecFrom1<I, Open<T>, I, SourceT>,
pub high: LazyVecFrom1<I, High<T>, I, SourceT>,
pub low: LazyVecFrom1<I, Low<T>, I, SourceT>,
pub close: LazyVecFrom1<I, Close<T>, I, SourceT>,
}
/// Lazy OHLC component extractors for height + dateindex.
#[derive(Clone, Traversable)]
pub struct LazyHeightDateOHLC<T, SourceT>
where
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
SourceT: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
{
pub height: LazyOHLC<Height, T, SourceT>,
pub dateindex: LazyOHLC<DateIndex, T, SourceT>,
}

View File

@@ -0,0 +1,7 @@
mod computed;
mod lazy;
mod period;
pub use computed::*;
pub use lazy::*;
pub use period::*;

View File

@@ -0,0 +1,29 @@
//! OHLC period groupings for all time/chain periods.
use brk_traversable::Traversable;
use brk_types::{
DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, SemesterIndex,
WeekIndex, YearIndex,
};
use schemars::JsonSchema;
use serde::Serialize;
use vecdb::{BytesVec, BytesVecValue, EagerVec, Formattable};
/// Bundled OHLC vecs for all periods (time + chain based).
#[derive(Clone, Traversable)]
pub struct OHLCPeriodVecs<T>
where
T: BytesVecValue + Formattable + Serialize + JsonSchema + 'static,
{
// Time-based periods
pub dateindex: EagerVec<BytesVec<DateIndex, T>>,
pub week: EagerVec<BytesVec<WeekIndex, T>>,
pub month: EagerVec<BytesVec<MonthIndex, T>>,
pub quarter: EagerVec<BytesVec<QuarterIndex, T>>,
pub semester: EagerVec<BytesVec<SemesterIndex, T>>,
pub year: EagerVec<BytesVec<YearIndex, T>>,
pub decade: EagerVec<BytesVec<DecadeIndex, T>>,
// Chain-based periods
pub height: EagerVec<BytesVec<Height, T>>,
pub difficultyepoch: EagerVec<BytesVec<DifficultyEpoch, T>>,
}

View File

@@ -0,0 +1,139 @@
use brk_error::Result;
use brk_traversable::{Traversable, TreeNode};
use brk_types::{DateIndex, Dollars, Version};
use rayon::prelude::*;
use vecdb::{
AnyExportableVec, AnyStoredVec, AnyVec, Database, EagerVec, Exit, GenericStoredVec, PcoVec,
};
use crate::{ComputeIndexes, indexes};
use super::super::ComputedDateLast;
pub const PERCENTILES: [u8; 19] = [
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95,
];
pub const PERCENTILES_LEN: usize = PERCENTILES.len();
#[derive(Clone)]
pub struct CostBasisPercentiles {
pub vecs: [Option<ComputedDateLast<Dollars>>; PERCENTILES_LEN],
}
const VERSION: Version = Version::ZERO;
impl CostBasisPercentiles {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
compute: bool,
) -> Result<Self> {
let vecs = PERCENTILES.map(|p| {
compute.then(|| {
let metric_name = if name.is_empty() {
format!("cost_basis_pct{p:02}")
} else {
format!("{name}_cost_basis_pct{p:02}")
};
ComputedDateLast::forced_import(db, &metric_name, version + VERSION, indexes)
.unwrap()
})
});
Ok(Self { vecs })
}
/// Get minimum length across dateindex-indexed vectors written in block loop.
pub fn min_stateful_dateindex_len(&self) -> usize {
self.vecs
.iter()
.filter_map(|v| v.as_ref())
.map(|v| v.dateindex.len())
.min()
.unwrap_or(usize::MAX)
}
/// Push percentile prices at date boundary.
/// Only called when dateindex is Some (last height of the day).
pub fn truncate_push(
&mut self,
dateindex: DateIndex,
percentile_prices: &[Dollars; PERCENTILES_LEN],
) -> Result<()> {
for (i, vec) in self.vecs.iter_mut().enumerate() {
if let Some(v) = vec {
v.dateindex.truncate_push(dateindex, percentile_prices[i])?;
}
}
Ok(())
}
pub fn compute_rest(&mut self, starting_indexes: &ComputeIndexes, exit: &Exit) -> Result<()> {
for vec in self.vecs.iter_mut().flatten() {
vec.compute_rest(
starting_indexes,
exit,
None::<&EagerVec<PcoVec<DateIndex, Dollars>>>,
)?;
}
Ok(())
}
pub fn get(&self, percentile: u8) -> Option<&ComputedDateLast<Dollars>> {
PERCENTILES
.iter()
.position(|&p| p == percentile)
.and_then(|i| self.vecs[i].as_ref())
}
}
impl CostBasisPercentiles {
pub fn write(&mut self) -> Result<()> {
for vec in self.vecs.iter_mut().flatten() {
vec.dateindex.write()?;
}
Ok(())
}
/// Returns a parallel iterator over all vecs for parallel writing.
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = &mut dyn AnyStoredVec> {
self.vecs
.iter_mut()
.flatten()
.map(|v| &mut v.dateindex as &mut dyn AnyStoredVec)
.collect::<Vec<_>>()
.into_par_iter()
}
/// Validate computed versions or reset if mismatched.
pub fn validate_computed_version_or_reset(&mut self, version: Version) -> Result<()> {
for vec in self.vecs.iter_mut().flatten() {
vec.dateindex.validate_computed_version_or_reset(version)?;
}
Ok(())
}
}
impl Traversable for CostBasisPercentiles {
fn to_tree_node(&self) -> TreeNode {
TreeNode::Branch(
PERCENTILES
.iter()
.zip(self.vecs.iter())
.filter_map(|(p, v)| {
v.as_ref()
.map(|v| (format!("cost_basis_pct{p:02}"), v.to_tree_node()))
})
.collect(),
)
}
fn iter_any_exportable(&self) -> impl Iterator<Item = &dyn AnyExportableVec> {
self.vecs
.iter()
.flatten()
.flat_map(|p| p.iter_any_exportable())
}
}

View File

@@ -0,0 +1,340 @@
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Date, DateIndex, Dollars, StoredF32, Version};
use vecdb::{
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
PcoVec, VecIndex,
};
use crate::{
ComputeIndexes, indexes,
internal::{
ComputedStandardDeviationVecsDate, LazyBinaryDateLast, PriceTimesRatio,
StandardDeviationVecsOptions,
},
price,
utils::get_percentile,
};
use super::super::{ComputedBlockLast, ComputedDateLast};
#[derive(Clone, Traversable)]
pub struct ComputedRatioVecsDate {
pub price: Option<ComputedDateLast<Dollars>>,
pub ratio: ComputedDateLast<StoredF32>,
pub ratio_1w_sma: Option<ComputedDateLast<StoredF32>>,
pub ratio_1m_sma: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct99: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct98: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct95: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct5: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct2: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct1: Option<ComputedDateLast<StoredF32>>,
pub ratio_pct99_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct98_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct95_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct5_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct2_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_pct1_usd: Option<LazyBinaryDateLast<Dollars, Dollars, StoredF32>>,
pub ratio_sd: Option<ComputedStandardDeviationVecsDate>,
pub ratio_4y_sd: Option<ComputedStandardDeviationVecsDate>,
pub ratio_2y_sd: Option<ComputedStandardDeviationVecsDate>,
pub ratio_1y_sd: Option<ComputedStandardDeviationVecsDate>,
}
const VERSION: Version = Version::TWO;
impl ComputedRatioVecsDate {
#[allow(clippy::too_many_arguments)]
pub fn forced_import(
db: &Database,
name: &str,
metric_price: Option<&ComputedBlockLast<Dollars>>,
version: Version,
indexes: &indexes::Vecs,
extended: bool,
price_vecs: Option<&price::Vecs>,
) -> Result<Self> {
let v = version + VERSION;
macro_rules! import {
($suffix:expr) => {
ComputedDateLast::forced_import(db, &format!("{name}_{}", $suffix), v, indexes)
.unwrap()
};
}
// Create price sources first so lazy vecs can reference them
// Only compute internally when metric_price is None
let price = metric_price
.is_none()
.then(|| ComputedDateLast::forced_import(db, name, v, indexes).unwrap());
macro_rules! import_sd {
($suffix:expr, $days:expr) => {
ComputedStandardDeviationVecsDate::forced_import(
db,
&format!("{name}_{}", $suffix),
$days,
v,
indexes,
StandardDeviationVecsOptions::default().add_all(),
price_vecs,
)
.unwrap()
};
}
let ratio_pct99 = extended.then(|| import!("ratio_pct99"));
let ratio_pct98 = extended.then(|| import!("ratio_pct98"));
let ratio_pct95 = extended.then(|| import!("ratio_pct95"));
let ratio_pct5 = extended.then(|| import!("ratio_pct5"));
let ratio_pct2 = extended.then(|| import!("ratio_pct2"));
let ratio_pct1 = extended.then(|| import!("ratio_pct1"));
macro_rules! lazy_usd {
($ratio:expr, $suffix:expr) => {
if let Some(mp) = metric_price {
$ratio.as_ref().map(|r| {
LazyBinaryDateLast::from_height_and_dateindex_last::<PriceTimesRatio>(
&format!("{name}_{}", $suffix),
v,
mp,
r,
)
})
} else {
price.as_ref().zip($ratio.as_ref()).map(|(p, r)| {
LazyBinaryDateLast::from_computed_both_last::<PriceTimesRatio>(
&format!("{name}_{}", $suffix),
v,
p,
r,
)
})
}
};
}
Ok(Self {
ratio: import!("ratio"),
ratio_1w_sma: extended.then(|| import!("ratio_1w_sma")),
ratio_1m_sma: extended.then(|| import!("ratio_1m_sma")),
ratio_sd: extended.then(|| import_sd!("ratio", usize::MAX)),
ratio_1y_sd: extended.then(|| import_sd!("ratio_1y", 365)),
ratio_2y_sd: extended.then(|| import_sd!("ratio_2y", 2 * 365)),
ratio_4y_sd: extended.then(|| import_sd!("ratio_4y", 4 * 365)),
ratio_pct99_usd: lazy_usd!(&ratio_pct99, "ratio_pct99_usd"),
ratio_pct98_usd: lazy_usd!(&ratio_pct98, "ratio_pct98_usd"),
ratio_pct95_usd: lazy_usd!(&ratio_pct95, "ratio_pct95_usd"),
ratio_pct5_usd: lazy_usd!(&ratio_pct5, "ratio_pct5_usd"),
ratio_pct2_usd: lazy_usd!(&ratio_pct2, "ratio_pct2_usd"),
ratio_pct1_usd: lazy_usd!(&ratio_pct1, "ratio_pct1_usd"),
price,
ratio_pct99,
ratio_pct98,
ratio_pct95,
ratio_pct5,
ratio_pct2,
ratio_pct1,
})
}
pub fn compute_all<F>(
&mut self,
price: &price::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Dollars>>) -> Result<()>,
{
self.price
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, compute)?;
let date_to_price_opt: Option<&EagerVec<PcoVec<DateIndex, Dollars>>> = None;
self.compute_rest(price, starting_indexes, exit, date_to_price_opt)
}
pub fn compute_rest(
&mut self,
price: &price::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
price_opt: Option<&impl IterableVec<DateIndex, Dollars>>,
) -> Result<()> {
let closes = &price.usd.split.close.dateindex;
let price = price_opt.unwrap_or_else(|| unsafe {
std::mem::transmute(&self.price.as_ref().unwrap().dateindex)
});
self.ratio.compute_all(starting_indexes, exit, |v| {
v.compute_transform2(
starting_indexes.dateindex,
closes,
price,
|(i, close, price, ..)| {
if price == Dollars::ZERO {
(i, StoredF32::from(1.0))
} else {
(i, StoredF32::from(*close / price))
}
},
exit,
)?;
Ok(())
})?;
if self.ratio_1w_sma.is_none() {
return Ok(());
}
let min_ratio_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
self.ratio_1w_sma
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, |v| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
7,
exit,
Some(min_ratio_date),
)?;
Ok(())
})?;
self.ratio_1m_sma
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, |v| {
v.compute_sma_(
starting_indexes.dateindex,
&self.ratio.dateindex,
30,
exit,
Some(min_ratio_date),
)?;
Ok(())
})?;
let ratio_version = self.ratio.dateindex.version();
self.mut_ratio_vecs()
.iter_mut()
.try_for_each(|v| -> Result<()> {
v.validate_computed_version_or_reset(ratio_version)?;
Ok(())
})?;
let starting_dateindex = self
.mut_ratio_vecs()
.iter()
.map(|v| DateIndex::from(v.len()))
.min()
.unwrap()
.min(starting_indexes.dateindex);
let min_ratio_date_usize = min_ratio_date.to_usize();
let mut sorted = self.ratio.dateindex.collect_range(
Some(min_ratio_date_usize),
Some(starting_dateindex.to_usize()),
);
sorted.sort_unstable();
// Cache mutable refs before the loop to avoid repeated unwrap chains
let pct1_vec = &mut self.ratio_pct1.as_mut().unwrap().dateindex;
let pct2_vec = &mut self.ratio_pct2.as_mut().unwrap().dateindex;
let pct5_vec = &mut self.ratio_pct5.as_mut().unwrap().dateindex;
let pct95_vec = &mut self.ratio_pct95.as_mut().unwrap().dateindex;
let pct98_vec = &mut self.ratio_pct98.as_mut().unwrap().dateindex;
let pct99_vec = &mut self.ratio_pct99.as_mut().unwrap().dateindex;
self.ratio
.dateindex
.iter()
.enumerate()
.skip(starting_dateindex.to_usize())
.try_for_each(|(index, ratio)| -> Result<()> {
if index < min_ratio_date_usize {
pct1_vec.truncate_push_at(index, StoredF32::NAN)?;
pct2_vec.truncate_push_at(index, StoredF32::NAN)?;
pct5_vec.truncate_push_at(index, StoredF32::NAN)?;
pct95_vec.truncate_push_at(index, StoredF32::NAN)?;
pct98_vec.truncate_push_at(index, StoredF32::NAN)?;
pct99_vec.truncate_push_at(index, StoredF32::NAN)?;
} else {
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
sorted.insert(pos, ratio);
pct1_vec.truncate_push_at(index, get_percentile(&sorted, 0.01))?;
pct2_vec.truncate_push_at(index, get_percentile(&sorted, 0.02))?;
pct5_vec.truncate_push_at(index, get_percentile(&sorted, 0.05))?;
pct95_vec.truncate_push_at(index, get_percentile(&sorted, 0.95))?;
pct98_vec.truncate_push_at(index, get_percentile(&sorted, 0.98))?;
pct99_vec.truncate_push_at(index, get_percentile(&sorted, 0.99))?;
}
Ok(())
})?;
{
let _lock = exit.lock();
self.mut_ratio_vecs()
.into_iter()
.try_for_each(|v| v.flush())?;
}
macro_rules! compute_pct_rest {
($($field:ident),*) => {
$(self.$field.as_mut().unwrap().compute_rest(
starting_indexes, exit, None as Option<&EagerVec<PcoVec<_, _>>>,
)?;)*
};
}
compute_pct_rest!(
ratio_pct1,
ratio_pct2,
ratio_pct5,
ratio_pct95,
ratio_pct98,
ratio_pct99
);
macro_rules! compute_sd {
($($field:ident),*) => {
$(self.$field.as_mut().unwrap().compute_all(
starting_indexes, exit, &self.ratio.dateindex,
)?;)*
};
}
compute_sd!(ratio_sd, ratio_4y_sd, ratio_2y_sd, ratio_1y_sd);
Ok(())
}
fn mut_ratio_vecs(&mut self) -> Vec<&mut EagerVec<PcoVec<DateIndex, StoredF32>>> {
macro_rules! collect_vecs {
($($field:ident),*) => {{
let mut vecs = Vec::with_capacity(6);
$(if let Some(v) = self.$field.as_mut() { vecs.push(&mut v.dateindex); })*
vecs
}};
}
collect_vecs!(
ratio_pct1,
ratio_pct2,
ratio_pct5,
ratio_pct95,
ratio_pct98,
ratio_pct99
)
}
}

View File

@@ -0,0 +1,398 @@
use std::mem;
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Close, Date, DateIndex, Dollars, StoredF32, Version};
use vecdb::{
AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, GenericStoredVec, IterableVec,
PcoVec, VecIndex,
};
use crate::{ComputeIndexes, indexes, price};
use crate::internal::{ClosePriceTimesRatio, ComputedDateLast, LazyBinaryDateLast};
#[derive(Clone, Traversable)]
pub struct ComputedStandardDeviationVecsDate {
days: usize,
pub sma: Option<ComputedDateLast<StoredF32>>,
pub sd: ComputedDateLast<StoredF32>,
pub zscore: Option<ComputedDateLast<StoredF32>>,
pub p0_5sd: Option<ComputedDateLast<StoredF32>>,
pub p1sd: Option<ComputedDateLast<StoredF32>>,
pub p1_5sd: Option<ComputedDateLast<StoredF32>>,
pub p2sd: Option<ComputedDateLast<StoredF32>>,
pub p2_5sd: Option<ComputedDateLast<StoredF32>>,
pub p3sd: Option<ComputedDateLast<StoredF32>>,
pub m0_5sd: Option<ComputedDateLast<StoredF32>>,
pub m1sd: Option<ComputedDateLast<StoredF32>>,
pub m1_5sd: Option<ComputedDateLast<StoredF32>>,
pub m2sd: Option<ComputedDateLast<StoredF32>>,
pub m2_5sd: Option<ComputedDateLast<StoredF32>>,
pub m3sd: Option<ComputedDateLast<StoredF32>>,
pub _0sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p0_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p1sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p1_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p2sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p2_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub p3sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m0_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m1sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m1_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m2sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m2_5sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
pub m3sd_usd: Option<LazyBinaryDateLast<Dollars, Close<Dollars>, StoredF32>>,
}
#[derive(Debug, Default)]
pub struct StandardDeviationVecsOptions {
zscore: bool,
bands: bool,
price_bands: bool,
}
impl StandardDeviationVecsOptions {
pub fn add_all(mut self) -> Self {
self.zscore = true;
self.bands = true;
self.price_bands = true;
self
}
pub fn add_zscore(mut self) -> Self {
self.zscore = true;
self
}
pub fn add_bands(mut self) -> Self {
self.bands = true;
self
}
pub fn add_price_bands(mut self) -> Self {
self.bands = true;
self.price_bands = true;
self
}
pub fn zscore(&self) -> bool {
self.zscore
}
pub fn bands(&self) -> bool {
self.bands
}
pub fn price_bands(&self) -> bool {
self.price_bands
}
}
impl ComputedStandardDeviationVecsDate {
#[allow(clippy::too_many_arguments)]
pub fn forced_import(
db: &Database,
name: &str,
days: usize,
parent_version: Version,
indexes: &indexes::Vecs,
options: StandardDeviationVecsOptions,
price_vecs: Option<&price::Vecs>,
) -> Result<Self> {
let version = parent_version + Version::ONE;
macro_rules! import {
($suffix:expr) => {
ComputedDateLast::forced_import(
db,
&format!("{name}_{}", $suffix),
version,
indexes,
)
.unwrap()
};
}
let sma_vec = Some(import!("sma"));
let p0_5sd = options.bands().then(|| import!("p0_5sd"));
let p1sd = options.bands().then(|| import!("p1sd"));
let p1_5sd = options.bands().then(|| import!("p1_5sd"));
let p2sd = options.bands().then(|| import!("p2sd"));
let p2_5sd = options.bands().then(|| import!("p2_5sd"));
let p3sd = options.bands().then(|| import!("p3sd"));
let m0_5sd = options.bands().then(|| import!("m0_5sd"));
let m1sd = options.bands().then(|| import!("m1sd"));
let m1_5sd = options.bands().then(|| import!("m1_5sd"));
let m2sd = options.bands().then(|| import!("m2sd"));
let m2_5sd = options.bands().then(|| import!("m2_5sd"));
let m3sd = options.bands().then(|| import!("m3sd"));
macro_rules! lazy_usd {
($band:expr, $suffix:expr) => {
price_vecs
.map(|p| &p.usd.split.close)
.zip($band.as_ref())
.filter(|_| options.price_bands())
.map(|(p, b)| {
LazyBinaryDateLast::from_computed_both_last::<ClosePriceTimesRatio>(
&format!("{name}_{}", $suffix),
version,
p,
b,
)
})
};
}
Ok(Self {
days,
sd: import!("sd"),
zscore: options.zscore().then(|| import!("zscore")),
// Lazy USD vecs
_0sd_usd: lazy_usd!(&sma_vec, "0sd_usd"),
p0_5sd_usd: lazy_usd!(&p0_5sd, "p0_5sd_usd"),
p1sd_usd: lazy_usd!(&p1sd, "p1sd_usd"),
p1_5sd_usd: lazy_usd!(&p1_5sd, "p1_5sd_usd"),
p2sd_usd: lazy_usd!(&p2sd, "p2sd_usd"),
p2_5sd_usd: lazy_usd!(&p2_5sd, "p2_5sd_usd"),
p3sd_usd: lazy_usd!(&p3sd, "p3sd_usd"),
m0_5sd_usd: lazy_usd!(&m0_5sd, "m0_5sd_usd"),
m1sd_usd: lazy_usd!(&m1sd, "m1sd_usd"),
m1_5sd_usd: lazy_usd!(&m1_5sd, "m1_5sd_usd"),
m2sd_usd: lazy_usd!(&m2sd, "m2sd_usd"),
m2_5sd_usd: lazy_usd!(&m2_5sd, "m2_5sd_usd"),
m3sd_usd: lazy_usd!(&m3sd, "m3sd_usd"),
// Stored band sources
sma: sma_vec,
p0_5sd,
p1sd,
p1_5sd,
p2sd,
p2_5sd,
p3sd,
m0_5sd,
m1sd,
m1_5sd,
m2sd,
m2_5sd,
m3sd,
})
}
pub fn compute_all(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
source: &impl CollectableVec<DateIndex, StoredF32>,
) -> Result<()> {
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
self.sma
.as_mut()
.unwrap()
.compute_all(starting_indexes, exit, |v| {
v.compute_sma_(
starting_indexes.dateindex,
source,
self.days,
exit,
Some(min_date),
)?;
Ok(())
})?;
let sma_opt: Option<&EagerVec<PcoVec<DateIndex, StoredF32>>> = None;
self.compute_rest(starting_indexes, exit, sma_opt, source)
}
pub fn compute_rest(
&mut self,
starting_indexes: &ComputeIndexes,
exit: &Exit,
sma_opt: Option<&impl IterableVec<DateIndex, StoredF32>>,
source: &impl CollectableVec<DateIndex, StoredF32>,
) -> Result<()> {
let sma = sma_opt
.unwrap_or_else(|| unsafe { mem::transmute(&self.sma.as_ref().unwrap().dateindex) });
let min_date = DateIndex::try_from(Date::MIN_RATIO).unwrap();
let source_version = source.version();
self.mut_stateful_date_vecs()
.try_for_each(|v| -> Result<()> {
v.validate_computed_version_or_reset(source_version)?;
Ok(())
})?;
let starting_dateindex = self
.mut_stateful_date_vecs()
.map(|v| DateIndex::from(v.len()))
.min()
.unwrap()
.min(starting_indexes.dateindex);
let mut sorted = source.collect_range(
Some(min_date.to_usize()),
Some(starting_dateindex.to_usize()),
);
sorted.sort_unstable();
macro_rules! band_ref {
($field:ident) => {
self.$field.as_mut().map(|c| &mut c.dateindex)
};
}
let mut p0_5sd = band_ref!(p0_5sd);
let mut p1sd = band_ref!(p1sd);
let mut p1_5sd = band_ref!(p1_5sd);
let mut p2sd = band_ref!(p2sd);
let mut p2_5sd = band_ref!(p2_5sd);
let mut p3sd = band_ref!(p3sd);
let mut m0_5sd = band_ref!(m0_5sd);
let mut m1sd = band_ref!(m1sd);
let mut m1_5sd = band_ref!(m1_5sd);
let mut m2sd = band_ref!(m2sd);
let mut m2_5sd = band_ref!(m2_5sd);
let mut m3sd = band_ref!(m3sd);
let min_date_usize = min_date.to_usize();
let mut sma_iter = sma.iter().skip(starting_dateindex.to_usize());
source
.iter()
.enumerate()
.skip(starting_dateindex.to_usize())
.try_for_each(|(index, ratio)| -> Result<()> {
if index < min_date_usize {
self.sd.dateindex.truncate_push_at(index, StoredF32::NAN)?;
macro_rules! push_nan {
($($band:ident),*) => {
$(if let Some(v) = $band.as_mut() { v.truncate_push_at(index, StoredF32::NAN)? })*
};
}
push_nan!(p0_5sd, p1sd, p1_5sd, p2sd, p2_5sd, p3sd, m0_5sd, m1sd, m1_5sd, m2sd, m2_5sd, m3sd);
// Advance iterator to stay in sync
sma_iter.next();
} else {
let pos = sorted.binary_search(&ratio).unwrap_or_else(|pos| pos);
sorted.insert(pos, ratio);
let average = sma_iter.next().unwrap();
let population =
index.checked_sub(min_date_usize).unwrap().to_usize() as f32 + 1.0;
let sd = StoredF32::from(
(sorted.iter().map(|v| (**v - *average).powi(2)).sum::<f32>() / population)
.sqrt(),
);
self.sd.dateindex.truncate_push_at(index, sd)?;
if let Some(v) = p0_5sd.as_mut() {
v.truncate_push_at(index, average + StoredF32::from(0.5 * *sd))?
}
if let Some(v) = p1sd.as_mut() {
v.truncate_push_at(index, average + sd)?
}
if let Some(v) = p1_5sd.as_mut() {
v.truncate_push_at(index, average + StoredF32::from(1.5 * *sd))?
}
if let Some(v) = p2sd.as_mut() {
v.truncate_push_at(index, average + 2 * sd)?
}
if let Some(v) = p2_5sd.as_mut() {
v.truncate_push_at(index, average + StoredF32::from(2.5 * *sd))?
}
if let Some(v) = p3sd.as_mut() {
v.truncate_push_at(index, average + 3 * sd)?
}
if let Some(v) = m0_5sd.as_mut() {
v.truncate_push_at(index, average - StoredF32::from(0.5 * *sd))?
}
if let Some(v) = m1sd.as_mut() {
v.truncate_push_at(index, average - sd)?
}
if let Some(v) = m1_5sd.as_mut() {
v.truncate_push_at(index, average - StoredF32::from(1.5 * *sd))?
}
if let Some(v) = m2sd.as_mut() {
v.truncate_push_at(index, average - 2 * sd)?
}
if let Some(v) = m2_5sd.as_mut() {
v.truncate_push_at(index, average - StoredF32::from(2.5 * *sd))?
}
if let Some(v) = m3sd.as_mut() {
v.truncate_push_at(index, average - 3 * sd)?
}
}
Ok(())
})?;
drop(sma_iter);
{
let _lock = exit.lock();
self.mut_stateful_date_vecs().try_for_each(|v| v.flush())?;
}
self.mut_stateful_computed().try_for_each(|v| {
v.compute_rest(
starting_indexes,
exit,
None as Option<&EagerVec<PcoVec<_, _>>>,
)
})?;
if let Some(zscore) = self.zscore.as_mut() {
zscore.compute_all(starting_indexes, exit, |vec| {
vec.compute_zscore(
starting_indexes.dateindex,
source,
sma,
&self.sd.dateindex,
exit,
)?;
Ok(())
})?;
}
Ok(())
}
fn mut_stateful_computed(&mut self) -> impl Iterator<Item = &mut ComputedDateLast<StoredF32>> {
[
Some(&mut self.sd),
self.p0_5sd.as_mut(),
self.p1sd.as_mut(),
self.p1_5sd.as_mut(),
self.p2sd.as_mut(),
self.p2_5sd.as_mut(),
self.p3sd.as_mut(),
self.m0_5sd.as_mut(),
self.m1sd.as_mut(),
self.m1_5sd.as_mut(),
self.m2sd.as_mut(),
self.m2_5sd.as_mut(),
self.m3sd.as_mut(),
]
.into_iter()
.flatten()
}
fn mut_stateful_date_vecs(
&mut self,
) -> impl Iterator<Item = &mut EagerVec<PcoVec<DateIndex, StoredF32>>> {
self.mut_stateful_computed().map(|c| &mut c.dateindex)
}
}

View File

@@ -0,0 +1,86 @@
//! Value type for Derived Last pattern from DateIndex (when source is external).
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Sats, Version};
use vecdb::{Database, Exit, IterableBoxedVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedDateLast, LazyPeriodsLast, LazyDateLast, SatsToBitcoin},
price,
traits::ComputeFromBitcoin,
utils::OptionExt,
};
#[derive(Clone, Traversable)]
pub struct ValueLazyPeriodsLast {
pub sats: LazyPeriodsLast<Sats>,
pub bitcoin: LazyDateLast<Bitcoin, Sats>,
pub dollars: Option<ComputedDateLast<Dollars>>,
}
const VERSION: Version = Version::ZERO;
impl ValueLazyPeriodsLast {
pub fn from_source(
db: &Database,
name: &str,
source: IterableBoxedVec<DateIndex, Sats>,
version: Version,
compute_dollars: bool,
indexes: &indexes::Vecs,
) -> Result<Self> {
let sats = LazyPeriodsLast::from_source(name, version + VERSION, source.clone(), indexes);
let bitcoin = LazyDateLast::from_derived::<SatsToBitcoin>(
&format!("{name}_btc"),
version + VERSION,
source,
&sats,
);
let dollars = compute_dollars.then(|| {
ComputedDateLast::forced_import(db, &format!("{name}_usd"), version + VERSION, indexes)
.unwrap()
});
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn compute_dollars<F>(&mut self, mut compute: F) -> Result<()>
where
F: FnMut(&mut ComputedDateLast<Dollars>) -> Result<()>,
{
if let Some(dollars) = self.dollars.as_mut() {
compute(dollars)?;
}
Ok(())
}
pub fn compute_dollars_from_price(
&mut self,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
if let Some(dollars) = self.dollars.as_mut() {
let dateindex_to_bitcoin = &*self.bitcoin.dateindex;
let dateindex_to_price_close = &price.u().usd.split.close.dateindex;
dollars.compute_all(starting_indexes, exit, |v| {
v.compute_from_bitcoin(
starting_indexes.dateindex,
dateindex_to_bitcoin,
dateindex_to_price_close,
exit,
)
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,82 @@
//! Value type for stateful Last pattern - height and dateindex both stored independently.
//!
//! Use this when dateindex values are NOT derivable from height (e.g., unrealized metrics
//! where end-of-day state differs from last-block-of-day).
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Height, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes, price};
use crate::internal::{LazyDerivedBlockValue, LazyValueDifficultyEpochFromHeight};
use super::ValueDateLast;
/// Value type where both height and dateindex are stored independently.
/// Dateindex values cannot be derived from height (e.g., unrealized P&L).
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ValueHeightDateLast {
#[traversable(rename = "sats")]
pub height: EagerVec<PcoVec<Height, Sats>>,
#[traversable(flatten)]
pub height_value: LazyDerivedBlockValue,
#[traversable(flatten)]
pub difficultyepoch: LazyValueDifficultyEpochFromHeight,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub indexes: ValueDateLast,
}
const VERSION: Version = Version::ZERO;
impl ValueHeightDateLast {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
compute_dollars: bool,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v = version + VERSION;
let height: EagerVec<PcoVec<Height, Sats>> = EagerVec::forced_import(db, name, v)?;
let price_source = price.map(|p| p.usd.split.close.height.boxed_clone());
let height_value =
LazyDerivedBlockValue::from_source(name, height.boxed_clone(), v, price_source);
let difficultyepoch = LazyValueDifficultyEpochFromHeight::from_height_source(
name,
height.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
price,
v,
);
let indexes = ValueDateLast::forced_import(db, name, v, compute_dollars, indexes)?;
Ok(Self {
height,
height_value,
difficultyepoch,
indexes,
})
}
/// Compute derived periods from dateindex.
pub fn compute_dollars_from_price(
&mut self,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes
.compute_dollars_from_price(price, starting_indexes, exit)
}
}

View File

@@ -0,0 +1,87 @@
//! Value type for Last pattern from DateIndex.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{DateIndex, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, EagerVec, Exit, ImportableVec, IterableCloneableVec, PcoVec};
use crate::{ComputeIndexes, indexes, price};
use super::ValueLazyPeriodsLast;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ValueDateLast {
#[traversable(rename = "sats")]
pub sats_dateindex: EagerVec<PcoVec<DateIndex, Sats>>,
#[deref]
#[deref_mut]
pub rest: ValueLazyPeriodsLast,
}
const VERSION: Version = Version::ZERO;
impl ValueDateLast {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
compute_dollars: bool,
indexes: &indexes::Vecs,
) -> Result<Self> {
let sats_dateindex = EagerVec::forced_import(db, name, version + VERSION)?;
let rest = ValueLazyPeriodsLast::from_source(
db,
name,
sats_dateindex.boxed_clone(),
version + VERSION,
compute_dollars,
indexes,
)?;
Ok(Self {
sats_dateindex,
rest,
})
}
pub fn compute_sats<F>(&mut self, mut compute: F) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Sats>>) -> Result<()>,
{
compute(&mut self.sats_dateindex)
}
pub fn compute_all<F>(
&mut self,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<DateIndex, Sats>>) -> Result<()>,
{
self.compute_sats(compute)?;
self.compute_dollars_from_price(price, starting_indexes, exit)
}
pub fn compute_dollars<F>(&mut self, compute: F) -> Result<()>
where
F: FnMut(&mut crate::internal::ComputedDateLast<brk_types::Dollars>) -> Result<()>,
{
self.rest.compute_dollars(compute)
}
pub fn compute_dollars_from_price(
&mut self,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.rest
.compute_dollars_from_price(price, starting_indexes, exit)
}
}

View File

@@ -0,0 +1,94 @@
//! Lazy value type for Last pattern from DateIndex.
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Sats, Version};
use vecdb::{IterableCloneableVec, UnaryTransform};
use crate::internal::{LazyDateLast, ValueBlockLast, ValueDateLast};
const VERSION: Version = Version::ZERO;
#[derive(Clone, Traversable)]
pub struct LazyValueDateLast {
pub sats: LazyDateLast<Sats, Sats>,
pub bitcoin: LazyDateLast<Bitcoin, Sats>,
pub dollars: Option<LazyDateLast<Dollars, Dollars>>,
}
impl LazyValueDateLast {
pub fn from_source<SatsTransform, BitcoinTransform, DollarsTransform>(
name: &str,
source: &ValueDateLast,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
DollarsTransform: UnaryTransform<Dollars, Dollars>,
{
let v = version + VERSION;
let sats = LazyDateLast::from_derived::<SatsTransform>(
name,
v,
source.sats_dateindex.boxed_clone(),
&source.sats,
);
let bitcoin = LazyDateLast::from_derived::<BitcoinTransform>(
&format!("{name}_btc"),
v,
source.sats_dateindex.boxed_clone(),
&source.sats,
);
let dollars = source.dollars.as_ref().map(|dollars_source| {
LazyDateLast::from_computed::<DollarsTransform>(
&format!("{name}_usd"),
v,
dollars_source.dateindex.boxed_clone(),
dollars_source,
)
});
Self { sats, bitcoin, dollars }
}
pub fn from_block_source<SatsTransform, BitcoinTransform, DollarsTransform>(
name: &str,
source: &ValueBlockLast,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
DollarsTransform: UnaryTransform<Dollars, Dollars>,
{
let v = version + VERSION;
let sats = LazyDateLast::from_derived::<SatsTransform>(
name,
v,
source.sats.rest.dateindex.0.boxed_clone(),
&source.sats.rest.dates,
);
let bitcoin = LazyDateLast::from_derived::<BitcoinTransform>(
&format!("{name}_btc"),
v,
source.sats.rest.dateindex.0.boxed_clone(),
&source.sats.rest.dates,
);
let dollars = source.dollars.as_ref().map(|dollars_source| {
LazyDateLast::from_derived::<DollarsTransform>(
&format!("{name}_usd"),
v,
dollars_source.rest.dateindex.0.boxed_clone(),
&dollars_source.rest.dates,
)
});
Self { sats, bitcoin, dollars }
}
}

View File

@@ -0,0 +1,9 @@
mod derived_last;
mod height_date_last;
mod last;
mod lazy_last;
pub use height_date_last::*;
pub use derived_last::*;
pub use last::*;
pub use lazy_last::*;

View File

@@ -0,0 +1,3 @@
mod sum_cum;
pub use sum_cum::*;

View File

@@ -0,0 +1,96 @@
//! Value type for derived SumCum pattern (derives from external height source).
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, IterableVec, LazyVecFrom2};
use crate::{
ComputeIndexes, indexes,
internal::{
ClosePriceTimesSats, ComputedDerivedBlockSumCum, LazyBlockSumCum, LazyBlockSumCumHeight,
SatsToBitcoin,
},
price,
};
/// Value wrapper for derived SumCum (derives from external height source).
#[derive(Clone, Traversable)]
pub struct ValueDerivedBlockSumCum {
pub sats: ComputedDerivedBlockSumCum<Sats>,
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
}
const VERSION: Version = Version::ZERO;
impl ValueDerivedBlockSumCum {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
sats_source: IterableBoxedVec<Height, Sats>,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedDerivedBlockSumCum::forced_import(
db,
name,
sats_source.boxed_clone(),
v,
indexes,
)?;
let bitcoin = LazyBlockSumCum::from_derived::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats_source.boxed_clone(),
&sats,
);
let dollars = if let Some(price) = price {
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
v,
price.usd.split.close.height.boxed_clone(),
sats_source.boxed_clone(),
);
Some(LazyBlockSumCumHeight::forced_import(
db,
&format!("{name}_usd"),
v,
indexes,
dollars_height,
)?)
} else {
None
};
Ok(Self {
sats,
bitcoin,
dollars,
})
}
/// Derive aggregates from caller-provided sats height source.
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
sats_source: &impl IterableVec<Height, Sats>,
exit: &Exit,
) -> Result<()> {
self.sats
.derive_from(indexes, starting_indexes, sats_source, exit)?;
if let Some(dollars) = self.dollars.as_mut() {
dollars.derive_from(indexes, starting_indexes, exit)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,179 @@
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use schemars::JsonSchema;
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec};
use crate::internal::{
ComputedVecValue, ValueDerivedBlockSumCum, LazyBinaryBlockSumCum, LazyValueBlockSumCum,
ValueBlockSumCum,
};
/// Lazy value vecs computed from two ValueBlockSumCum sources via binary transforms.
/// Used for computing coinbase = subsidy + fee.
#[derive(Clone, Traversable)]
pub struct ValueBinaryBlock {
pub sats: LazyBinaryBlockSumCum<Sats, Sats, Sats>,
pub bitcoin: LazyBinaryBlockSumCum<Bitcoin, Sats, Sats>,
pub dollars: Option<LazyBinaryBlockSumCum<Dollars, Dollars, Dollars>>,
}
impl ValueBinaryBlock {
pub fn from_computed<SatsF, BitcoinF, DollarsF>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, Sats>,
height_source2: IterableBoxedVec<Height, Sats>,
source1: &ValueBlockSumCum,
source2: &ValueBlockSumCum,
) -> Self
where
SatsF: BinaryTransform<Sats, Sats, Sats>,
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
{
let sats = LazyBinaryBlockSumCum::from_computed::<SatsF>(
name,
version,
height_source1.boxed_clone(),
height_source2.boxed_clone(),
&source1.sats,
&source2.sats,
);
let bitcoin = LazyBinaryBlockSumCum::from_computed::<BitcoinF>(
&format!("{name}_btc"),
version,
height_source1,
height_source2,
&source1.sats,
&source2.sats,
);
let dollars = source1
.dollars
.as_ref()
.zip(source2.dollars.as_ref())
.map(|(d1, d2)| {
LazyBinaryBlockSumCum::from_computed::<DollarsF>(
&format!("{name}_usd"),
version,
d1.height.boxed_clone(),
d2.height.boxed_clone(),
d1,
d2,
)
});
Self {
sats,
bitcoin,
dollars,
}
}
pub fn from_derived<SatsF, BitcoinF, DollarsF>(
name: &str,
version: Version,
height_source1: IterableBoxedVec<Height, Sats>,
height_source2: IterableBoxedVec<Height, Sats>,
source1: &ValueDerivedBlockSumCum,
source2: &ValueDerivedBlockSumCum,
) -> Self
where
SatsF: BinaryTransform<Sats, Sats, Sats>,
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
{
let sats = LazyBinaryBlockSumCum::from_derived::<SatsF>(
name,
version,
height_source1.boxed_clone(),
height_source2.boxed_clone(),
&source1.sats,
&source2.sats,
);
let bitcoin = LazyBinaryBlockSumCum::from_derived::<BitcoinF>(
&format!("{name}_btc"),
version,
height_source1,
height_source2,
&source1.sats,
&source2.sats,
);
let dollars = source1
.dollars
.as_ref()
.zip(source2.dollars.as_ref())
.map(|(d1, d2)| {
LazyBinaryBlockSumCum::from_derived::<DollarsF>(
&format!("{name}_usd"),
version,
d1.height_cumulative.0.boxed_clone(),
d2.height_cumulative.0.boxed_clone(),
d1,
d2,
)
});
Self {
sats,
bitcoin,
dollars,
}
}
pub fn from_lazy<SatsF, BitcoinF, DollarsF, S1T, S2T>(
name: &str,
version: Version,
source1: &LazyValueBlockSumCum<S1T, S2T>,
source2: &LazyValueBlockSumCum<S1T, S2T>,
) -> Self
where
SatsF: BinaryTransform<Sats, Sats, Sats>,
BitcoinF: BinaryTransform<Sats, Sats, Bitcoin>,
DollarsF: BinaryTransform<Dollars, Dollars, Dollars>,
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
let sats = LazyBinaryBlockSumCum::from_derived::<SatsF>(
name,
version,
source1.sats.height.boxed_clone(),
source2.sats.height.boxed_clone(),
&source1.sats.rest,
&source2.sats.rest,
);
let bitcoin = LazyBinaryBlockSumCum::from_derived::<BitcoinF>(
&format!("{name}_btc"),
version,
source1.sats.height.boxed_clone(),
source2.sats.height.boxed_clone(),
&source1.sats.rest,
&source2.sats.rest,
);
let dollars = source1
.dollars
.as_ref()
.zip(source2.dollars.as_ref())
.map(|(d1, d2)| {
LazyBinaryBlockSumCum::from_derived::<DollarsF>(
&format!("{name}_usd"),
version,
d1.height.boxed_clone(),
d2.height.boxed_clone(),
&d1.rest,
&d2.rest,
)
});
Self {
sats,
bitcoin,
dollars,
}
}
}

View File

@@ -0,0 +1,86 @@
//! Value type for Full pattern from Height.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedBlockFull, LazyBlockFull, SatsToBitcoin},
price,
traits::ComputeFromBitcoin,
};
#[derive(Clone, Traversable)]
pub struct ValueBlockFull {
pub sats: ComputedBlockFull<Sats>,
pub bitcoin: LazyBlockFull<Bitcoin, Sats>,
pub dollars: Option<ComputedBlockFull<Dollars>>,
}
const VERSION: Version = Version::ZERO;
impl ValueBlockFull {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedBlockFull::forced_import(db, name, v, indexes)?;
let bitcoin = LazyBlockFull::from_computed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats,
);
let dollars = compute_dollars
.then(|| ComputedBlockFull::forced_import(db, &format!("{name}_usd"), v, indexes))
.transpose()?;
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
{
// Compute sats
self.sats
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
// Compute dollars from bitcoin and price (if enabled)
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
let height_to_bitcoin = &self.bitcoin.height;
let height_to_price_close = &price.usd.split.close.height;
dollars.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_price_close,
exit,
)
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,107 @@
//! Value type for Last pattern from Height.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedBlockLast, LazyBlockLast, SatsToBitcoin},
price,
traits::ComputeFromBitcoin,
};
#[derive(Clone, Traversable)]
pub struct ValueBlockLast {
pub sats: ComputedBlockLast<Sats>,
pub bitcoin: LazyBlockLast<Bitcoin, Sats>,
pub dollars: Option<ComputedBlockLast<Dollars>>,
}
const VERSION: Version = Version::ZERO;
impl ValueBlockLast {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedBlockLast::forced_import(db, name, v, indexes)?;
let bitcoin = LazyBlockLast::from_computed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats,
);
let dollars = compute_dollars
.then(|| ComputedBlockLast::forced_import(db, &format!("{name}_usd"), v, indexes))
.transpose()?;
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
{
// Compute sats (closure receives &mut height vec)
self.sats
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
self.compute_dollars(indexes, price, starting_indexes, exit)
}
/// Compute derived vecs from existing height data.
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.sats.compute_rest(indexes, starting_indexes, exit)?;
self.compute_dollars(indexes, price, starting_indexes, exit)
}
fn compute_dollars(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
let height_to_bitcoin = &self.bitcoin.height;
let height_to_price_close = &price.usd.split.close.height;
dollars.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_price_close,
exit,
)
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,69 @@
//! Lazy binary value wrapper combining height (with price) + difficultyepoch + date last transforms.
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{BinaryTransform, IterableCloneableVec, UnaryTransform};
use super::{LazyBlockValue, LazyTransformedValueDifficultyEpoch};
use crate::internal::LazyValueDateLast;
use crate::{internal::ValueBlockLast, price};
const VERSION: Version = Version::ZERO;
/// Lazy binary value wrapper with height (using price binary transform) + difficultyepoch + date last transforms.
///
/// Use this when the height-level dollars need a binary transform (e.g., price × sats)
/// rather than a unary transform from existing dollars.
///
/// No merge at this level - denominations (sats, bitcoin, dollars) stay as separate branches.
/// Each inner field has merge which combines indexes within each denomination.
#[derive(Clone, Deref, DerefMut, Traversable)]
pub struct LazyBinaryValueBlockLast {
#[traversable(flatten)]
pub height: LazyBlockValue,
#[traversable(flatten)]
pub difficultyepoch: LazyTransformedValueDifficultyEpoch,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyValueDateLast,
}
impl LazyBinaryValueBlockLast {
pub fn from_block_source<SatsTransform, BitcoinTransform, HeightDollarsTransform, DateDollarsTransform>(
name: &str,
source: &ValueBlockLast,
price: Option<&price::Vecs>,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
HeightDollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
DateDollarsTransform: UnaryTransform<Dollars, Dollars>,
{
let v = version + VERSION;
let price_source = price.map(|p| p.usd.split.close.height.boxed_clone());
let height = LazyBlockValue::from_sources::<SatsTransform, BitcoinTransform, HeightDollarsTransform>(
name,
source.sats.height.boxed_clone(),
price_source,
v,
);
let difficultyepoch = LazyTransformedValueDifficultyEpoch::from_block_source::<
SatsTransform,
BitcoinTransform,
HeightDollarsTransform,
>(name, source, price, v);
let dates = LazyValueDateLast::from_block_source::<SatsTransform, BitcoinTransform, DateDollarsTransform>(
name, source, v,
);
Self { height, difficultyepoch, dates }
}
}

View File

@@ -0,0 +1,56 @@
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{BinaryTransform, IterableBoxedVec, LazyVecFrom1, LazyVecFrom2, UnaryTransform};
use super::LazyDerivedBlockValue;
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyBlockValue {
#[traversable(rename = "sats")]
pub sats: LazyVecFrom1<Height, Sats, Height, Sats>,
#[deref]
#[deref_mut]
pub rest: LazyDerivedBlockValue,
}
impl LazyBlockValue {
pub fn from_sources<SatsTransform, BitcoinTransform, DollarsTransform>(
name: &str,
sats_source: IterableBoxedVec<Height, Sats>,
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
DollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
{
let v = version + VERSION;
let sats = LazyVecFrom1::transformed::<SatsTransform>(name, v, sats_source.clone());
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
&format!("{name}_btc"),
v,
sats_source.clone(),
);
let dollars = price_source.map(|price| {
LazyVecFrom2::transformed::<DollarsTransform>(
&format!("{name}_usd"),
v,
price,
sats_source,
)
});
Self {
sats,
rest: LazyDerivedBlockValue { bitcoin, dollars },
}
}
}

View File

@@ -0,0 +1,97 @@
//! Value type with stored height + lazy dollars for SumCum pattern.
//!
//! Use this when:
//! - Sats height is stored (primary source of truth)
//! - Sats indexes are derived from height
//! - Bitcoin is lazy (transform from sats)
//! - Dollars height is lazy (price × sats), with stored indexes
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Sats, Version};
use vecdb::{Database, Exit, IterableCloneableVec, LazyVecFrom2};
use crate::{
ComputeIndexes, indexes,
internal::{
ClosePriceTimesSats, ComputedBlockSumCum, LazyBlockSumCum, LazyBlockSumCumHeight,
SatsToBitcoin,
},
price,
};
/// Value wrapper with stored sats height + lazy dollars.
///
/// Sats height is stored (computed directly or from stateful loop).
/// Dollars height is lazy (price × sats).
/// Cumulative and dateindex aggregates are stored for both.
#[derive(Clone, Traversable)]
pub struct LazyComputedValueBlockSumCum {
pub sats: ComputedBlockSumCum<Sats>,
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
}
const VERSION: Version = Version::ZERO;
impl LazyComputedValueBlockSumCum {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedBlockSumCum::forced_import(db, name, v, indexes)?;
let bitcoin = LazyBlockSumCum::from_computed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats,
);
let dollars = if let Some(price) = price {
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
v,
price.usd.split.close.height.boxed_clone(),
sats.height.boxed_clone(),
);
Some(LazyBlockSumCumHeight::forced_import(
db,
&format!("{name}_usd"),
v,
indexes,
dollars_height,
)?)
} else {
None
};
Ok(Self {
sats,
bitcoin,
dollars,
})
}
/// Compute rest (derived indexes) from already-computed height.
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.sats.compute_rest(indexes, starting_indexes, exit)?;
if let Some(dollars) = self.dollars.as_mut() {
dollars.derive_from(indexes, starting_indexes, exit)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,39 @@
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
use vecdb::{IterableBoxedVec, LazyVecFrom1, LazyVecFrom2};
use crate::internal::{ClosePriceTimesSats, SatsToBitcoin};
#[derive(Clone, Traversable)]
pub struct LazyDerivedBlockValue {
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
pub dollars: Option<LazyVecFrom2<Height, Dollars, Height, Close<Dollars>, Height, Sats>>,
}
const VERSION: Version = Version::ZERO;
impl LazyDerivedBlockValue {
pub fn from_source(
name: &str,
sats_source: IterableBoxedVec<Height, Sats>,
version: Version,
price_source: Option<IterableBoxedVec<Height, Close<Dollars>>>,
) -> Self {
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
&format!("{name}_btc"),
version + VERSION,
sats_source.clone(),
);
let dollars = price_source.map(|price| {
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
version + VERSION,
price,
sats_source,
)
});
Self { bitcoin, dollars }
}
}

View File

@@ -0,0 +1,112 @@
//! Fully lazy value types for DifficultyEpoch indexing.
//!
//! Two variants exist for different source patterns:
//! - `LazyValueDifficultyEpochFromHeight`: For sources without dollars (computes from price × sats)
//! - `LazyTransformedValueDifficultyEpoch`: For transformed views (e.g., halved supply)
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, DifficultyEpoch, Dollars, Height, Sats, Version};
use vecdb::{BinaryTransform, IterableBoxedVec, IterableCloneableVec, LazyVecFrom1, LazyVecFrom2, UnaryTransform};
use crate::internal::{ClosePriceTimesSats, LazyLast, SatsToBitcoin};
use crate::price;
const VERSION: Version = Version::ZERO;
/// Lazy value type at difficultyepoch level - computed from height sats + price.
///
/// Use this when the source only has height-indexed sats (e.g., ValueHeightDateLast).
/// Dollars are computed via price × sats binary transform.
#[derive(Clone, Traversable)]
pub struct LazyValueDifficultyEpochFromHeight {
pub sats: LazyLast<DifficultyEpoch, Sats, Height, DifficultyEpoch>,
pub bitcoin: LazyVecFrom1<DifficultyEpoch, Bitcoin, DifficultyEpoch, Sats>,
pub dollars: Option<LazyVecFrom2<DifficultyEpoch, Dollars, DifficultyEpoch, Close<Dollars>, DifficultyEpoch, Sats>>,
}
impl LazyValueDifficultyEpochFromHeight {
/// Create from height sats source and difficultyepoch identity.
/// Bitcoin is derived from sats. Dollars are computed from price × sats.
pub fn from_height_source(
name: &str,
height_sats: IterableBoxedVec<Height, Sats>,
difficultyepoch_identity: IterableBoxedVec<DifficultyEpoch, DifficultyEpoch>,
price: Option<&price::Vecs>,
version: Version,
) -> Self {
let v = version + VERSION;
let sats = LazyLast::from_source(name, v, height_sats, difficultyepoch_identity);
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.boxed_clone(),
);
let dollars = price.map(|p| {
LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
v,
p.usd.split.close.difficultyepoch.boxed_clone(),
sats.boxed_clone(),
)
});
Self { sats, bitcoin, dollars }
}
}
/// Lazy value type at difficultyepoch level - transformed from existing difficultyepoch sources.
///
/// Use this when creating transformed views (e.g., halved supply) from sources that
/// already have difficultyepoch aggregations. Applies transforms to the existing aggregations.
#[derive(Clone, Traversable)]
pub struct LazyTransformedValueDifficultyEpoch {
pub sats: LazyVecFrom1<DifficultyEpoch, Sats, DifficultyEpoch, Sats>,
pub bitcoin: LazyVecFrom1<DifficultyEpoch, Bitcoin, DifficultyEpoch, Sats>,
pub dollars: Option<LazyVecFrom2<DifficultyEpoch, Dollars, DifficultyEpoch, Close<Dollars>, DifficultyEpoch, Sats>>,
}
impl LazyTransformedValueDifficultyEpoch {
/// Create transformed difficultyepoch values from a ValueBlockLast source.
/// SatsTransform is applied to the source's difficultyepoch sats.
/// BitcoinTransform converts source sats to bitcoin (should combine sats transform + conversion).
/// Dollars are computed from price × transformed sats.
pub fn from_block_source<SatsTransform, BitcoinTransform, DollarsTransform>(
name: &str,
source: &super::ValueBlockLast,
price: Option<&price::Vecs>,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
BitcoinTransform: UnaryTransform<Sats, Bitcoin>,
DollarsTransform: BinaryTransform<Close<Dollars>, Sats, Dollars>,
{
let v = version + VERSION;
let sats = LazyVecFrom1::transformed::<SatsTransform>(
name,
v,
source.sats.rest.difficultyepoch.boxed_clone(),
);
let bitcoin = LazyVecFrom1::transformed::<BitcoinTransform>(
&format!("{name}_btc"),
v,
source.sats.rest.difficultyepoch.boxed_clone(),
);
let dollars = price.map(|p| {
LazyVecFrom2::transformed::<DollarsTransform>(
&format!("{name}_usd"),
v,
p.usd.split.close.difficultyepoch.boxed_clone(),
source.sats.rest.difficultyepoch.boxed_clone(),
)
});
Self { sats, bitcoin, dollars }
}
}

View File

@@ -0,0 +1,52 @@
//! Fully lazy value type for Height indexing.
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{IterableCloneableVec, LazyVecFrom1, UnaryTransform};
use crate::internal::SatsToBitcoin;
const VERSION: Version = Version::ZERO;
/// Fully lazy value type at height level.
///
/// All fields are lazy transforms from existing sources - no storage.
#[derive(Clone, Traversable)]
pub struct LazyValueBlockHeight {
pub sats: LazyVecFrom1<Height, Sats, Height, Sats>,
pub bitcoin: LazyVecFrom1<Height, Bitcoin, Height, Sats>,
pub dollars: Option<LazyVecFrom1<Height, Dollars, Height, Dollars>>,
}
impl LazyValueBlockHeight {
pub fn from_block_source<SatsTransform, DollarsTransform>(
name: &str,
source: &super::ValueBlockLast,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
DollarsTransform: UnaryTransform<Dollars, Dollars>,
{
let v = version + VERSION;
let sats =
LazyVecFrom1::transformed::<SatsTransform>(name, v, source.sats.height.boxed_clone());
let bitcoin = LazyVecFrom1::transformed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
source.sats.height.boxed_clone(),
);
let dollars = source.dollars.as_ref().map(|d| {
LazyVecFrom1::transformed::<DollarsTransform>(
&format!("{name}_usd"),
v,
d.height.boxed_clone(),
)
});
Self { sats, bitcoin, dollars }
}
}

View File

@@ -0,0 +1,46 @@
//! Lazy value wrapper for ValueBlockLast - all transforms are lazy.
use brk_traversable::Traversable;
use brk_types::{Dollars, Sats, Version};
use derive_more::{Deref, DerefMut};
use vecdb::UnaryTransform;
use super::LazyValueBlockHeight;
use crate::internal::{LazyValueDateLast, SatsToBitcoin, ValueBlockLast};
const VERSION: Version = Version::ZERO;
/// Lazy value wrapper with height + date last transforms from ValueBlockLast.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct LazyValueBlockLast {
#[traversable(flatten)]
pub height: LazyValueBlockHeight,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub dates: LazyValueDateLast,
}
impl LazyValueBlockLast {
pub fn from_block_source<SatsTransform, DollarsTransform>(
name: &str,
source: &ValueBlockLast,
version: Version,
) -> Self
where
SatsTransform: UnaryTransform<Sats, Sats>,
DollarsTransform: UnaryTransform<Dollars, Dollars>,
{
let v = version + VERSION;
let height =
LazyValueBlockHeight::from_block_source::<SatsTransform, DollarsTransform>(name, source, v);
let dates = LazyValueDateLast::from_block_source::<SatsTransform, SatsToBitcoin, DollarsTransform>(
name, source, v,
);
Self { height, dates }
}
}

View File

@@ -0,0 +1,110 @@
//! Value type with lazy binary height + stored derived SumCum.
//!
//! Use this when the height-level sats is a lazy binary transform (e.g., mask × source).
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Close, Dollars, Height, Sats, Version};
use schemars::JsonSchema;
use vecdb::{
BinaryTransform, Database, Exit, IterableBoxedVec, IterableCloneableVec, LazyVecFrom2,
};
use crate::{
ComputeIndexes, indexes,
internal::{
ClosePriceTimesSats, ComputedVecValue, LazyBlockSumCum, LazyBlockSumCumHeight,
SatsToBitcoin,
},
price,
};
/// Value wrapper with lazy binary height + stored derived SumCum.
///
/// Sats height is a lazy binary transform (e.g., mask × source).
/// Dollars height is also lazy (price × sats).
/// Cumulative and dateindex are stored.
#[derive(Clone, Traversable)]
pub struct LazyValueBlockSumCum<S1T, S2T>
where
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub sats: LazyBlockSumCumHeight<Sats, S1T, S2T>,
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
pub dollars: Option<LazyBlockSumCumHeight<Dollars, Close<Dollars>, Sats>>,
}
const VERSION: Version = Version::ZERO;
impl<S1T, S2T> LazyValueBlockSumCum<S1T, S2T>
where
S1T: ComputedVecValue + JsonSchema,
S2T: ComputedVecValue + JsonSchema,
{
pub fn forced_import<F>(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
source1: IterableBoxedVec<Height, S1T>,
source2: IterableBoxedVec<Height, S2T>,
price: Option<&price::Vecs>,
) -> Result<Self>
where
F: BinaryTransform<S1T, S2T, Sats>,
{
let v = version + VERSION;
let sats_height = LazyVecFrom2::transformed::<F>(name, v, source1, source2);
let sats = LazyBlockSumCumHeight::forced_import(db, name, v, indexes, sats_height)?;
let bitcoin = LazyBlockSumCum::from_derived::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats.rest,
);
let dollars = if let Some(price) = price {
let dollars_height = LazyVecFrom2::transformed::<ClosePriceTimesSats>(
&format!("{name}_usd"),
v,
price.usd.split.close.height.boxed_clone(),
sats.height.boxed_clone(),
);
Some(LazyBlockSumCumHeight::forced_import(
db,
&format!("{name}_usd"),
v,
indexes,
dollars_height,
)?)
} else {
None
};
Ok(Self {
sats,
bitcoin,
dollars,
})
}
/// Derive aggregates from the lazy sats height source.
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.sats.derive_from(indexes, starting_indexes, exit)?;
if let Some(dollars) = self.dollars.as_mut() {
dollars.derive_from(indexes, starting_indexes, exit)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,27 @@
mod binary;
mod full;
mod last;
mod lazy_block_value;
mod lazy_binary_last;
mod lazy_computed_sum_cum;
mod lazy_derived;
mod lazy_difficultyepoch;
mod lazy_height;
mod lazy_last;
mod lazy_sum_cum;
mod sum;
mod sum_cum;
pub use binary::*;
pub use full::*;
pub use last::*;
pub use lazy_block_value::*;
pub use lazy_binary_last::*;
pub use lazy_computed_sum_cum::*;
pub use lazy_derived::*;
pub use lazy_difficultyepoch::*;
pub use lazy_height::*;
pub use lazy_last::*;
pub use lazy_sum_cum::*;
pub use sum::*;
pub use sum_cum::*;

View File

@@ -0,0 +1,86 @@
//! Value type for Sum pattern from Height.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedBlockSum, LazyBlockSum, SatsToBitcoin},
price,
traits::ComputeFromBitcoin,
};
#[derive(Clone, Traversable)]
pub struct ValueBlockSum {
pub sats: ComputedBlockSum<Sats>,
pub bitcoin: LazyBlockSum<Bitcoin, Sats>,
pub dollars: Option<ComputedBlockSum<Dollars>>,
}
const VERSION: Version = Version::ZERO;
impl ValueBlockSum {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedBlockSum::forced_import(db, name, v, indexes)?;
let bitcoin = LazyBlockSum::from_computed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats,
);
let dollars = compute_dollars
.then(|| ComputedBlockSum::forced_import(db, &format!("{name}_usd"), v, indexes))
.transpose()?;
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
{
// Compute sats (closure receives &mut height vec)
self.sats
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
// Compute dollars from bitcoin and price (if enabled)
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
let height_to_bitcoin = &self.bitcoin.height;
let height_to_price_close = &price.usd.split.close.height;
dollars.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_price_close,
exit,
)
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,125 @@
//! Value type for SumCum pattern from Height.
use brk_error::Result;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Dollars, Height, Sats, Version};
use vecdb::{Database, EagerVec, Exit, IterableCloneableVec, PcoVec};
use crate::{
ComputeIndexes, indexes,
internal::{ComputedBlockSumCum, LazyBlockSumCum, SatsToBitcoin},
price,
traits::ComputeFromBitcoin,
};
use vecdb::IterableVec;
#[derive(Clone, Traversable)]
pub struct ValueBlockSumCum {
pub sats: ComputedBlockSumCum<Sats>,
pub bitcoin: LazyBlockSumCum<Bitcoin, Sats>,
pub dollars: Option<ComputedBlockSumCum<Dollars>>,
}
const VERSION: Version = Version::ZERO;
impl ValueBlockSumCum {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
compute_dollars: bool,
) -> Result<Self> {
let v = version + VERSION;
let sats = ComputedBlockSumCum::forced_import(db, name, v, indexes)?;
let bitcoin = LazyBlockSumCum::from_computed::<SatsToBitcoin>(
&format!("{name}_btc"),
v,
sats.height.boxed_clone(),
&sats,
);
let dollars = compute_dollars
.then(|| ComputedBlockSumCum::forced_import(db, &format!("{name}_usd"), v, indexes))
.transpose()?;
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn compute_all<F>(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
mut compute: F,
) -> Result<()>
where
F: FnMut(&mut EagerVec<PcoVec<Height, Sats>>) -> Result<()>,
{
// Compute sats (closure receives &mut height vec)
self.sats
.compute_all(indexes, starting_indexes, exit, |v| compute(v))?;
self.compute_dollars(indexes, price, starting_indexes, exit)
}
/// Derive from an external height source (e.g., a LazyVec).
pub fn derive_from(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
source: &impl IterableVec<Height, Sats>,
exit: &Exit,
) -> Result<()> {
// Derive sats from source
self.sats
.derive_from(indexes, starting_indexes, source, exit)?;
self.compute_dollars(indexes, price, starting_indexes, exit)
}
/// Compute rest (derived indexes) from already-computed height.
pub fn compute_rest(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.sats.compute_rest(indexes, starting_indexes, exit)?;
self.compute_dollars(indexes, price, starting_indexes, exit)
}
fn compute_dollars(
&mut self,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
// Compute dollars from bitcoin and price (if enabled)
if let (Some(dollars), Some(price)) = (self.dollars.as_mut(), price) {
let height_to_bitcoin = &self.bitcoin.height;
let height_to_price_close = &price.usd.split.close.height;
dollars.compute_all(indexes, starting_indexes, exit, |v| {
v.compute_from_bitcoin(
starting_indexes.height,
height_to_bitcoin,
height_to_price_close,
exit,
)
})?;
}
Ok(())
}
}

View File

@@ -0,0 +1,9 @@
mod date;
mod derived_height;
mod height;
mod tx;
pub use date::*;
pub use derived_height::*;
pub use height::*;
pub use tx::*;

View File

@@ -0,0 +1,79 @@
//! Value type for Full pattern from TxIndex.
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{Bitcoin, Sats, TxIndex, Version};
use vecdb::{CollectableVec, Database, Exit, IterableCloneableVec};
use crate::{
ComputeIndexes, indexes,
internal::{DerivedTxFull, ValueDollarsTxFull, LazyDerivedTxFull, SatsToBitcoin},
price,
};
#[derive(Clone, Traversable)]
pub struct ValueDerivedTxFull {
pub sats: DerivedTxFull<Sats>,
pub bitcoin: LazyDerivedTxFull<Bitcoin, Sats>,
pub dollars: Option<ValueDollarsTxFull>,
}
const VERSION: Version = Version::ZERO;
impl ValueDerivedTxFull {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
indexer: &Indexer,
price: Option<&price::Vecs>,
sats_txindex: &impl IterableCloneableVec<TxIndex, Sats>,
) -> Result<Self> {
let v = version + VERSION;
let sats = DerivedTxFull::forced_import(db, name, v, indexes)?;
let bitcoin =
LazyDerivedTxFull::from_computed::<SatsToBitcoin>(&format!("{name}_btc"), v, &sats);
let dollars = price
.map(|price| {
ValueDollarsTxFull::forced_import(
db,
&format!("{name}_usd"),
v,
indexes,
sats_txindex.boxed_clone(),
indexer.vecs.transactions.height.boxed_clone(),
price.usd.split.close.height.boxed_clone(),
)
})
.transpose()?;
Ok(Self {
sats,
bitcoin,
dollars,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
txindex_source: &impl CollectableVec<TxIndex, Sats>,
exit: &Exit,
) -> Result<()> {
self.sats
.derive_from(indexer, indexes, starting_indexes, txindex_source, exit)?;
if let Some(dollars) = self.dollars.as_mut() {
dollars.derive_from(indexer, indexes, starting_indexes, exit)?;
}
Ok(())
}
}

View File

@@ -0,0 +1,136 @@
//! Dollars from TxIndex with lazy txindex and eager aggregates.
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, Close, DateIndex, DifficultyEpoch, Dollars, Height, Sats, TxIndex, Version,
};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, Exit, IterableBoxedVec, IterableCloneableVec, LazyVecFrom3};
use crate::{
ComputeIndexes, indexes,
internal::{LazyPeriodsFull, Full, LazyFull, Stats},
};
/// Lazy dollars at TxIndex: `sats * price[height]`
pub type LazyDollarsTxIndex =
LazyVecFrom3<TxIndex, Dollars, TxIndex, Sats, TxIndex, Height, Height, Close<Dollars>>;
/// Dollars with lazy txindex field and eager height/dateindex aggregates.
#[derive(Clone, Deref, DerefMut, Traversable)]
#[traversable(merge)]
pub struct ValueDollarsTxFull {
#[traversable(skip)]
pub txindex: LazyDollarsTxIndex,
pub height: Full<Height, Dollars>,
pub difficultyepoch: LazyFull<DifficultyEpoch, Dollars, Height, DifficultyEpoch>,
pub dateindex: Stats<DateIndex, Dollars>,
#[deref]
#[deref_mut]
pub dates: LazyPeriodsFull<Dollars>,
}
const VERSION: Version = Version::ZERO;
impl ValueDollarsTxFull {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
sats_txindex: IterableBoxedVec<TxIndex, Sats>,
txindex_to_height: IterableBoxedVec<TxIndex, Height>,
height_to_price: IterableBoxedVec<Height, Close<Dollars>>,
) -> Result<Self> {
let v = version + VERSION;
let txindex =
create_lazy_txindex(name, v, sats_txindex, txindex_to_height, height_to_price);
let height = Full::forced_import(db, name, v)?;
let dateindex = Stats::forced_import(db, name, v)?;
let difficultyepoch =
LazyFull::<DifficultyEpoch, Dollars, Height, DifficultyEpoch>::from_stats_aggregate(
name,
v,
height.distribution.average.0.boxed_clone(),
height.distribution.minmax.min.0.boxed_clone(),
height.distribution.minmax.max.0.boxed_clone(),
height.sum_cum.sum.0.boxed_clone(),
height.sum_cum.cumulative.0.boxed_clone(),
indexes.difficultyepoch.identity.boxed_clone(),
);
let dates = LazyPeriodsFull::from_sources(
name,
v,
dateindex.average.0.boxed_clone(),
dateindex.minmax.min.0.boxed_clone(),
dateindex.minmax.max.0.boxed_clone(),
dateindex.sum_cum.sum.0.boxed_clone(),
dateindex.sum_cum.cumulative.0.boxed_clone(),
indexes,
);
Ok(Self {
txindex,
height,
difficultyepoch,
dateindex,
dates,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.height.compute(
starting_indexes.height,
&self.txindex,
&indexer.vecs.transactions.first_txindex,
&indexes.height.txindex_count,
exit,
)?;
self.dateindex.compute(
starting_indexes.dateindex,
&self.height.distribution.average.0,
&indexes.dateindex.first_height,
&indexes.dateindex.height_count,
exit,
)?;
Ok(())
}
}
fn create_lazy_txindex(
name: &str,
version: Version,
sats_txindex: IterableBoxedVec<TxIndex, Sats>,
txindex_to_height: IterableBoxedVec<TxIndex, Height>,
height_to_price: IterableBoxedVec<Height, Close<Dollars>>,
) -> LazyDollarsTxIndex {
LazyVecFrom3::init(
&format!("{name}_txindex"),
version,
sats_txindex,
txindex_to_height,
height_to_price,
|txindex, sats_iter, height_iter, price_iter| {
sats_iter.get(txindex).and_then(|sats| {
height_iter.get(txindex).and_then(|height| {
price_iter
.get(height)
.map(|close| *close * Bitcoin::from(sats))
})
})
},
)
}

View File

@@ -0,0 +1,55 @@
//! ValueTxFull - eager txindex Sats source + ValueDerivedTxFull (sats/bitcoin/dollars).
use brk_error::Result;
use brk_indexer::Indexer;
use brk_traversable::Traversable;
use brk_types::{Sats, TxIndex, Version};
use derive_more::{Deref, DerefMut};
use vecdb::{Database, EagerVec, Exit, ImportableVec, PcoVec};
use crate::{ComputeIndexes, indexes, price};
use super::ValueDerivedTxFull;
const VERSION: Version = Version::ZERO;
#[derive(Clone, Deref, DerefMut, Traversable)]
pub struct ValueTxFull {
#[traversable(rename = "txindex")]
pub base: EagerVec<PcoVec<TxIndex, Sats>>,
#[deref]
#[deref_mut]
#[traversable(flatten)]
pub indexes: ValueDerivedTxFull,
}
impl ValueTxFull {
pub fn forced_import(
db: &Database,
name: &str,
version: Version,
indexes: &indexes::Vecs,
indexer: &Indexer,
price: Option<&price::Vecs>,
) -> Result<Self> {
let v = version + VERSION;
let txindex = EagerVec::forced_import(db, name, v)?;
let derived =
ValueDerivedTxFull::forced_import(db, name, v, indexes, indexer, price, &txindex)?;
Ok(Self {
base: txindex,
indexes: derived,
})
}
pub fn derive_from(
&mut self,
indexer: &Indexer,
indexes: &indexes::Vecs,
starting_indexes: &ComputeIndexes,
exit: &Exit,
) -> Result<()> {
self.indexes
.derive_from(indexer, indexes, starting_indexes, &self.base, exit)
}
}

Some files were not shown because too many files have changed in this diff Show More