#[test]
fn test_layer_norm_1d_input() {
let layer_norm = LayerNorm::new(4, 1e-5).expect("test");
let input = Tensor::from_vec(vec![4], vec![1.0, 2.0, 3.0, 4.0]).expect("test");
let output = layer_norm.forward(&input).expect("test");
assert_eq!(output.shape(), &[4]);
let mean: f32 = output.data().iter().sum::<f32>() / 4.0;
assert!((mean - 0.0).abs() < 1e-5);
}
#[test]
fn test_layer_norm_3d_input() {
let layer_norm = LayerNorm::new(4, 1e-5).expect("test");
let input =
Tensor::from_vec(vec![2, 3, 4], (0..24).map(|i| i as f32 * 0.1).collect()).expect("test");
let output = layer_norm.forward(&input).expect("test");
assert_eq!(output.shape(), &[2, 3, 4]);
for group in 0..6 {
let group_mean: f32 = (0..4).map(|i| output.data()[group * 4 + i]).sum::<f32>() / 4.0;
assert!(
(group_mean - 0.0).abs() < 1e-4,
"Group {} mean should be ~0, got {}",
group,
group_mean
);
}
}
#[test]
fn test_layer_norm_large_eps() {
let layer_norm = LayerNorm::new(4, 1.0).expect("test");
let input = Tensor::from_vec(vec![4], vec![1.0, 2.0, 3.0, 4.0]).expect("test");
let output = layer_norm.forward(&input).expect("test");
for &val in output.data() {
assert!(val.is_finite());
}
}
#[test]
fn test_layer_norm_numerical_stability_large_values() {
let layer_norm = LayerNorm::new(4, 1e-5).expect("test");
let input =
Tensor::from_vec(vec![4], vec![1e6, 1e6 + 1.0, 1e6 + 2.0, 1e6 + 3.0]).expect("test");
let output = layer_norm.forward(&input).expect("test");
for &val in output.data() {
assert!(val.is_finite(), "LayerNorm should handle large values");
}
let mean: f32 = output.data().iter().sum::<f32>() / 4.0;
assert!((mean - 0.0).abs() < 1e-4);
}
#[test]
fn test_ffn_1d_input() {
let ffn = FeedForward::new(4, 16).expect("test");
let input = Tensor::from_vec(vec![4], vec![1.0, 2.0, 3.0, 4.0]).expect("test");
let output = ffn.forward(&input).expect("test");
assert_eq!(output.shape(), &[4]);
}
#[test]
fn test_ffn_3d_input() {
let ffn = FeedForward::new(4, 16).expect("test");
let input = Tensor::from_vec(vec![2, 3, 4], vec![0.1; 24]).expect("test");
let output = ffn.forward(&input).expect("test");
assert_eq!(output.shape(), &[2, 3, 4]);
}
#[test]
fn test_ffn_dimension_mismatch_error() {
let ffn = FeedForward::new(4, 16).expect("test");
let input = Tensor::from_vec(vec![5], vec![0.1; 5]).expect("test");
let result = ffn.forward(&input);
assert!(result.is_err(), "Should error on dimension mismatch");
}
#[test]
fn test_ffn_with_custom_weights() {
let mut ffn = FeedForward::new(2, 4).expect("test");
for (i, w) in ffn.fc1_mut().weight_mut().iter_mut().enumerate() {
*w = if i % 2 == 0 { 1.0 } else { 0.0 };
}
for b in ffn.fc1_mut().bias_mut().iter_mut() {
*b = 0.0;
}
for (i, w) in ffn.fc2_mut().weight_mut().iter_mut().enumerate() {
*w = if i % 2 == 0 { 1.0 } else { 0.0 };
}
for b in ffn.fc2_mut().bias_mut().iter_mut() {
*b = 0.0;
}
let input = Tensor::from_vec(vec![2], vec![1.0, 0.5]).expect("test");
let output = ffn.forward(&input).expect("test");
assert_eq!(output.shape(), &[2]);
for &val in output.data() {
assert!(val.is_finite());
}
}
#[test]
fn test_layer_norm_debug_clone() {
let layer_norm = LayerNorm::new(4, 1e-5).expect("test");
let debug_str = format!("{:?}", layer_norm);
assert!(debug_str.contains("LayerNorm"));
let cloned = layer_norm.clone();
assert_eq!(cloned.normalized_shape(), layer_norm.normalized_shape());
assert!((cloned.eps() - layer_norm.eps()).abs() < 1e-10);
}
#[test]
fn test_linear_debug_clone() {
let linear = Linear::new(4, 8).expect("test");
let debug_str = format!("{:?}", linear);
assert!(debug_str.contains("Linear"));
let cloned = linear.clone();
assert_eq!(cloned.in_features(), linear.in_features());
assert_eq!(cloned.out_features(), linear.out_features());
}
#[test]
fn test_quantized_linear_debug_clone() {
let weight_bytes = vec![0u8; 144];
let bias = vec![0.0f32; 1];
let layer = QuantizedLinear::new(256, 1, weight_bytes, bias).expect("test");
let debug_str = format!("{:?}", layer);
assert!(debug_str.contains("QuantizedLinear"));
let cloned = layer.clone();
assert_eq!(cloned.in_features(), layer.in_features());
assert_eq!(cloned.out_features(), layer.out_features());
}
#[test]
fn test_fused_layer_norm_linear_debug_clone() {
let fused = FusedLayerNormLinear::new(4, 8, 1e-5).expect("test");
let debug_str = format!("{:?}", fused);
assert!(debug_str.contains("FusedLayerNormLinear"));
let cloned = fused.clone();
assert_eq!(cloned.feature_dim(), fused.feature_dim());
assert_eq!(cloned.out_features(), fused.out_features());
}
#[test]
fn test_feed_forward_debug_clone() {
let ffn = FeedForward::new(4, 16).expect("test");
let debug_str = format!("{:?}", ffn);
assert!(debug_str.contains("FeedForward"));
let cloned = ffn.clone();
assert_eq!(cloned.hidden_dim(), ffn.hidden_dim());
assert_eq!(cloned.intermediate_dim(), ffn.intermediate_dim());
}
#[test]
fn test_softmax_inf_handling() {
let input = Tensor::from_vec(vec![3], vec![f32::MAX / 2.0, 0.0, 0.0]).expect("test");
let result = softmax(&input);
if let Ok(output) = result {
let sum: f32 = output.data().iter().sum();
assert!(sum.is_finite() || sum.is_nan(), "Sum should be handled");
}
}
#[test]
fn test_gelu_inf_input() {
let input = Tensor::from_vec(vec![1], vec![f32::MAX / 2.0]).expect("test");
let result = gelu(&input);
if let Ok(output) = result {
let val = output.data()[0];
assert!(
val.is_finite() || val.is_infinite(),
"Should produce a value"
);
}
}
#[test]
fn test_layer_norm_tiny_eps() {
let layer_norm = LayerNorm::new(4, 1e-12).expect("test");
let input = Tensor::from_vec(vec![4], vec![1.0, 2.0, 3.0, 4.0]).expect("test");
let output = layer_norm.forward(&input).expect("test");
for &val in output.data() {
assert!(val.is_finite());
}
}
#[test]
fn test_linear_large_batch() {
let linear = Linear::new(4, 8).expect("test");
let input = Tensor::from_vec(vec![100, 4], vec![0.1; 400]).expect("test");
let output = linear.forward(&input).expect("test");
assert_eq!(output.shape(), &[100, 8]);
}
#[test]
fn test_layer_norm_large_batch() {
let layer_norm = LayerNorm::new(4, 1e-5).expect("test");
let input = Tensor::from_vec(vec![100, 4], vec![0.1; 400]).expect("test");
let output = layer_norm.forward(&input).expect("test");
assert_eq!(output.shape(), &[100, 4]);
}
#[test]
fn test_fused_layer_norm_linear_large_batch_parallel() {
let fused = FusedLayerNormLinear::new(8, 16, 1e-5).expect("test");
let input = Tensor::from_vec(vec![100, 8], vec![0.1; 800]).expect("test");
let serial = fused.forward(&input).expect("test");
let parallel = fused.forward_parallel(&input).expect("test");
assert_eq!(serial.shape(), &[100, 16]);
assert_eq!(parallel.shape(), &[100, 16]);
for i in 0..serial.data().len() {
assert!(
(serial.data()[i] - parallel.data()[i]).abs() < 1e-4,
"Large batch mismatch at {}: {} vs {}",
i,
serial.data()[i],
parallel.data()[i]
);
}
}