diff --git a/mlx-rs/src/fast.rs b/mlx-rs/src/fast.rs index 6d9d0935..669fc599 100644 --- a/mlx-rs/src/fast.rs +++ b/mlx-rs/src/fast.rs @@ -182,22 +182,28 @@ pub fn scaled_dot_product_attention_device<'a>( /// # Params /// /// - x: input array -/// - weight: A multiplicative weight to scale the result by. The `weight` should be one-dimensional with the same size as the last axis of `x`. +/// - weight: A multiplicative weight to scale the result by. The `weight` should be one-dimensional +/// with the same size as the last axis of `x`. If not given, no scaling will occur (matches +/// Python's `mx.fast.rms_norm(x, None, eps)` semantics — the underlying Metal kernel skips +/// the per-element multiply, saving a kernel pass). /// - eps: A small additive constant for numerical stability /// - stream: stream or device to evaluate on #[generate_macro(customize(root = "$crate::fast"))] #[default_device] -pub fn rms_norm_device( - x: impl AsRef, - weight: impl AsRef, - eps: f32, +pub fn rms_norm_device<'a>( + #[named] x: impl AsRef, + #[optional] weight: impl Into>, + #[named] eps: f32, #[optional] stream: impl AsRef, ) -> Result { Array::try_from_op(|res| unsafe { mlx_sys::mlx_fast_rms_norm( res, x.as_ref().as_ptr(), - weight.as_ref().as_ptr(), + weight + .into() + .map(|w| w.as_ptr()) + .unwrap_or_else(|| mlx_sys::mlx_array_new()), eps, stream.as_ref().as_ptr(), ) @@ -308,7 +314,7 @@ mod tests { assert_eq!(a.dtype(), crate::Dtype::Float32); let weight = Array::ones::(&[16]).unwrap(); - let result = rms_norm(a, weight, 1e-5).unwrap(); + let result = rms_norm(a, &weight, 1e-5).unwrap(); assert_eq!(result.shape(), [2, 8, 16]); assert_eq!(result.dtype(), crate::Dtype::Float32); assert_float_eq!(