use crate::array::Array;
use crate::array::ArrayElement;
use crate::error::Result;
use crate::utils::guard::Guarded;
use crate::{Dtype, Stream};
use mlx_internal_macros::generate_macro;
use num_traits::NumCast;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LinspaceOptions {
pub count: i32,
pub endpoint: bool,
}
impl Default for LinspaceOptions {
fn default() -> Self {
Self {
count: 50,
endpoint: true,
}
}
}
impl Array {
pub fn zeros<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
let dtype = T::DTYPE;
zeros_dtype(shape, dtype)
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `zeros`"
)]
pub fn zeros_device<T: ArrayElement>(
shape: &[i32],
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::zeros::<T>(shape))
}
pub fn ones<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
let dtype = T::DTYPE;
ones_dtype(shape, dtype)
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `ones`"
)]
pub fn ones_device<T: ArrayElement>(
shape: &[i32],
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::ones::<T>(shape))
}
pub fn eye<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_eye(
res,
n,
m.unwrap_or(n),
k.unwrap_or(0),
T::DTYPE.into(),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `eye`"
)]
pub fn eye_device<T: ArrayElement>(
n: i32,
m: Option<i32>,
k: Option<i32>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::eye::<T>(n, m, k))
}
pub fn full<T: ArrayElement>(shape: &[i32], values: impl AsRef<Array>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_full(
res,
shape.as_ptr(),
shape.len(),
values.as_ref().as_ptr(),
T::DTYPE.into(),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `full`"
)]
pub fn full_device<T: ArrayElement>(
shape: &[i32],
values: impl AsRef<Array>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::full::<T>(shape, values))
}
pub fn identity<T: ArrayElement>(n: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_identity(res, n, T::DTYPE.into(), stream.as_ref().as_ptr())
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `identity`"
)]
pub fn identity_device<T: ArrayElement>(n: i32, stream: impl AsRef<Stream>) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::identity::<T>(n))
}
pub fn arange<U, T>(
start: impl Into<Option<U>>,
stop: U,
step: impl Into<Option<U>>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
let stream = Stream::thread_local_or_default();
let start: f64 = start.into().and_then(NumCast::from).unwrap_or(0.0);
let stop: f64 = NumCast::from(stop).unwrap();
let step: f64 = step.into().and_then(NumCast::from).unwrap_or(1.0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_arange(
res,
start,
stop,
step,
T::DTYPE.into(),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `arange`"
)]
pub fn arange_device<U, T>(
start: impl Into<Option<U>>,
stop: U,
step: impl Into<Option<U>>,
stream: impl AsRef<Stream>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
crate::with_stream(stream.as_ref(), || Self::arange::<U, T>(start, stop, step))
}
#[deprecated(since = "0.26.0", note = "use `ops::linspace` with `LinspaceOptions`")]
pub fn linspace<U, T>(start: U, stop: U, count: impl Into<Option<i32>>) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
linspace::<U, T>(
start,
stop,
LinspaceOptions {
count: count.into().unwrap_or(50),
endpoint: true,
},
)
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `ops::linspace`"
)]
pub fn linspace_device<U, T>(
start: U,
stop: U,
count: impl Into<Option<i32>>,
stream: impl AsRef<Stream>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
crate::with_stream(stream.as_ref(), || {
linspace::<U, T>(
start,
stop,
LinspaceOptions {
count: count.into().unwrap_or(50),
endpoint: true,
},
)
})
}
pub fn repeat_axis<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
axis: i32,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let array = array.as_ref();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_repeat_axis(res, array.as_ptr(), count, axis, stream.as_ref().as_ptr())
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `repeat_axis`"
)]
pub fn repeat_axis_device<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
axis: i32,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || {
Self::repeat_axis::<T>(array, count, axis)
})
}
pub fn repeat<T: ArrayElement>(array: impl AsRef<Array>, count: i32) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let array = array.as_ref();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_repeat(res, array.as_ptr(), count, stream.as_ref().as_ptr())
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `repeat`"
)]
pub fn repeat_device<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::repeat::<T>(array, count))
}
pub fn tri<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_tri(
res,
n,
m.unwrap_or(n),
k.unwrap_or(0),
T::DTYPE.into(),
stream.as_ref().as_ptr(),
)
})
}
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `tri`"
)]
pub fn tri_device<T: ArrayElement>(
n: i32,
m: Option<i32>,
k: Option<i32>,
stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || Self::tri::<T>(n, m, k))
}
}
pub fn zeros<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
Array::zeros::<T>(shape)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `zeros`"
)]
pub fn zeros_device<T: ArrayElement>(
shape: &[i32],
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || zeros::<T>(shape))
}
pub fn zeros_like(input: impl AsRef<Array>) -> Result<Array> {
let a = input.as_ref();
let shape = a.shape();
let dtype = a.dtype();
zeros_dtype(shape, dtype)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `zeros_like`"
)]
pub fn zeros_like_device(
input: impl AsRef<Array>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || zeros_like(input))
}
pub fn zeros_dtype(shape: &[i32], dtype: Dtype) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_zeros(
res,
shape.as_ptr(),
shape.len(),
dtype.into(),
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `zeros_dtype`"
)]
pub fn zeros_dtype_device(
shape: &[i32],
dtype: Dtype,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || zeros_dtype(shape, dtype))
}
pub fn ones<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
Array::ones::<T>(shape)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `ones`"
)]
pub fn ones_device<T: ArrayElement>(
shape: &[i32],
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || ones::<T>(shape))
}
pub fn ones_like(input: impl AsRef<Array>) -> Result<Array> {
let a = input.as_ref();
let shape = a.shape();
let dtype = a.dtype();
ones_dtype(shape, dtype)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `ones_like`"
)]
pub fn ones_like_device(
input: impl AsRef<Array>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || ones_like(input))
}
pub fn full_like(
input: impl AsRef<Array>,
values: impl AsRef<Array>,
dtype: impl Into<Option<Dtype>>,
) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = input.as_ref();
let dtype = dtype.into().unwrap_or_else(|| a.dtype());
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_full_like(
res,
a.as_ptr(),
values.as_ref().as_ptr(),
dtype.into(),
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `full_like`"
)]
pub fn full_like_device(
input: impl AsRef<Array>,
values: impl AsRef<Array>,
#[optional] dtype: impl Into<Option<Dtype>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || full_like(input, values, dtype))
}
pub fn ones_dtype(shape: &[i32], dtype: Dtype) -> Result<Array> {
let stream = Stream::thread_local_or_default();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_ones(
res,
shape.as_ptr(),
shape.len(),
dtype.into(),
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `ones_dtype`"
)]
pub fn ones_dtype_device(
shape: &[i32],
dtype: Dtype,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || ones_dtype(shape, dtype))
}
pub fn eye<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
Array::eye::<T>(n, m, k)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `eye`"
)]
pub fn eye_device<T: ArrayElement>(
n: i32,
#[optional] m: Option<i32>,
#[optional] k: Option<i32>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || eye::<T>(n, m, k))
}
pub fn full<T: ArrayElement>(shape: &[i32], values: impl AsRef<Array>) -> Result<Array> {
Array::full::<T>(shape, values)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `full`"
)]
pub fn full_device<T: ArrayElement>(
shape: &[i32],
values: impl AsRef<Array>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || full::<T>(shape, values))
}
pub fn identity<T: ArrayElement>(n: i32) -> Result<Array> {
Array::identity::<T>(n)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `identity`"
)]
pub fn identity_device<T: ArrayElement>(
n: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || identity::<T>(n))
}
pub fn arange<U, T>(
start: impl Into<Option<U>>,
stop: U,
step: impl Into<Option<U>>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
Array::arange::<U, T>(start, stop, step)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `arange`"
)]
pub fn arange_device<U, T>(
#[optional] start: impl Into<Option<U>>,
#[named] stop: U,
#[optional] step: impl Into<Option<U>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
crate::with_stream(stream.as_ref(), || arange::<U, T>(start, stop, step))
}
pub fn linspace<U, T>(start: U, stop: U, options: LinspaceOptions) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
let stream = Stream::thread_local_or_default();
let start: f64 = NumCast::from(start).unwrap();
let stop: f64 = NumCast::from(stop).unwrap();
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_linspace_endpoint(
res,
start,
stop,
options.count,
options.endpoint,
T::DTYPE.into(),
stream.as_ref().as_ptr(),
)
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `linspace`"
)]
pub fn linspace_device<U, T>(
start: U,
stop: U,
#[optional] count: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array>
where
U: NumCast,
T: ArrayElement,
{
crate::with_stream(stream.as_ref(), || {
linspace::<U, T>(
start,
stop,
LinspaceOptions {
count: count.into().unwrap_or(50),
endpoint: true,
},
)
})
}
pub fn repeat_axis<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
axis: i32,
) -> Result<Array> {
Array::repeat_axis::<T>(array, count, axis)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `repeat_axis`"
)]
pub fn repeat_axis_device<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
axis: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || repeat_axis::<T>(array, count, axis))
}
pub fn repeat<T: ArrayElement>(array: impl AsRef<Array>, count: i32) -> Result<Array> {
Array::repeat::<T>(array, count)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `repeat`"
)]
pub fn repeat_device<T: ArrayElement>(
array: impl AsRef<Array>,
count: i32,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || repeat::<T>(array, count))
}
pub fn tri<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
Array::tri::<T>(n, m, k)
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `tri`"
)]
pub fn tri_device<T: ArrayElement>(
n: i32,
#[optional] m: Option<i32>,
#[optional] k: Option<i32>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || tri::<T>(n, m, k))
}
pub fn tril(a: impl AsRef<Array>, k: impl Into<Option<i32>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = a.as_ref();
let k = k.into().unwrap_or(0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_tril(res, a.as_ptr(), k, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `tril`"
)]
pub fn tril_device(
a: impl AsRef<Array>,
#[optional] k: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || tril(a, k))
}
pub fn triu(a: impl AsRef<Array>, k: impl Into<Option<i32>>) -> Result<Array> {
let stream = Stream::thread_local_or_default();
let a = a.as_ref();
let k = k.into().unwrap_or(0);
Array::try_from_op(|res| unsafe {
mlx_sys::mlx_triu(res, a.as_ptr(), k, stream.as_ref().as_ptr())
})
}
#[generate_macro(customize(forwarding_shim = true))]
#[deprecated(
since = "0.26.0",
note = "use `with_stream` or `with_device` around `triu`"
)]
pub fn triu_device(
a: impl AsRef<Array>,
#[optional] k: impl Into<Option<i32>>,
#[optional] stream: impl AsRef<Stream>,
) -> Result<Array> {
crate::with_stream(stream.as_ref(), || triu(a, k))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
array, dtype::Dtype, test_utils::assert_array_eq, test_utils::tolerances, with_device,
Device,
};
use half::f16;
#[test]
fn test_zeros() {
let array = Array::zeros::<f32>(&[2, 3]).unwrap();
assert_eq!(array.shape(), &[2, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
let data: &[f32] = array.as_slice();
assert_eq!(data, &[0.0; 6]);
}
#[test]
fn test_zeros_try() {
let array = Array::zeros::<f32>(&[2, 3]);
assert!(array.is_ok());
let array = Array::zeros::<f32>(&[-1, 3]);
assert!(array.is_err());
}
#[test]
fn test_ones() {
let array = Array::ones::<f16>(&[2, 3]).unwrap();
assert_eq!(array.shape(), &[2, 3]);
assert_eq!(array.dtype(), Dtype::Float16);
let data: &[f16] = array.as_slice();
assert_eq!(data, &[f16::from_f32(1.0); 6]);
}
#[test]
fn test_eye() {
let array = Array::eye::<f32>(3, None, None).unwrap();
assert_eq!(array.shape(), &[3, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
let data: &[f32] = array.as_slice();
assert_eq!(data, &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]);
}
#[test]
fn test_full_scalar() {
let array = Array::full::<f32>(&[2, 3], array!(7f32)).unwrap();
assert_eq!(array.shape(), &[2, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
assert_array_eq(
array,
Array::from_slice(&[7.0; 6], &[2, 3]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
}
#[test]
fn test_full_array() {
let source = with_device(Device::cpu(), || Array::zeros::<f32>(&[1, 3])).unwrap();
let array = Array::full::<f32>(&[2, 3], source).unwrap();
assert_eq!(array.shape(), &[2, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
assert_array_eq(
array,
Array::from_slice(&[0.0; 6], &[2, 3]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
}
#[test]
fn test_full_try() {
let source = Array::zeros::<f32>(&[1, 3]).unwrap();
let array = Array::full::<f32>(&[2, 3], source);
assert!(array.is_ok());
let source = Array::zeros::<f32>(&[1, 3]).unwrap();
let array = Array::full::<f32>(&[-1, 3], source);
assert!(array.is_err());
}
#[test]
fn test_identity() {
let array = Array::identity::<f32>(3).unwrap();
assert_eq!(array.shape(), &[3, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
let data: &[f32] = array.as_slice();
assert_eq!(data, &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]);
}
#[test]
fn test_arange() {
let array = Array::arange::<_, f32>(None, 50, None).unwrap();
assert_eq!(array.shape(), &[50]);
assert_eq!(array.dtype(), Dtype::Float32);
let data: &[f32] = array.as_slice();
let expected: Vec<f32> = (0..50).map(|x| x as f32).collect();
assert_eq!(data, expected.as_slice());
let array = Array::arange::<_, i32>(0, 50, None).unwrap();
assert_eq!(array.shape(), &[50]);
assert_eq!(array.dtype(), Dtype::Int32);
let data: &[i32] = array.as_slice();
let expected: Vec<i32> = (0..50).collect();
assert_eq!(data, expected.as_slice());
let result = Array::arange::<_, bool>(None, 50, None);
assert!(result.is_err());
let result = Array::arange::<_, f32>(f64::NEG_INFINITY, 50.0, None);
assert!(result.is_err());
let result = Array::arange::<_, f32>(0.0, f64::INFINITY, None);
assert!(result.is_err());
let result = Array::arange::<_, f32>(0.0, 50.0, f32::NAN);
assert!(result.is_err());
let result = Array::arange::<_, f32>(f32::NAN, 50.0, None);
assert!(result.is_err());
let result = Array::arange::<_, f32>(0.0, f32::NAN, None);
assert!(result.is_err());
let result = Array::arange::<_, f32>(0, i32::MAX as i64 + 1, None);
assert!(result.is_err());
}
#[test]
fn test_linspace_int() {
let array = linspace::<_, f32>(0, 50, LinspaceOptions::default()).unwrap();
assert_eq!(array.shape(), &[50]);
assert_eq!(array.dtype(), Dtype::Float32);
let expected_data: Vec<f32> = (0..50).map(|x| x as f32 * (50.0 / 49.0)).collect();
let expected = Array::from_slice(&expected_data, &[50]);
assert_eq!(array.shape(), expected.shape());
assert_array_all_close!(array, expected);
}
#[test]
fn test_linspace_float() {
let array = linspace::<_, f32>(0., 50., LinspaceOptions::default()).unwrap();
assert_eq!(array.shape(), &[50]);
assert_eq!(array.dtype(), Dtype::Float32);
let expected_data: Vec<f32> = (0..50).map(|x| x as f32 * (50.0 / 49.0)).collect();
let expected = Array::from_slice(&expected_data, &[50]);
assert_eq!(array.shape(), expected.shape());
assert_array_all_close!(array, expected);
}
#[test]
fn test_linspace_try() {
let array = linspace::<_, f32>(0, 50, LinspaceOptions::default());
assert!(array.is_ok());
let array = linspace::<_, f32>(
0,
50,
LinspaceOptions {
count: -1,
..Default::default()
},
);
assert!(array.is_err());
}
#[test]
#[allow(deprecated)]
fn test_repeat_borrowed() {
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let stream = Stream::thread_local_or_default();
for repeated in [
Array::repeat::<i32>(&source, 2).unwrap(),
repeat::<i32>(&source, 2).unwrap(),
Array::repeat_device::<i32>(&source, 2, &stream).unwrap(),
repeat_device::<i32>(&source, 2, &stream).unwrap(),
] {
assert_eq!(repeated.shape(), &[8]);
assert_eq!(repeated.as_slice::<i32>(), &[0, 0, 1, 1, 2, 2, 3, 3]);
}
for repeated in [
Array::repeat_axis::<i32>(&source, 2, 0).unwrap(),
repeat_axis::<i32>(&source, 2, 0).unwrap(),
Array::repeat_axis_device::<i32>(&source, 2, 0, &stream).unwrap(),
repeat_axis_device::<i32>(&source, 2, 0, &stream).unwrap(),
] {
assert_eq!(repeated.shape(), &[4, 2]);
assert_eq!(repeated.as_slice::<i32>(), &[0, 1, 0, 1, 2, 3, 2, 3]);
}
assert_eq!(source.as_slice::<i32>(), &[0, 1, 2, 3]);
}
#[test]
fn test_repeat() {
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat_axis::<i32>(source, 4, 1).unwrap();
assert_eq!(array.shape(), &[2, 8]);
assert_eq!(array.dtype(), Dtype::Int32);
let data: &[i32] = array.as_slice();
assert_eq!(data, [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
}
#[test]
fn test_repeat_try() {
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat_axis::<i32>(source, 4, 1);
assert!(array.is_ok());
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat_axis::<i32>(source, -1, 1);
assert!(array.is_err());
}
#[test]
fn test_repeat_all() {
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat::<i32>(source, 4).unwrap();
assert_eq!(array.shape(), &[16]);
assert_eq!(array.dtype(), Dtype::Int32);
let data: &[i32] = array.as_slice();
assert_eq!(data, [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
}
#[test]
fn test_repeat_all_try() {
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat::<i32>(source, 4);
assert!(array.is_ok());
let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
let array = Array::repeat::<i32>(source, -1);
assert!(array.is_err());
}
#[test]
fn test_tri() {
let array = Array::tri::<f32>(3, None, None).unwrap();
assert_eq!(array.shape(), &[3, 3]);
assert_eq!(array.dtype(), Dtype::Float32);
let data: &[f32] = array.as_slice();
assert_eq!(data, &[1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0]);
}
#[test]
fn test_full_like() {
let base_int = Array::from_slice(&[1i16, 2, 3], &[3]);
let from_array_with_dtype =
full_like(&base_int, &array!(7.5f32), Some(Dtype::Float16)).unwrap();
assert_eq!(from_array_with_dtype.dtype(), Dtype::Float16);
assert_eq!(from_array_with_dtype.shape(), &[3]);
assert_array_eq(
from_array_with_dtype,
Array::from_slice(&[f16::from_f32(7.5); 3], &[3]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
let from_array_default_dtype = full_like(&base_int, &array!(4.0f32), None).unwrap();
assert_eq!(from_array_default_dtype.dtype(), Dtype::Int16);
assert_array_eq(
from_array_default_dtype,
Array::from_slice(&[4_i16, 4, 4], &[3]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
let from_scalar_with_dtype =
full_like(&base_int, &array!(3.25f32), Some(Dtype::Float32)).unwrap();
assert_eq!(from_scalar_with_dtype.dtype(), Dtype::Float32);
assert_array_eq(
from_scalar_with_dtype,
Array::from_slice(&[3.25_f32; 3], &[3]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
let base_float = Array::from_slice(&[1.0f32, 2.0f32], &[2]);
let from_scalar_default_dtype = full_like(&base_float, &array!(2i32), None).unwrap();
assert_eq!(from_scalar_default_dtype.dtype(), Dtype::Float32);
assert_array_eq(
from_scalar_default_dtype,
Array::from_slice(&[2.0_f32; 2], &[2]),
tolerances::EXACT.rtol,
tolerances::EXACT.atol,
);
}
}