use crate::api::ElementConversion;
use crate::api::FloatDType;
use crate::api::backend::Backend;
use crate::api::Tensor;
use super::l2_norm;
pub fn cosine_similarity<B: Backend, const D: usize>(
x1: Tensor<B, D>,
x2: Tensor<B, D>,
dim: i32,
eps: Option<B::FloatElem>,
) -> Tensor<B, D> {
let eps = eps.map(|value| value.elem::<f64>()).unwrap_or_else(|| {
x1
.dtype()
.finfo()
.unwrap_or(FloatDType::F32.finfo())
.min_positive
});
let dim_idx = if dim < 0 { D as i32 + dim } else { dim };
assert!((0..D as i32).contains(&dim_idx), "Cosine Similarity dimension is out of bounds");
let dim_idx = dim_idx as usize;
let norm_x1 = l2_norm(x1.clone(), dim_idx).clamp_min(eps);
let norm_x2 = l2_norm(x2.clone(), dim_idx).clamp_min(eps);
((x1 / norm_x1) * (x2 / norm_x2)).sum_dim(dim_idx)
}