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
use crate::registry::Support;
use crate::registry::WeightsFormat;
use crate::registry::sparse;
use crate::registry::sparse::SparseComputation;
use crate::registry::sparse::SparseDescriptor;

fn dtype_cells(d: &SparseDescriptor) -> impl Iterator<Item = Support> {
  [
    d.dtype_backends.f32,
    d.dtype_backends.f16,
    d.dtype_backends.bf16,
  ]
  .into_iter()
  .flat_map(|row| [row.cpu, row.metal, row.cuda])
}

#[test]
fn every_registered_sparse_entry_has_already_flipped_past_pending() {
  for d in sparse::all() {
    assert_ne!(d.backends.cpu, Support::Pending, "{}", d.id);
    assert_ne!(d.backends.metal, Support::Pending, "{}", d.id);
    assert_ne!(d.backends.cuda, Support::Pending, "{}", d.id);
    for status in dtype_cells(&d) {
      assert_ne!(status, Support::Pending, "{}", d.id);
    }
  }
}

/// `NotApplicable` must come with `Computed`, no family and `NoWeights`, so an encoder entry cannot spell an unmeasured cell that way.
#[test]
fn not_applicable_status_agrees_with_computation_family_and_weights_on_every_entry() {
  for d in sparse::all() {
    let any_not_applicable = [d.backends.cpu, d.backends.metal, d.backends.cuda]
      .into_iter()
      .chain(dtype_cells(&d))
      .any(|status| status == Support::NotApplicable);

    assert_eq!(
      any_not_applicable,
      d.computation == SparseComputation::Computed,
      "{}: NotApplicable must imply Computed, and vice versa",
      d.id
    );
    assert_eq!(
      any_not_applicable,
      d.family.is_none(),
      "{}: NotApplicable must imply family == None, and vice versa",
      d.id
    );
    assert_eq!(
      any_not_applicable,
      d.weights == WeightsFormat::NoWeights,
      "{}: NotApplicable must imply weights == NoWeights, and vice versa",
      d.id
    );
  }
}