candding 0.1.0

Pure candle embeddings for Rust with no ONNX: dense, sparse, multi-vector and rerank models today, image models on the roadmap
Documentation
//! The rules every catalog's `CellException`s hold to, read from one entry's own statuses beside its final rows.

use candle_core::DType;

use crate::registry::Backend;
use crate::registry::BackendSupport;
use crate::registry::CellException;
use crate::registry::DtypeBackendSupport;
use crate::registry::DtypeSupport;
use crate::registry::Support;

/// What a run can leave one cell as. A `Verified` cell comes from the derivation alone, and a CUDA cell takes
/// `Untested`, or `Unsupported` where the reason names the run that measured the failure.
const RUN_STATES: [Support; 3] = [Support::Untested, Support::Unsupported, Support::Pending];

const DTYPES: [DType; 3] = [DType::F32, DType::F16, DType::BF16];
const BACKENDS: [Backend; 3] = [Backend::Cpu, Backend::Metal, Backend::Cuda];

fn cuda_may_take(status: Support, reason: &str) -> bool {
  status == Support::Untested || (status == Support::Unsupported && cites_a_run(reason))
}

/// A run cited by its id, as `cuda.yml run 37127370028` is.
fn cites_a_run(reason: &str) -> bool {
  reason
    .split("run ")
    .skip(1)
    .any(|rest| rest.starts_with(|c: char| c.is_ascii_digit()))
}

/// One entry as the rules read it: its model-wide and per-dtype statuses, its exceptions, and its descriptor's rows.
pub(crate) struct Cells<'a> {
  pub id: &'a str,
  pub backends: BackendSupport,
  pub dtypes: DtypeSupport,
  pub accel_only: &'a [DType],
  pub exceptions: &'a [CellException],
  pub rows: DtypeBackendSupport,
}

impl Cells<'_> {
  fn derived(&self, accel_only: &[DType]) -> DtypeBackendSupport {
    DtypeBackendSupport::derive(self.backends, self.dtypes, accel_only)
  }

  /// The first rule an exception breaks, or `None`: each names a catalog dtype and a reason, is alone on its cell,
  /// writes a run state the derivation does not already give, is no processor refusal, and reaches the rows.
  pub(crate) fn exception_violation(&self) -> Option<String> {
    let id = self.id;
    let derived = self.derived(self.accel_only);
    let mut seen = Vec::new();
    for exception in self.exceptions {
      let (dtype, backend, status) = (exception.dtype, exception.backend, exception.status);
      let mut accel_only = self.accel_only.to_vec();
      accel_only.push(dtype);
      let broken = if !DTYPES.contains(&dtype) {
        "names no catalog dtype"
      } else if exception.reason.trim().is_empty() {
        "gives no reason"
      } else if !RUN_STATES.contains(&status) {
        "writes a status no run leaves"
      } else if backend == Backend::Cuda && !cuda_may_take(status, exception.reason) {
        "writes a CUDA cell other than untested or a failure a cited run measured"
      } else if seen.contains(&(dtype, backend)) {
        "shares its cell with another exception"
      } else if derived.row(dtype).get(backend) == status {
        "restates what the derivation already gives"
      } else if derived.with_exceptions(&[*exception]) == self.derived(&accel_only) {
        "is a processor refusal, which accel_only_dtypes states"
      } else if self.rows.row(dtype).get(backend) != status {
        "does not reach the descriptor"
      } else {
        seen.push((dtype, backend));
        continue;
      };
      return Some(format!("{id}: {exception:?} {broken}"));
    }
    None
  }

  /// Every `Verified` cell of the rows that the derivation alone does not give: one only an exception wrote.
  pub(crate) fn verified_by_an_exception(&self) -> Vec<(DType, Backend)> {
    let derived = self.derived(self.accel_only);
    DTYPES
      .into_iter()
      .flat_map(|dtype| BACKENDS.map(|backend| (dtype, backend)))
      .filter(|&(dtype, backend)| {
        self.rows.row(dtype).get(backend) == Support::Verified
          && derived.row(dtype).get(backend) != Support::Verified
      })
      .collect()
  }
}