use mlx_internal_macros::generate_macro;
use crate::{error::Result, utils::guard::Guarded, Array, Stream};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum SearchSide {
#[default]
Left,
Right,
}
impl SearchSide {
fn as_c_ptr(self) -> *const std::ffi::c_char {
match self {
Self::Left => c"left".as_ptr(),
Self::Right => c"right".as_ptr(),
}
}
}
impl Array {
pub fn search_sorted(&self, values: impl AsRef<Array>, side: SearchSide) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_searchsorted(
res,
self.as_ptr(),
values.as_ref().as_ptr(),
side.as_c_ptr(),
stream.as_ref().as_ptr(),
)
})
}
}
pub fn sort_axis(a: impl AsRef<Array>, axis: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_sort_axis(res, a.as_ref().as_ptr(), axis, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sort_axis`"
)]
pub fn sort_axis_device(
a: impl AsRef<Array>,
axis: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || sort_axis(a, axis))
}
pub fn sort(a: impl AsRef<Array>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_sort(res, a.as_ref().as_ptr(), stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `sort`"
)]
pub fn sort_device(a: impl AsRef<Array>, #[optional] stream: impl AsRef<Stream>) -> Result<Array> {
crate::with_stream(stream.as_ref(), || sort(a))
}
pub fn argsort_axis(a: impl AsRef<Array>, axis: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_argsort_axis(res, a.as_ref().as_ptr(), axis, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `argsort_axis`"
)]
pub fn argsort_axis_device(
a: impl AsRef<Array>,
axis: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || argsort_axis(a, axis))
}
pub fn argsort(a: impl AsRef<Array>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_argsort(res, a.as_ref().as_ptr(), stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `argsort`"
)]
pub fn argsort_device(
a: impl AsRef<Array>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || argsort(a))
}
pub fn partition_axis(a: impl AsRef<Array>, kth: i32, axis: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_partition_axis(
res,
a.as_ref().as_ptr(),
kth,
axis,
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `partition_axis`"
)]
pub fn partition_axis_device(
a: impl AsRef<Array>,
kth: i32,
axis: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || partition_axis(a, kth, axis))
}
pub fn partition(a: impl AsRef<Array>, kth: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_partition(res, a.as_ref().as_ptr(), kth, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `partition`"
)]
pub fn partition_device(
a: impl AsRef<Array>,
kth: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || partition(a, kth))
}
pub fn argpartition_axis(a: impl AsRef<Array>, kth: i32, axis: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_argpartition_axis(
res,
a.as_ref().as_ptr(),
kth,
axis,
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `argpartition_axis`"
)]
pub fn argpartition_axis_device(
a: impl AsRef<Array>,
kth: i32,
axis: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || argpartition_axis(a, kth, axis))
}
pub fn argpartition(a: impl AsRef<Array>, kth: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_argpartition(res, a.as_ref().as_ptr(), kth, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `argpartition`"
)]
pub fn argpartition_device(
a: impl AsRef<Array>,
kth: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || argpartition(a, kth))
}
#[cfg(test)]
mod tests {
use crate::Array;
#[test]
fn test_sort_with_invalid_axis() {
let a = Array::from_slice(&[1, 2, 3, 4, 5], &[5]);
let axis = 1;
let result = super::sort_axis(&a, axis);
assert!(result.is_err());
}
#[test]
fn test_partition_with_invalid_axis() {
let a = Array::from_slice(&[1, 2, 3, 4, 5], &[5]);
let kth = 2;
let axis = 1;
let result = super::partition_axis(&a, kth, axis);
assert!(result.is_err());
}
#[test]
fn test_partition_with_invalid_kth() {
let a = Array::from_slice(&[1, 2, 3, 4, 5], &[5]);
let kth = 5;
let axis = 0;
let result = super::partition_axis(&a, kth, axis);
assert!(result.is_err());
}
#[test]
fn test_partition_all_with_invalid_kth() {
let a = Array::from_slice(&[1, 2, 3, 4, 5], &[5]);
let kth = 5;
let result = super::partition(&a, kth);
assert!(result.is_err());
}
}