use crate::array::Array;
use crate::error::Result;
use crate::utils::axes_or_default_to_all;
use crate::utils::guard::Guarded;
use crate::{Axes, Stream};
use mlx_internal_macros::generate_macro;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct CountNonzeroOptions {
pub axes: Axes,
pub keep_dims: bool,
}
static EMPTY_AXES_DUMMY: [i32; 1] = [0];
impl Array {
pub fn count_nonzero(&self, options: CountNonzeroOptions) -> Result<Array> {
let stream = Stream::thread_local_or_default();
match options.axes {
Axes::All => Array::try_from_op(|res| unsafe {
mlx_sys::mlx_count_nonzero(
res,
self.as_ptr(),
options.keep_dims,
stream.as_ref().as_ptr(),
)
}),
Axes::Axis(axis) => Array::try_from_op(|res| unsafe {
mlx_sys::mlx_count_nonzero_axis(
res,
self.as_ptr(),
axis,
options.keep_dims,
stream.as_ref().as_ptr(),
)
}),
Axes::Axes(axes) => {
let axes_ptr = if axes.is_empty() {
EMPTY_AXES_DUMMY.as_ptr()
} else {
axes.as_ptr()
};
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_count_nonzero_axes(
res,
self.as_ptr(),
axes_ptr,
axes.len(),
options.keep_dims,
stream.as_ref().as_ptr(),
)
})
}
}
}
pub fn all_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_all_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all_axes`"
)]
pub fn all_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.all_axes(axes, keep_dims))
}
pub fn all_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_all_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all_axis`"
)]
pub fn all_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.all_axis(axis, keep_dims))
}
pub fn all(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_all(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all`"
)]
pub fn all_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.all(keep_dims))
}
pub fn prod_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_prod_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod_axes`"
)]
pub fn prod_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.prod_axes(axes, keep_dims))
}
pub fn prod_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_prod_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod_axis`"
)]
pub fn prod_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.prod_axis(axis, keep_dims))
}
pub fn prod(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_prod(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod`"
)]
pub fn prod_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.prod(keep_dims))
}
pub fn max_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_max_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max_axes`"
)]
pub fn max_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.max_axes(axes, keep_dims))
}
pub fn max_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_max_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max_axis`"
)]
pub fn max_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.max_axis(axis, keep_dims))
}
pub fn max(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_max(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max`"
)]
pub fn max_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.max(keep_dims))
}
pub fn sum_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_sum_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum_axes`"
)]
pub fn sum_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.sum_axes(axes, keep_dims))
}
pub fn sum_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_sum_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum_axis`"
)]
pub fn sum_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.sum_axis(axis, keep_dims))
}
pub fn sum(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_sum(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum`"
)]
pub fn sum_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.sum(keep_dims))
}
pub fn mean_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let axes = axes_or_default_to_all(axes, self.ndim() as i32);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_mean_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean_axes`"
)]
pub fn mean_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.mean_axes(axes, keep_dims))
}
pub fn mean_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_mean_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean_axis`"
)]
pub fn mean_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.mean_axis(axis, keep_dims))
}
pub fn mean(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_mean(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean`"
)]
pub fn mean_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.mean(keep_dims))
}
pub fn min_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_min_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min_axes`"
)]
pub fn min_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.min_axes(axes, keep_dims))
}
pub fn min_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_min_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min_axis`"
)]
pub fn min_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.min_axis(axis, keep_dims))
}
pub fn min(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_min(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min`"
)]
pub fn min_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.min(keep_dims))
}
pub fn var_axes(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_var_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
ddof.into().unwrap_or(0),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var_axes`"
)]
pub fn var_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.var_axes(axes, keep_dims, ddof))
}
pub fn var_axis(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_var_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
ddof.into().unwrap_or(0),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var_axis`"
)]
pub fn var_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.var_axis(axis, keep_dims, ddof))
}
pub fn var(
&self,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_var(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
ddof.into().unwrap_or(0),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var`"
)]
pub fn var_device(
&self,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.var(keep_dims, ddof))
}
pub fn median_axes(&self, axes: &[i32], keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_median_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median_axes`"
)]
pub fn median_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.median_axes(axes, keep_dims))
}
pub fn median_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_median_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median_axis`"
)]
pub fn median_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.median_axis(axis, keep_dims))
}
pub fn median(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_median(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median`"
)]
pub fn median_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.median(keep_dims))
}
pub fn logsumexp_axes(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_logsumexp_axes(
res,
self.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp_axes`"
)]
pub fn logsumexp_axes_device(
&self,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.logsumexp_axes(axes, keep_dims))
}
pub fn logsumexp_axis(&self, axis: i32, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_logsumexp_axis(
res,
self.as_ptr(),
axis,
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp_axis`"
)]
pub fn logsumexp_axis_device(
&self,
axis: i32,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.logsumexp_axis(axis, keep_dims))
}
pub fn logsumexp(&self, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_logsumexp(
res,
self.as_ptr(),
keep_dims.into().unwrap_or(false),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp`"
)]
pub fn logsumexp_device(
&self,
keep_dims: impl Into<Option<bool>>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || self.logsumexp(keep_dims))
}
}
pub fn all_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().all_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all_axes`"
)]
pub fn all_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || all_axes(array, axes, keep_dims))
}
pub fn all_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().all_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all_axis`"
)]
pub fn all_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || all_axis(array, axis, keep_dims))
}
pub fn all(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().all(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `all`"
)]
pub fn all_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || all(array, keep_dims))
}
pub fn prod_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().prod_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod_axes`"
)]
pub fn prod_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || prod_axes(array, axes, keep_dims))
}
pub fn prod_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().prod_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod_axis`"
)]
pub fn prod_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || prod_axis(array, axis, keep_dims))
}
pub fn prod(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().prod(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `prod`"
)]
pub fn prod_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || prod(array, keep_dims))
}
pub fn max_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().max_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max_axes`"
)]
pub fn max_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || max_axes(array, axes, keep_dims))
}
pub fn max_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().max_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max_axis`"
)]
pub fn max_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || max_axis(array, axis, keep_dims))
}
pub fn max(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().max(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `max`"
)]
pub fn max_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || max(array, keep_dims))
}
pub fn std_axes(
a: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = a.as_ref();
let keep_dims = keep_dims.into().unwrap_or(false);
let ddof = ddof.into().unwrap_or(0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_std_axes(
res,
a.as_ptr(),
axes.as_ptr(),
axes.len(),
keep_dims,
ddof,
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `std_axes`"
)]
pub fn std_axes_device(
a: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || std_axes(a, axes, keep_dims, ddof))
}
pub fn std_axis(
a: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = a.as_ref();
let keep_dims = keep_dims.into().unwrap_or(false);
let ddof = ddof.into().unwrap_or(0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_std_axis(
res,
a.as_ptr(),
axis,
keep_dims,
ddof,
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `std_axis`"
)]
pub fn std_axis_device(
a: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || std_axis(a, axis, keep_dims, ddof))
}
pub fn std(
a: impl AsRef<Array>,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = a.as_ref();
let keep_dims = keep_dims.into().unwrap_or(false);
let ddof = ddof.into().unwrap_or(0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_std(res, a.as_ptr(), keep_dims, ddof, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `std`"
)]
pub fn std_device(
a: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || std(a, keep_dims, ddof))
}
pub fn sum_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().sum_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum_axes`"
)]
pub fn sum_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || sum_axes(array, axes, keep_dims))
}
pub fn sum_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().sum_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum_axis`"
)]
pub fn sum_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || sum_axis(array, axis, keep_dims))
}
pub fn sum(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().sum(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sum`"
)]
pub fn sum_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || sum(array, keep_dims))
}
pub fn mean_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().mean_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean_axes`"
)]
pub fn mean_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || mean_axes(array, axes, keep_dims))
}
pub fn mean_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().mean_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean_axis`"
)]
pub fn mean_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || mean_axis(array, axis, keep_dims))
}
pub fn mean(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().mean(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `mean`"
)]
pub fn mean_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || mean(array, keep_dims))
}
pub fn min_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().min_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min_axes`"
)]
pub fn min_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || min_axes(array, axes, keep_dims))
}
pub fn min_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().min_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min_axis`"
)]
pub fn min_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || min_axis(array, axis, keep_dims))
}
pub fn min(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().min(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `min`"
)]
pub fn min_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || min(array, keep_dims))
}
pub fn var_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
array.as_ref().var_axes(axes, keep_dims, ddof)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var_axes`"
)]
pub fn var_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || var_axes(array, axes, keep_dims, ddof))
}
pub fn var_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
array.as_ref().var_axis(axis, keep_dims, ddof)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var_axis`"
)]
pub fn var_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || var_axis(array, axis, keep_dims, ddof))
}
pub fn var(
array: impl AsRef<Array>,
keep_dims: impl Into<Option<bool>>,
ddof: impl Into<Option<i32>>,
) -> Result<Array> {
array.as_ref().var(keep_dims, ddof)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `var`"
)]
pub fn var_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] ddof: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || var(array, keep_dims, ddof))
}
pub fn median_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().median_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median_axes`"
)]
pub fn median_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || median_axes(array, axes, keep_dims))
}
pub fn median_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().median_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median_axis`"
)]
pub fn median_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || median_axis(array, axis, keep_dims))
}
pub fn median(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().median(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `median`"
)]
pub fn median_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || median(array, keep_dims))
}
pub fn logsumexp_axes(
array: impl AsRef<Array>,
axes: &[i32],
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().logsumexp_axes(axes, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp_axes`"
)]
pub fn logsumexp_axes_device(
array: impl AsRef<Array>,
axes: &[i32],
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || logsumexp_axes(array, axes, keep_dims))
}
pub fn logsumexp_axis(
array: impl AsRef<Array>,
axis: i32,
keep_dims: impl Into<Option<bool>>,
) -> Result<Array> {
array.as_ref().logsumexp_axis(axis, keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp_axis`"
)]
pub fn logsumexp_axis_device(
array: impl AsRef<Array>,
axis: i32,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || logsumexp_axis(array, axis, keep_dims))
}
pub fn logsumexp(array: impl AsRef<Array>, keep_dims: impl Into<Option<bool>>) -> Result<Array> {
array.as_ref().logsumexp(keep_dims)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `logsumexp`"
)]
pub fn logsumexp_device(
array: impl AsRef<Array>,
#[optional] keep_dims: impl Into<Option<bool>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || logsumexp(array, keep_dims))
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_all() {
let array = Array::from_slice(&[true, false, true, false], &[2, 2]);
assert_eq!(array.all(None).unwrap().item_exact::<bool>(), false);
assert_eq!(array.all(true).unwrap().shape(), &[1, 1]);
assert_eq!(
array.all_axes(&[0, 1], None).unwrap().item_exact::<bool>(),
false
);
let result = array.all_axis(0, None).unwrap();
assert_eq!(result.as_slice::<bool>(), &[true, false]);
let result = array.all_axis(1, None).unwrap();
assert_eq!(result.as_slice::<bool>(), &[false, false]);
}
#[test]
fn test_all_empty_axes() {
let array = Array::from_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], &[3, 4]);
let all = array.all_axes(&[], None).unwrap();
let results: &[bool] = all.as_slice();
assert_eq!(
results,
&[false, true, true, true, true, true, true, true, true, true, true, true]
);
}
#[test]
fn test_prod() {
let x = Array::from_slice(&[1, 2, 3, 3], &[2, 2]);
assert_eq!(x.prod(None).unwrap().item_exact::<i32>(), 18);
let y = x.prod(true).unwrap();
assert_eq!(y.item_exact::<i32>(), 18);
assert_eq!(y.shape(), &[1, 1]);
let result = x.prod_axis(0, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[3, 6]);
let result = x.prod_axis(1, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[2, 9])
}
#[test]
fn test_prod_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.prod_axes(&[], None).unwrap();
let results: &[i32] = result.as_slice();
assert_eq!(results, &[5, 8, 4, 9]);
}
#[test]
fn test_max() {
let x = Array::from_slice(&[1, 2, 3, 4], &[2, 2]);
assert_eq!(x.max(None).unwrap().item_exact::<i32>(), 4);
let y = x.max(true).unwrap();
assert_eq!(y.item_exact::<i32>(), 4);
assert_eq!(y.shape(), &[1, 1]);
let result = x.max_axis(0, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[3, 4]);
let result = x.max_axis(1, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[2, 4]);
}
#[test]
fn test_max_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.max_axes(&[], None).unwrap();
let results: &[i32] = result.as_slice();
assert_eq!(results, &[5, 8, 4, 9]);
}
#[test]
fn test_sum() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.sum_axis(0, None).unwrap();
let results: &[i32] = result.as_slice();
assert_eq!(results, &[9, 17]);
}
#[test]
fn test_sum_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.sum_axes(&[], None).unwrap();
let results: &[i32] = result.as_slice();
assert_eq!(results, &[5, 8, 4, 9]);
}
#[test]
fn test_mean() {
let x = Array::from_slice(&[1, 2, 3, 4], &[2, 2]);
assert_eq!(x.mean(None).unwrap().item_exact::<f32>(), 2.5);
let y = x.mean(true).unwrap();
assert_eq!(y.item_exact::<f32>(), 2.5);
assert_eq!(y.shape(), &[1, 1]);
let result = x.mean_axis(0, None).unwrap();
assert_eq!(result.as_slice::<f32>(), &[2.0, 3.0]);
let result = x.mean_axis(1, None).unwrap();
assert_eq!(result.as_slice::<f32>(), &[1.5, 3.5]);
}
#[test]
fn test_mean_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.mean_axes(&[], None).unwrap();
let results: &[f32] = result.as_slice();
assert_eq!(results, &[5.0, 8.0, 4.0, 9.0]);
}
#[test]
fn test_mean_out_of_bounds() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.mean_axis(2, None);
assert!(result.is_err());
}
#[test]
fn test_min() {
let x = Array::from_slice(&[1, 2, 3, 4], &[2, 2]);
assert_eq!(x.min(None).unwrap().item_exact::<i32>(), 1);
let y = x.min(true).unwrap();
assert_eq!(y.item_exact::<i32>(), 1);
assert_eq!(y.shape(), &[1, 1]);
let result = x.min_axis(0, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[1, 2]);
let result = x.min_axis(1, None).unwrap();
assert_eq!(result.as_slice::<i32>(), &[1, 3]);
}
#[test]
fn test_min_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.min_axes(&[], None).unwrap();
let results: &[i32] = result.as_slice();
assert_eq!(results, &[5, 8, 4, 9]);
}
#[test]
fn test_var() {
let x = Array::from_slice(&[1, 2, 3, 4], &[2, 2]);
assert_eq!(x.var(None, None).unwrap().item_exact::<f32>(), 1.25);
let y = x.var(true, None).unwrap();
assert_eq!(y.item_exact::<f32>(), 1.25);
assert_eq!(y.shape(), &[1, 1]);
let result = x.var_axis(0, None, None).unwrap();
assert_eq!(result.as_slice::<f32>(), &[1.0, 1.0]);
let result = x.var_axis(1, None, None).unwrap();
assert_eq!(result.as_slice::<f32>(), &[0.25, 0.25]);
let x = Array::from_slice(&[1.0, 2.0], &[2]);
let out = x.var(None, Some(3)).unwrap();
assert_eq!(out.item_exact::<f32>(), f32::INFINITY);
}
#[test]
fn test_var_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.var_axes(&[], None, 0).unwrap();
let results: &[f32] = result.as_slice();
assert_eq!(results, &[0.0, 0.0, 0.0, 0.0]);
}
#[test]
fn test_log_sum_exp() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.logsumexp_axis(0, None).unwrap();
let results: &[f32] = result.as_slice();
assert_eq!(results, &[5.3132615, 9.313262]);
}
#[test]
fn test_log_sum_exp_empty_axes() {
let array = Array::from_slice(&[5, 8, 4, 9], &[2, 2]);
let result = array.logsumexp_axes(&[], None).unwrap();
let results: &[f32] = result.as_slice();
assert_eq!(results, &[5.0, 8.0, 4.0, 9.0]);
}
#[test]
fn test_median() {
let x = Array::from_slice(&[0, 1, 2, 3, 4], &[5]);
let out = x.median(None).unwrap();
assert_eq!(out.shape(), &[] as &[i32]);
assert_eq!(out.item_exact::<f32>(), 2.0);
let out = x.median(true).unwrap();
assert_eq!(out.shape(), &[1]);
let x = Array::from_slice(&[0, 1, 2, 3, 4, 5], &[6]);
let out = x.median(None).unwrap();
assert!((out.item_exact::<f32>() - 2.5).abs() < 1e-5);
use crate::random;
random::seed(0).unwrap();
let x = random::normal::<f32>(&[5, 5, 5, 5], None, None, None).unwrap();
let out = x.median_axes(&[0, 2], true).unwrap();
assert_eq!(out.shape(), &[1, 5, 1, 5]);
let out = x.median_axes(&[1, 3], true).unwrap();
assert_eq!(out.shape(), &[5, 1, 5, 1]);
let x = Array::from_slice(&[1, 5, 2, 4, 3, 6], &[2, 3]);
let out = x.median_axis(0, None).unwrap();
assert_eq!(out.shape(), &[3]);
let out = x.median_axis(1, None).unwrap();
assert_eq!(out.shape(), &[2]);
}
}