use crate::error::{FocrError, FocrResult};
use super::nn;
use super::tensor::Mat;
use super::vision_sam::{self, Conv, LayerNormP, Linear};
use super::weights::Weights;
pub const EMBED_DIM: usize = 768;
pub const DEPTH: usize = 12;
pub const NUM_HEADS: usize = 12;
pub const HEAD_DIM: usize = 64;
pub const PATCH: usize = 16;
pub const IMG_SIDE: usize = 512;
pub const GRID: usize = IMG_SIDE / PATCH;
pub const TOKENS: usize = GRID * GRID;
pub const INTERMEDIATE: usize = 3072;
const LN_EPS: f32 = 1e-6;
const ATTN_SCALE: f32 = 0.125;
#[derive(Debug, Clone)]
pub struct SiglipBlockP {
pub ln1: LayerNormP,
pub q: Linear,
pub k: Linear,
pub v: Linear,
pub out: Linear,
pub ln2: LayerNormP,
pub fc1: Linear,
pub fc2: Linear,
}
#[derive(Debug, Clone)]
pub struct SiglipWeights {
pub patch_embed: Conv,
pub pos_embed: Vec<f32>,
pub blocks: Vec<SiglipBlockP>,
pub post_ln: LayerNormP,
}
pub fn siglip_weights_from(weights: &Weights, prefix: &str) -> FocrResult<SiglipWeights> {
let statics = siglip_statics_from(weights, prefix)?;
let mut blocks = Vec::with_capacity(DEPTH);
for i in 0..DEPTH {
blocks.push(siglip_block_from(weights, prefix, i)?);
}
Ok(SiglipWeights {
patch_embed: statics.patch_embed,
pos_embed: statics.pos_embed,
blocks,
post_ln: statics.post_ln,
})
}
pub(crate) struct SiglipStatics {
pub patch_embed: Conv,
pub pos_embed: Vec<f32>,
pub post_ln: LayerNormP,
}
pub(crate) fn siglip_statics_from(weights: &Weights, prefix: &str) -> FocrResult<SiglipStatics> {
let p = prefix;
let pe_w = weights.vec(&format!("{p}.embeddings.patch_embedding.weight"))?;
let pe_b = weights.vec(&format!("{p}.embeddings.patch_embedding.bias"))?;
if pe_w.len() != EMBED_DIM * 3 * PATCH * PATCH || pe_b.len() != EMBED_DIM {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip patch_embedding: weight/bias len ({}, {}) != ([{EMBED_DIM},3,{PATCH},{PATCH}], {EMBED_DIM})",
pe_w.len(),
pe_b.len()
)));
}
let patch_embed = Conv {
w: pe_w,
b: Some(pe_b),
out_ch: EMBED_DIM,
in_ch: 3,
kh: PATCH,
kw: PATCH,
};
let pos_embed = weights.vec(&format!("{p}.embeddings.position_embedding.weight"))?;
if pos_embed.len() != TOKENS * EMBED_DIM {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip position_embedding: len {} != [{TOKENS},{EMBED_DIM}]",
pos_embed.len()
)));
}
Ok(SiglipStatics {
patch_embed,
pos_embed,
post_ln: block_ln(weights, &format!("{p}.post_layernorm"))?,
})
}
fn block_linear(weights: &Weights, name: &str, out: usize, in_: usize) -> FocrResult<Linear> {
let w = weights.vec(&format!("{name}.weight"))?;
let b = weights.vec(&format!("{name}.bias"))?;
if w.len() != out * in_ || b.len() != out {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip {name}: weight/bias len ({}, {}) != ([{out},{in_}], {out})",
w.len(),
b.len()
)));
}
Linear::from_row_major(&w, b, out, in_)
}
fn block_ln(weights: &Weights, name: &str) -> FocrResult<LayerNormP> {
let w = weights.vec(&format!("{name}.weight"))?;
let b = weights.vec(&format!("{name}.bias"))?;
if w.len() != EMBED_DIM || b.len() != EMBED_DIM {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip {name}: affine len ({}, {}) != {EMBED_DIM}",
w.len(),
b.len()
)));
}
Ok(LayerNormP { w, b })
}
pub(crate) fn siglip_block_from(
weights: &Weights,
prefix: &str,
i: usize,
) -> FocrResult<SiglipBlockP> {
let b = format!("{prefix}.encoder.layers.{i}");
Ok(SiglipBlockP {
ln1: block_ln(weights, &format!("{b}.layer_norm1"))?,
q: block_linear(
weights,
&format!("{b}.self_attn.q_proj"),
EMBED_DIM,
EMBED_DIM,
)?,
k: block_linear(
weights,
&format!("{b}.self_attn.k_proj"),
EMBED_DIM,
EMBED_DIM,
)?,
v: block_linear(
weights,
&format!("{b}.self_attn.v_proj"),
EMBED_DIM,
EMBED_DIM,
)?,
out: block_linear(
weights,
&format!("{b}.self_attn.out_proj"),
EMBED_DIM,
EMBED_DIM,
)?,
ln2: block_ln(weights, &format!("{b}.layer_norm2"))?,
fc1: block_linear(weights, &format!("{b}.mlp.fc1"), INTERMEDIATE, EMBED_DIM)?,
fc2: block_linear(weights, &format!("{b}.mlp.fc2"), EMBED_DIM, INTERMEDIATE)?,
})
}
pub fn forward_frame(w: &SiglipWeights, pixels: &[f32]) -> FocrResult<Mat> {
if pixels.len() != 3 * IMG_SIDE * IMG_SIDE {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip forward: pixel buffer len {} != 3*{IMG_SIDE}*{IMG_SIDE}",
pixels.len()
)));
}
let mut x = embed_frame(w, pixels)?;
for blk in &w.blocks {
encoder_block(blk, &mut x)?;
}
nn::layer_norm(&x, Some(&w.post_ln.w), Some(&w.post_ln.b), LN_EPS)
}
pub(crate) fn embed_frame(w: &SiglipWeights, pixels: &[f32]) -> FocrResult<Mat> {
embed_frame_parts(&w.patch_embed, &w.pos_embed, pixels)
}
pub(crate) fn embed_frame_parts(
patch_embed: &Conv,
pos_embed: &[f32],
pixels: &[f32],
) -> FocrResult<Mat> {
let nchw = vision_sam::conv_apply(patch_embed, pixels, IMG_SIDE, IMG_SIDE, 0, PATCH)?;
let mut x = vision_sam::nchw_to_nhwc_rows(&nchw, EMBED_DIM, GRID, GRID);
let bucket = |i: usize| i.saturating_sub(1);
for r in 0..GRID {
for c in 0..GRID {
let t = r * GRID + c;
let pos_id = bucket(r) * GRID + bucket(c);
let row = x.row_mut(t);
let pos = &pos_embed[pos_id * EMBED_DIM..(pos_id + 1) * EMBED_DIM];
for (v, p) in row.iter_mut().zip(pos) {
*v += p;
}
}
}
Ok(x)
}
pub(crate) fn encoder_block(blk: &SiglipBlockP, x: &mut Mat) -> FocrResult<()> {
let h = nn::layer_norm(x, Some(&blk.ln1.w), Some(&blk.ln1.b), LN_EPS)?;
let attn = self_attention(blk, &h)?;
add_assign(x, &attn)?;
let h2 = nn::layer_norm(x, Some(&blk.ln2.w), Some(&blk.ln2.b), LN_EPS)?;
let mut m = blk.fc1.apply(&h2)?;
nn::gelu_tanh(&mut m);
let m = blk.fc2.apply(&m)?;
add_assign(x, &m)
}
pub fn forward_frames(w: &SiglipWeights, pixels: &[f32], n_frames: usize) -> FocrResult<Vec<Mat>> {
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
if n_frames == 0 || pixels.len() != n_frames * frame_len {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip forward_frames: buffer len {} != n_frames {n_frames} * {frame_len}",
pixels.len()
)));
}
let mut out = Vec::with_capacity(n_frames);
for f in 0..n_frames {
out.push(forward_frame(
w,
&pixels[f * frame_len..(f + 1) * frame_len],
)?);
}
Ok(out)
}
pub fn forward_frames_streamed(
weights: &Weights,
prefix: &str,
pixels: &[f32],
n_frames: usize,
) -> FocrResult<Vec<Mat>> {
forward_frames_streamed_depth(weights, prefix, pixels, n_frames, DEPTH)
}
fn forward_frames_streamed_depth(
weights: &Weights,
prefix: &str,
pixels: &[f32],
n_frames: usize,
depth: usize,
) -> FocrResult<Vec<Mat>> {
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
if n_frames == 0 || pixels.len() != n_frames * frame_len {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip forward_frames_streamed: buffer len {} != n_frames {n_frames} * {frame_len}",
pixels.len()
)));
}
let statics = siglip_statics_from(weights, prefix)?;
let mut xs = Vec::with_capacity(n_frames);
for f in 0..n_frames {
xs.push(embed_frame_parts(
&statics.patch_embed,
&statics.pos_embed,
&pixels[f * frame_len..(f + 1) * frame_len],
)?);
}
for i in 0..depth {
let blk = siglip_block_from(weights, prefix, i)?;
for x in &mut xs {
encoder_block(&blk, x)?;
}
}
xs.iter()
.map(|x| {
nn::layer_norm(
x,
Some(&statics.post_ln.w),
Some(&statics.post_ln.b),
LN_EPS,
)
})
.collect()
}
fn self_attention(blk: &SiglipBlockP, x: &Mat) -> FocrResult<Mat> {
let seq = x.rows;
let q = blk.q.apply(x)?;
let k = blk.k.apply(x)?;
let v = blk.v.apply(x)?;
let head_span = seq * HEAD_DIM;
let mut qf = vec![0.0f32; NUM_HEADS * head_span];
let mut kf = vec![0.0f32; NUM_HEADS * head_span];
let mut vf = vec![0.0f32; NUM_HEADS * head_span];
for s in 0..seq {
let (qr, kr, vr) = (q.row(s), k.row(s), v.row(s));
for h in 0..NUM_HEADS {
let src = h * HEAD_DIM;
let dst = h * head_span + s * HEAD_DIM;
qf[dst..dst + HEAD_DIM].copy_from_slice(&qr[src..src + HEAD_DIM]);
kf[dst..dst + HEAD_DIM].copy_from_slice(&kr[src..src + HEAD_DIM]);
vf[dst..dst + HEAD_DIM].copy_from_slice(&vr[src..src + HEAD_DIM]);
}
}
let ctx = nn::sdpa(
&qf, &kf, &vf, NUM_HEADS, seq, seq, HEAD_DIM, HEAD_DIM, ATTN_SCALE, false,
);
let mut merged = Mat::zeros(seq, EMBED_DIM);
for h in 0..NUM_HEADS {
for s in 0..seq {
let src = h * head_span + s * HEAD_DIM;
let dst_row = merged.row_mut(s);
dst_row[h * HEAD_DIM..(h + 1) * HEAD_DIM].copy_from_slice(&ctx[src..src + HEAD_DIM]);
}
}
blk.out.apply(&merged)
}
fn self_attention_batched(
blk: &SiglipBlockP,
x: &Mat,
frames: usize,
seq: usize,
) -> FocrResult<Mat> {
let q = blk.q.apply(x)?;
let k = blk.k.apply(x)?;
let v = blk.v.apply(x)?;
let head_span = seq * HEAD_DIM;
let mut qf = vec![0.0f32; frames * NUM_HEADS * head_span];
let mut kf = vec![0.0f32; frames * NUM_HEADS * head_span];
let mut vf = vec![0.0f32; frames * NUM_HEADS * head_span];
for f in 0..frames {
for s in 0..seq {
let row = f * seq + s;
let (qr, kr, vr) = (q.row(row), k.row(row), v.row(row));
for h in 0..NUM_HEADS {
let src = h * HEAD_DIM;
let dst = (f * NUM_HEADS + h) * head_span + s * HEAD_DIM;
qf[dst..dst + HEAD_DIM].copy_from_slice(&qr[src..src + HEAD_DIM]);
kf[dst..dst + HEAD_DIM].copy_from_slice(&kr[src..src + HEAD_DIM]);
vf[dst..dst + HEAD_DIM].copy_from_slice(&vr[src..src + HEAD_DIM]);
}
}
}
let ctx = nn::sdpa(
&qf,
&kf,
&vf,
frames * NUM_HEADS,
seq,
seq,
HEAD_DIM,
HEAD_DIM,
ATTN_SCALE,
false,
);
let mut merged = Mat::zeros(frames * seq, EMBED_DIM);
for f in 0..frames {
for h in 0..NUM_HEADS {
for s in 0..seq {
let src = (f * NUM_HEADS + h) * head_span + s * HEAD_DIM;
let dst_row = merged.row_mut(f * seq + s);
dst_row[h * HEAD_DIM..(h + 1) * HEAD_DIM]
.copy_from_slice(&ctx[src..src + HEAD_DIM]);
}
}
}
blk.out.apply(&merged)
}
fn encoder_block_batched(
blk: &SiglipBlockP,
x: &mut Mat,
frames: usize,
seq: usize,
) -> FocrResult<()> {
let h = nn::layer_norm(x, Some(&blk.ln1.w), Some(&blk.ln1.b), LN_EPS)?;
let attn = self_attention_batched(blk, &h, frames, seq)?;
add_assign(x, &attn)?;
let h2 = nn::layer_norm(x, Some(&blk.ln2.w), Some(&blk.ln2.b), LN_EPS)?;
let mut m = blk.fc1.apply(&h2)?;
nn::gelu_tanh(&mut m);
let m = blk.fc2.apply(&m)?;
add_assign(x, &m)
}
pub fn forward_frames_batched(
w: &SiglipWeights,
pixels: &[f32],
n_frames: usize,
) -> FocrResult<Vec<Mat>> {
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
if n_frames == 0 || pixels.len() != n_frames * frame_len {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip forward_frames_batched: buffer len {} != n_frames {n_frames} * {frame_len}",
pixels.len()
)));
}
let mut x = Mat::zeros(n_frames * TOKENS, EMBED_DIM);
for f in 0..n_frames {
let e = embed_frame(w, &pixels[f * frame_len..(f + 1) * frame_len])?;
x.data[f * TOKENS * EMBED_DIM..(f + 1) * TOKENS * EMBED_DIM].copy_from_slice(&e.data);
}
for blk in &w.blocks {
encoder_block_batched(blk, &mut x, n_frames, TOKENS)?;
}
let post = nn::layer_norm(&x, Some(&w.post_ln.w), Some(&w.post_ln.b), LN_EPS)?;
let mut out = Vec::with_capacity(n_frames);
for f in 0..n_frames {
out.push(Mat::from_vec(
TOKENS,
EMBED_DIM,
post.data[f * TOKENS * EMBED_DIM..(f + 1) * TOKENS * EMBED_DIM].to_vec(),
));
}
Ok(out)
}
fn add_assign(a: &mut Mat, b: &Mat) -> FocrResult<()> {
if a.shape() != b.shape() {
return Err(FocrError::Other(anyhow::anyhow!(
"vision_siglip residual: shape {:?} != {:?}",
a.shape(),
b.shape()
)));
}
for (x, y) in a.data.iter_mut().zip(&b.data) {
*x += y;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn synthetic_weights_depth(depth: usize) -> SiglipWeights {
let wave = |n: usize, f: f32, a: f32| -> Vec<f32> {
(0..n).map(|i| (i as f32 * f).sin() * a).collect()
};
let linear = |out: usize, in_: usize, seed: f32| {
let w = wave(out * in_, 0.13 + seed, 0.02);
Linear::from_row_major(&w, wave(out, 0.7 + seed, 0.01), out, in_)
.expect("synthetic linear shape")
};
let ln = |seed: f32| LayerNormP {
w: (0..EMBED_DIM)
.map(|i| 1.0 + (i as f32 * seed).sin() * 0.05)
.collect(),
b: wave(EMBED_DIM, 0.3 + seed, 0.01),
};
let blocks = (0..depth)
.map(|i| {
let s = i as f32 * 0.01;
SiglipBlockP {
ln1: ln(0.11 + s),
q: linear(EMBED_DIM, EMBED_DIM, s),
k: linear(EMBED_DIM, EMBED_DIM, s + 0.001),
v: linear(EMBED_DIM, EMBED_DIM, s + 0.002),
out: linear(EMBED_DIM, EMBED_DIM, s + 0.003),
ln2: ln(0.17 + s),
fc1: linear(INTERMEDIATE, EMBED_DIM, s + 0.004),
fc2: linear(EMBED_DIM, INTERMEDIATE, s + 0.005),
}
})
.collect();
SiglipWeights {
patch_embed: Conv {
w: wave(EMBED_DIM * 3 * PATCH * PATCH, 0.01, 0.05),
b: Some(wave(EMBED_DIM, 0.5, 0.01)),
out_ch: EMBED_DIM,
in_ch: 3,
kh: PATCH,
kw: PATCH,
},
pos_embed: wave(TOKENS * EMBED_DIM, 0.023, 0.02),
blocks,
post_ln: ln(0.29),
}
}
fn synthetic_weights() -> SiglipWeights {
synthetic_weights_depth(1)
}
fn synthetic_pixels() -> Vec<f32> {
(0..3 * IMG_SIDE * IMG_SIDE)
.map(|i| ((i % 511) as f32 / 255.0) - 1.0)
.collect()
}
#[test]
fn forward_shapes_and_determinism() {
let w = synthetic_weights();
let px = synthetic_pixels();
let a = forward_frame(&w, &px).expect("forward");
assert_eq!((a.rows, a.cols), (TOKENS, EMBED_DIM));
assert!(
a.data.iter().all(|v| v.is_finite()),
"non-finite activation"
);
let b = forward_frame(&w, &px).expect("forward twice");
assert_eq!(a.data, b.data);
}
#[test]
fn pos_embed_moves_the_output() {
let w = synthetic_weights();
let px = synthetic_pixels();
let a = forward_frame(&w, &px).unwrap();
let mut w2 = w.clone();
w2.pos_embed = vec![0.0; TOKENS * EMBED_DIM];
let b = forward_frame(&w2, &px).unwrap();
assert_ne!(a.data, b.data);
}
#[test]
fn attention_is_bidirectional() {
let w = synthetic_weights();
let mut px = synthetic_pixels();
let a = forward_frame(&w, &px).unwrap();
for c in 0..3 {
let plane = (c + 1) * IMG_SIDE * IMG_SIDE;
for v in &mut px[plane - PATCH..plane] {
*v += 0.5;
}
}
let b = forward_frame(&w, &px).unwrap();
let first_a = &a.data[..EMBED_DIM];
let first_b = &b.data[..EMBED_DIM];
assert_ne!(first_a, first_b, "last-patch info did not reach token 0");
}
#[test]
fn forward_frames_matches_per_frame() {
let w = synthetic_weights();
let px = synthetic_pixels();
let mut two = px.clone();
two.extend(px.iter().map(|v| -v));
let outs = forward_frames(&w, &two, 2).unwrap();
assert_eq!(outs.len(), 2);
let single = forward_frame(&w, &px).unwrap();
assert_eq!(outs[0].data, single.data, "frame 0 must equal solo forward");
assert_ne!(outs[1].data, single.data);
}
#[test]
fn error_handling() {
let w = synthetic_weights();
assert!(forward_frame(&w, &[0.0; 100]).is_err());
assert!(forward_frames(&w, &[0.0; 100], 2).is_err());
assert!(forward_frames(&w, &synthetic_pixels(), 0).is_err());
}
#[test]
fn gelu_tanh_reference_values() {
assert_eq!(nn::gelu_tanh_scalar(0.0), 0.0);
let close = |a: f32, b: f32| (a - b).abs() < 1e-6;
assert!(close(nn::gelu_tanh_scalar(1.0), 0.841_192));
assert!(close(nn::gelu_tanh_scalar(-1.0), -0.158_808));
assert!(close(nn::gelu_tanh_scalar(3.0), 2.996_363));
assert!(close(nn::gelu_tanh_scalar(10.0), 10.0));
assert!(close(nn::gelu_tanh_scalar(-10.0), 0.0));
}
#[test]
fn siglip_seams_match_torch_oracle_frame0() {
let Ok(dir) = std::env::var("FOCR_SMOLVLM2_DIR") else {
return;
};
let pv_path = format!("{dir}/smolvlm2_pixel_values.bin");
let h0_path = format!("{dir}/smolvlm2_dbg_vision_hidden_0_frame0.bin");
let h1_path = format!("{dir}/smolvlm2_dbg_vision_hidden_1_frame0.bin");
if !std::path::Path::new(&h0_path).is_file() {
eprintln!("skip-with-SUCCESS: {h0_path} absent (npz→bin dbg extract)");
return;
}
let read_f32 = |p: &str| -> Vec<f32> {
std::fs::read(p)
.expect("oracle blob reads")
.as_chunks::<4>()
.0
.iter()
.map(|c| f32::from_le_bytes(*c))
.collect()
};
let cos = |a: &[f32], b: &[f32]| -> f64 {
let mut dot = 0.0f64;
let (mut na, mut nb) = (0.0f64, 0.0f64);
for (x, y) in a.iter().zip(b) {
let (x, y) = (f64::from(*x), f64::from(*y));
dot += x * y;
na += x * x;
nb += y * y;
}
dot / (na.sqrt() * nb.sqrt())
};
let pv = read_f32(&pv_path);
let frame0 = &pv[..3 * IMG_SIDE * IMG_SIDE];
let weights = Weights::load(std::path::Path::new(&format!("{dir}/model.safetensors")))
.expect("weights load");
let w = siglip_weights_from(&weights, "model.vision_model").expect("hydrate");
let emb = embed_frame(&w, frame0).expect("embed");
let h0 = read_f32(&h0_path);
let c0 = cos(&emb.data, &h0);
eprintln!("[C3 seam] embeddings-out cos={c0:.8}");
let mut x = emb;
encoder_block(&w.blocks[0], &mut x).expect("block 0");
let h1 = read_f32(&h1_path);
let c1 = cos(&x.data, &h1);
eprintln!("[C3 seam] block-0-out cos={c1:.8}");
assert!(c0 >= 0.9999, "embeddings seam diverged: cos={c0:.8}");
assert!(c1 >= 0.9999, "block-0 seam diverged: cos={c1:.8}");
}
#[test]
fn siglip_matches_torch_oracle() {
let Ok(dir) = std::env::var("FOCR_SMOLVLM2_DIR") else {
return;
};
let pv_path = format!("{dir}/smolvlm2_pixel_values.bin");
let want_path = format!("{dir}/smolvlm2_vision_post_ln.bin");
let model_path = format!("{dir}/model.safetensors");
if !std::path::Path::new(&pv_path).is_file() {
eprintln!("skip-with-SUCCESS: {pv_path} absent (run the vision oracle script)");
return;
}
let read_f32 = |p: &str| -> Vec<f32> {
std::fs::read(p)
.expect("oracle blob reads")
.as_chunks::<4>()
.0
.iter()
.map(|c| f32::from_le_bytes(*c))
.collect()
};
let pv = read_f32(&pv_path);
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
let n_frames = pv.len() / frame_len;
assert_eq!(
n_frames * frame_len,
pv.len(),
"pixel_values not [F,3,512,512]"
);
let want = read_f32(&want_path);
assert_eq!(want.len(), n_frames * TOKENS * EMBED_DIM);
let weights = Weights::load(std::path::Path::new(&model_path)).expect("weights load");
let w = siglip_weights_from(&weights, "model.vision_model").expect("hydrate");
let outs = forward_frames(&w, &pv, n_frames).expect("forward");
let mut worst_cos = 1.0f64;
let mut max_abs = 0.0f64;
for (f, ours) in outs.iter().enumerate() {
let oracle = &want[f * TOKENS * EMBED_DIM..(f + 1) * TOKENS * EMBED_DIM];
let mut dot = 0.0f64;
let (mut na, mut nb) = (0.0f64, 0.0f64);
for (a, b) in ours.data.iter().zip(oracle) {
let (a, b) = (f64::from(*a), f64::from(*b));
dot += a * b;
na += a * a;
nb += b * b;
max_abs = max_abs.max((a - b).abs());
}
let cos = dot / (na.sqrt() * nb.sqrt());
worst_cos = worst_cos.min(cos);
}
eprintln!("[C3 parity] frames={n_frames} worst_cos={worst_cos:.8} maxabs={max_abs:.3e}");
assert!(
worst_cos >= 0.9999,
"SigLIP per-frame cosine {worst_cos:.8} < 0.9999"
);
assert!(
max_abs <= 1e-2,
"SigLIP post-LN maxabs {max_abs:.3e} > 1e-2 — investigate before tightening"
);
}
#[test]
fn batched_frames_match_sequential_byte_for_byte() {
let w = synthetic_weights_depth(1);
let frames = 3usize;
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
let pixels: Vec<f32> = (0..frames * frame_len)
.map(|i| ((i % 251) as f32) / 251.0 - 0.5)
.collect();
let sequential = forward_frames(&w, &pixels, frames).expect("sequential");
let batched = forward_frames_batched(&w, &pixels, frames).expect("batched");
assert_eq!(sequential.len(), batched.len());
for (f, (a, b)) in sequential.iter().zip(&batched).enumerate() {
assert_eq!(a.shape(), b.shape(), "frame {f} shape");
for (i, (x, y)) in a.data.iter().zip(&b.data).enumerate() {
assert_eq!(
x.to_bits(),
y.to_bits(),
"frame {f} element {i}: {x} vs {y}"
);
}
}
}
#[test]
fn batched_frames_reject_bad_buffer() {
let w = synthetic_weights_depth(1);
assert!(forward_frames_batched(&w, &[0.0; 7], 1).is_err());
assert!(forward_frames_batched(&w, &[], 0).is_err());
}
#[test]
fn streamed_frames_match_whole_tower_hydration() -> FocrResult<()> {
use crate::native_engine::vision_sam::test_support::synth_values;
use crate::quant::focrq::{FocrqBuilder, WriteDType};
let p = "model.vision_model";
let mut b = FocrqBuilder::new();
{
let mut add = |name: String, shape: Vec<usize>, idx: u64| {
let len: usize = shape.iter().product();
let bytes: Vec<u8> = synth_values(len, idx << 40)
.iter()
.flat_map(|v| v.to_le_bytes())
.collect();
b.add_tensor(name, WriteDType::F32, shape, bytes)
.expect("valid synthetic f32 tensor");
};
add(
format!("{p}.embeddings.patch_embedding.weight"),
vec![EMBED_DIM, 3, PATCH, PATCH],
1,
);
add(
format!("{p}.embeddings.patch_embedding.bias"),
vec![EMBED_DIM],
2,
);
add(
format!("{p}.embeddings.position_embedding.weight"),
vec![TOKENS, EMBED_DIM],
3,
);
add(format!("{p}.post_layernorm.weight"), vec![EMBED_DIM], 4);
add(format!("{p}.post_layernorm.bias"), vec![EMBED_DIM], 5);
let l = format!("{p}.encoder.layers.0");
add(format!("{l}.layer_norm1.weight"), vec![EMBED_DIM], 6);
add(format!("{l}.layer_norm1.bias"), vec![EMBED_DIM], 7);
add(format!("{l}.layer_norm2.weight"), vec![EMBED_DIM], 8);
add(format!("{l}.layer_norm2.bias"), vec![EMBED_DIM], 9);
for (i, proj) in ["q_proj", "k_proj", "v_proj", "out_proj"]
.into_iter()
.enumerate()
{
let i = i as u64;
add(
format!("{l}.self_attn.{proj}.weight"),
vec![EMBED_DIM, EMBED_DIM],
10 + i * 2,
);
add(
format!("{l}.self_attn.{proj}.bias"),
vec![EMBED_DIM],
11 + i * 2,
);
}
add(
format!("{l}.mlp.fc1.weight"),
vec![INTERMEDIATE, EMBED_DIM],
18,
);
add(format!("{l}.mlp.fc1.bias"), vec![INTERMEDIATE], 19);
add(
format!("{l}.mlp.fc2.weight"),
vec![EMBED_DIM, INTERMEDIATE],
20,
);
add(format!("{l}.mlp.fc2.bias"), vec![EMBED_DIM], 21);
}
let weights = Weights::from_bytes(b.build()).expect("synthetic SigLIP parses");
let statics = siglip_statics_from(&weights, p)?;
let retained = SiglipWeights {
patch_embed: statics.patch_embed.clone(),
pos_embed: statics.pos_embed.clone(),
blocks: vec![siglip_block_from(&weights, p, 0)?],
post_ln: LayerNormP {
w: statics.post_ln.w.clone(),
b: statics.post_ln.b.clone(),
},
};
let frames = 2usize;
let frame_len = 3 * IMG_SIDE * IMG_SIDE;
let pixels: Vec<f32> = (0..frames * frame_len)
.map(|i| ((i % 251) as f32) / 251.0 - 0.5)
.collect();
let want = forward_frames(&retained, &pixels, frames)?;
let got = forward_frames_streamed_depth(&weights, p, &pixels, frames, 1)?;
assert_eq!(got.len(), frames);
assert_eq!(want.len(), got.len());
let mut nonzero = 0usize;
for (f, (a, c)) in want.iter().zip(&got).enumerate() {
assert_eq!(a.shape(), c.shape(), "frame {f} shape");
for (i, (x, y)) in a.data.iter().zip(&c.data).enumerate() {
assert_eq!(
x.to_bits(),
y.to_bits(),
"frame {f} element {i}: {x} vs {y}"
);
if *y != 0.0 {
nonzero += 1;
}
}
}
assert!(nonzero > 0, "streamed output is degenerate (all zeros)");
assert_ne!(
got[0].data, got[1].data,
"frames are identical; the inversion is untested"
);
Ok(())
}
}