helena 0.1.0

Core types and component interfaces for helena, a latent data-to-waveform generation platform.
Documentation
use crate::latent::{Continuous, FrameSeq, Latent};
use crate::{Error, Result, Tensor};

/// Validate a set of generations as a non-empty collection of equal-shape,
/// non-empty continuous latents and return their payload sequences. The shared
/// trust boundary for latent-space diagnostics.
///
/// Rank-2-ness and finiteness are now [`FrameSeq`] invariants, so this check
/// shrinks to what the *set* must prove: at least one sample, a non-empty
/// payload, and one shared `[frames, dim]` shape. The old "got tokens" rejection
/// is gone — a `Latent<Continuous>` cannot hold tokens, so the kind mismatch is
/// unrepresentable rather than validated.
pub(super) fn continuous_set(samples: &[Latent<Continuous>]) -> Result<Vec<&FrameSeq>> {
    let Some(first) = samples.first() else {
        return Err(Error::validation("no samples to measure"));
    };
    let expected = first.repr();
    if expected.values().is_empty() {
        return Err(Error::validation("samples must have at least one element"));
    }

    let mut seqs = Vec::with_capacity(samples.len());
    for sample in samples {
        let seq = sample.repr();
        if !same_shape(seq, expected) {
            return Err(Error::validation(format!(
                "all samples must share a shape; expected {:?}, got {:?}",
                shape(expected),
                shape(seq)
            )));
        }
        seqs.push(seq);
    }
    Ok(seqs)
}

/// The `[frames, dim]` shape of a sequence, for reporting.
pub(super) fn shape(seq: &FrameSeq) -> [usize; 2] {
    [seq.frames(), seq.dim()]
}

/// Whether two sequences share both frame count and width.
fn same_shape(a: &FrameSeq, b: &FrameSeq) -> bool {
    a.frames() == b.frames() && a.dim() == b.dim()
}

/// Mean over elements of the population variance across `seqs`.
pub(super) fn mean_elementwise_variance(seqs: &[&FrameSeq]) -> f64 {
    let n = seqs.len() as f64;
    let len = seqs[0].values().len();
    let mut total = 0.0f64;
    for j in 0..len {
        let mean = seqs.iter().map(|t| t.values()[j] as f64).sum::<f64>() / n;
        total += seqs
            .iter()
            .map(|t| {
                let d = t.values()[j] as f64 - mean;
                d * d
            })
            .sum::<f64>()
            / n;
    }
    total / len as f64
}

/// Mean squared error between two tensors, the shared trust boundary for the
/// clean-target loss curve. Validated equal-shape, non-empty, and finite so a
/// diverged head surfaces as an error rather than a `NaN` curve.
///
/// This stays on the raw [`Tensor`] carrier: the clean-target loss is measured
/// on the diffusion module's velocity/`x0` tensors, which are not
/// finite-by-construction the way a [`FrameSeq`] latent is, so the finiteness
/// check remains load-bearing here.
pub(super) fn mean_squared_error(a: &Tensor, b: &Tensor) -> Result<f64> {
    if a.shape() != b.shape() {
        return Err(Error::validation(format!(
            "loss operands must share a shape; got {:?} and {:?}",
            a.shape(),
            b.shape()
        )));
    }
    if a.is_empty() {
        return Err(Error::validation(
            "loss operands must have at least one element",
        ));
    }
    let mut total = 0.0f64;
    for (&x, &y) in a.data().iter().zip(b.data()) {
        if !x.is_finite() || !y.is_finite() {
            return Err(Error::validation(format!(
                "loss operands must be finite; found {x} and {y}"
            )));
        }
        let d = x as f64 - y as f64;
        total += d * d;
    }
    Ok(total / a.len() as f64)
}

/// Euclidean distance between two equal-shape sequences, in `f64` for stability.
pub(super) fn l2_distance(a: &FrameSeq, b: &FrameSeq) -> f64 {
    a.values()
        .iter()
        .zip(b.values())
        .map(|(&x, &y)| {
            let d = x as f64 - y as f64;
            d * d
        })
        .sum::<f64>()
        .sqrt()
}

/// Element-wise mean sequence over an equal-shape, non-empty set.
pub(super) fn elementwise_mean(seqs: &[&FrameSeq]) -> FrameSeq {
    let n = seqs.len() as f64;
    let len = seqs[0].values().len();
    let mean: Vec<f32> = (0..len)
        .map(|j| (seqs.iter().map(|t| t.values()[j] as f64).sum::<f64>() / n) as f32)
        .collect();
    FrameSeq::new(seqs[0].frames(), seqs[0].dim(), mean).expect("mean preserves the common shape")
}