1use crate::array::Array;
2use crate::array::ArrayElement;
3use crate::error::Result;
4use crate::utils::guard::Guarded;
5use crate::{Dtype, Stream};
6use mlx_internal_macros::generate_macro;
7use num_traits::NumCast;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct LinspaceOptions {
12 pub count: i32,
14
15 pub endpoint: bool,
17}
18
19impl Default for LinspaceOptions {
20 fn default() -> Self {
21 Self {
22 count: 50,
23 endpoint: true,
24 }
25 }
26}
27
28impl Array {
29 pub fn zeros<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
42 let dtype = T::DTYPE;
43 zeros_dtype(shape, dtype)
44 }
45
46 #[deprecated(
48 since = "0.26.0",
49 note = "use `with_stream` or `with_device` around `zeros`"
50 )]
51 pub fn zeros_device<T: ArrayElement>(
52 shape: &[i32],
53 stream: impl AsRef<Stream>,
54 ) -> Result<Array> {
55 crate::with_stream(stream.as_ref(), || Self::zeros::<T>(shape))
56 }
57
58 pub fn ones<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
71 let dtype = T::DTYPE;
72 ones_dtype(shape, dtype)
73 }
74
75 #[deprecated(
77 since = "0.26.0",
78 note = "use `with_stream` or `with_device` around `ones`"
79 )]
80 pub fn ones_device<T: ArrayElement>(
81 shape: &[i32],
82 stream: impl AsRef<Stream>,
83 ) -> Result<Array> {
84 crate::with_stream(stream.as_ref(), || Self::ones::<T>(shape))
85 }
86
87 pub fn eye<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
103 let stream = Stream::thread_local_or_default();
104 Array::try_from_op(|res| unsafe {
105 mlx_sys::mlx_eye(
106 res,
107 n,
108 m.unwrap_or(n),
109 k.unwrap_or(0),
110 T::DTYPE.into(),
111 stream.as_ref().as_ptr(),
112 )
113 })
114 }
115
116 #[deprecated(
118 since = "0.26.0",
119 note = "use `with_stream` or `with_device` around `eye`"
120 )]
121 pub fn eye_device<T: ArrayElement>(
122 n: i32,
123 m: Option<i32>,
124 k: Option<i32>,
125 stream: impl AsRef<Stream>,
126 ) -> Result<Array> {
127 crate::with_stream(stream.as_ref(), || Self::eye::<T>(n, m, k))
128 }
129
130 pub fn full<T: ArrayElement>(shape: &[i32], values: impl AsRef<Array>) -> Result<Array> {
148 let stream = Stream::thread_local_or_default();
149 Array::try_from_op(|res| unsafe {
150 mlx_sys::mlx_full(
151 res,
152 shape.as_ptr(),
153 shape.len(),
154 values.as_ref().as_ptr(),
155 T::DTYPE.into(),
156 stream.as_ref().as_ptr(),
157 )
158 })
159 }
160
161 #[deprecated(
163 since = "0.26.0",
164 note = "use `with_stream` or `with_device` around `full`"
165 )]
166 pub fn full_device<T: ArrayElement>(
167 shape: &[i32],
168 values: impl AsRef<Array>,
169 stream: impl AsRef<Stream>,
170 ) -> Result<Array> {
171 crate::with_stream(stream.as_ref(), || Self::full::<T>(shape, values))
172 }
173
174 pub fn identity<T: ArrayElement>(n: i32) -> Result<Array> {
188 let stream = Stream::thread_local_or_default();
189 Array::try_from_op(|res| unsafe {
190 mlx_sys::mlx_identity(res, n, T::DTYPE.into(), stream.as_ref().as_ptr())
191 })
192 }
193
194 #[deprecated(
196 since = "0.26.0",
197 note = "use `with_stream` or `with_device` around `identity`"
198 )]
199 pub fn identity_device<T: ArrayElement>(n: i32, stream: impl AsRef<Stream>) -> Result<Array> {
200 crate::with_stream(stream.as_ref(), || Self::identity::<T>(n))
201 }
202
203 pub fn arange<U, T>(
222 start: impl Into<Option<U>>,
223 stop: U,
224 step: impl Into<Option<U>>,
225 ) -> Result<Array>
226 where
227 U: NumCast,
228 T: ArrayElement,
229 {
230 let stream = Stream::thread_local_or_default();
231 let start: f64 = start.into().and_then(NumCast::from).unwrap_or(0.0);
232 let stop: f64 = NumCast::from(stop).unwrap();
233 let step: f64 = step.into().and_then(NumCast::from).unwrap_or(1.0);
234
235 Array::try_from_op(|res| unsafe {
236 mlx_sys::mlx_arange(
237 res,
238 start,
239 stop,
240 step,
241 T::DTYPE.into(),
242 stream.as_ref().as_ptr(),
243 )
244 })
245 }
246
247 #[deprecated(
249 since = "0.26.0",
250 note = "use `with_stream` or `with_device` around `arange`"
251 )]
252 pub fn arange_device<U, T>(
253 start: impl Into<Option<U>>,
254 stop: U,
255 step: impl Into<Option<U>>,
256 stream: impl AsRef<Stream>,
257 ) -> Result<Array>
258 where
259 U: NumCast,
260 T: ArrayElement,
261 {
262 crate::with_stream(stream.as_ref(), || Self::arange::<U, T>(start, stop, step))
263 }
264
265 #[deprecated(since = "0.26.0", note = "use `ops::linspace` with `LinspaceOptions`")]
267 pub fn linspace<U, T>(start: U, stop: U, count: impl Into<Option<i32>>) -> Result<Array>
268 where
269 U: NumCast,
270 T: ArrayElement,
271 {
272 linspace::<U, T>(
273 start,
274 stop,
275 LinspaceOptions {
276 count: count.into().unwrap_or(50),
277 endpoint: true,
278 },
279 )
280 }
281
282 #[deprecated(
284 since = "0.26.0",
285 note = "use `with_stream` or `with_device` around `ops::linspace`"
286 )]
287 pub fn linspace_device<U, T>(
288 start: U,
289 stop: U,
290 count: impl Into<Option<i32>>,
291 stream: impl AsRef<Stream>,
292 ) -> Result<Array>
293 where
294 U: NumCast,
295 T: ArrayElement,
296 {
297 crate::with_stream(stream.as_ref(), || {
298 linspace::<U, T>(
299 start,
300 stop,
301 LinspaceOptions {
302 count: count.into().unwrap_or(50),
303 endpoint: true,
304 },
305 )
306 })
307 }
308
309 pub fn repeat_axis<T: ArrayElement>(array: Array, count: i32, axis: i32) -> Result<Array> {
326 let stream = Stream::thread_local_or_default();
327 Array::try_from_op(|res| unsafe {
328 mlx_sys::mlx_repeat_axis(res, array.as_ptr(), count, axis, stream.as_ref().as_ptr())
329 })
330 }
331
332 #[deprecated(
334 since = "0.26.0",
335 note = "use `with_stream` or `with_device` around `repeat_axis`"
336 )]
337 pub fn repeat_axis_device<T: ArrayElement>(
338 array: Array,
339 count: i32,
340 axis: i32,
341 stream: impl AsRef<Stream>,
342 ) -> Result<Array> {
343 crate::with_stream(stream.as_ref(), || {
344 Self::repeat_axis::<T>(array, count, axis)
345 })
346 }
347
348 pub fn repeat<T: ArrayElement>(array: Array, count: i32) -> Result<Array> {
364 let stream = Stream::thread_local_or_default();
365 Array::try_from_op(|res| unsafe {
366 mlx_sys::mlx_repeat(res, array.as_ptr(), count, stream.as_ref().as_ptr())
367 })
368 }
369
370 #[deprecated(
372 since = "0.26.0",
373 note = "use `with_stream` or `with_device` around `repeat`"
374 )]
375 pub fn repeat_device<T: ArrayElement>(
376 array: Array,
377 count: i32,
378 stream: impl AsRef<Stream>,
379 ) -> Result<Array> {
380 crate::with_stream(stream.as_ref(), || Self::repeat::<T>(array, count))
381 }
382
383 pub fn tri<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
399 let stream = Stream::thread_local_or_default();
400 Array::try_from_op(|res| unsafe {
401 mlx_sys::mlx_tri(
402 res,
403 n,
404 m.unwrap_or(n),
405 k.unwrap_or(0),
406 T::DTYPE.into(),
407 stream.as_ref().as_ptr(),
408 )
409 })
410 }
411
412 #[deprecated(
414 since = "0.26.0",
415 note = "use `with_stream` or `with_device` around `tri`"
416 )]
417 pub fn tri_device<T: ArrayElement>(
418 n: i32,
419 m: Option<i32>,
420 k: Option<i32>,
421 stream: impl AsRef<Stream>,
422 ) -> Result<Array> {
423 crate::with_stream(stream.as_ref(), || Self::tri::<T>(n, m, k))
424 }
425}
426
427pub fn zeros<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
429 Array::zeros::<T>(shape)
430}
431
432#[generate_macro(customize(forwarding_shim = true))]
434#[deprecated(
435 since = "0.26.0",
436 note = "use `with_stream` or `with_device` around `zeros`"
437)]
438pub fn zeros_device<T: ArrayElement>(
439 shape: &[i32],
440 #[optional] stream: impl AsRef<Stream>,
441) -> Result<Array> {
442 crate::with_stream(stream.as_ref(), || zeros::<T>(shape))
443}
444
445pub fn zeros_like(input: impl AsRef<Array>) -> Result<Array> {
447 let a = input.as_ref();
448 let shape = a.shape();
449 let dtype = a.dtype();
450 zeros_dtype(shape, dtype)
451}
452
453#[generate_macro(customize(forwarding_shim = true))]
455#[deprecated(
456 since = "0.26.0",
457 note = "use `with_stream` or `with_device` around `zeros_like`"
458)]
459pub fn zeros_like_device(
460 input: impl AsRef<Array>,
461 #[optional] stream: impl AsRef<Stream>,
462) -> Result<Array> {
463 crate::with_stream(stream.as_ref(), || zeros_like(input))
464}
465
466pub fn zeros_dtype(shape: &[i32], dtype: Dtype) -> Result<Array> {
468 let stream = Stream::thread_local_or_default();
469 Array::try_from_op(|res| unsafe {
470 mlx_sys::mlx_zeros(
471 res,
472 shape.as_ptr(),
473 shape.len(),
474 dtype.into(),
475 stream.as_ref().as_ptr(),
476 )
477 })
478}
479
480#[generate_macro(customize(forwarding_shim = true))]
482#[deprecated(
483 since = "0.26.0",
484 note = "use `with_stream` or `with_device` around `zeros_dtype`"
485)]
486pub fn zeros_dtype_device(
487 shape: &[i32],
488 dtype: Dtype,
489 #[optional] stream: impl AsRef<Stream>,
490) -> Result<Array> {
491 crate::with_stream(stream.as_ref(), || zeros_dtype(shape, dtype))
492}
493
494pub fn ones<T: ArrayElement>(shape: &[i32]) -> Result<Array> {
496 Array::ones::<T>(shape)
497}
498
499#[generate_macro(customize(forwarding_shim = true))]
501#[deprecated(
502 since = "0.26.0",
503 note = "use `with_stream` or `with_device` around `ones`"
504)]
505pub fn ones_device<T: ArrayElement>(
506 shape: &[i32],
507 #[optional] stream: impl AsRef<Stream>,
508) -> Result<Array> {
509 crate::with_stream(stream.as_ref(), || ones::<T>(shape))
510}
511
512pub fn ones_like(input: impl AsRef<Array>) -> Result<Array> {
514 let a = input.as_ref();
515 let shape = a.shape();
516 let dtype = a.dtype();
517 ones_dtype(shape, dtype)
518}
519
520#[generate_macro(customize(forwarding_shim = true))]
522#[deprecated(
523 since = "0.26.0",
524 note = "use `with_stream` or `with_device` around `ones_like`"
525)]
526pub fn ones_like_device(
527 input: impl AsRef<Array>,
528 #[optional] stream: impl AsRef<Stream>,
529) -> Result<Array> {
530 crate::with_stream(stream.as_ref(), || ones_like(input))
531}
532
533pub fn full_like(
557 input: impl AsRef<Array>,
558 values: impl AsRef<Array>,
559 dtype: impl Into<Option<Dtype>>,
560) -> Result<Array> {
561 let stream = Stream::thread_local_or_default();
562 let a = input.as_ref();
563 let dtype = dtype.into().unwrap_or_else(|| a.dtype());
564 Array::try_from_op(|res| unsafe {
565 mlx_sys::mlx_full_like(
566 res,
567 a.as_ptr(),
568 values.as_ref().as_ptr(),
569 dtype.into(),
570 stream.as_ref().as_ptr(),
571 )
572 })
573}
574
575#[generate_macro(customize(forwarding_shim = true))]
577#[deprecated(
578 since = "0.26.0",
579 note = "use `with_stream` or `with_device` around `full_like`"
580)]
581pub fn full_like_device(
582 input: impl AsRef<Array>,
583 values: impl AsRef<Array>,
584 #[optional] dtype: impl Into<Option<Dtype>>,
585 #[optional] stream: impl AsRef<Stream>,
586) -> Result<Array> {
587 crate::with_stream(stream.as_ref(), || full_like(input, values, dtype))
588}
589
590pub fn ones_dtype(shape: &[i32], dtype: Dtype) -> Result<Array> {
592 let stream = Stream::thread_local_or_default();
593 Array::try_from_op(|res| unsafe {
594 mlx_sys::mlx_ones(
595 res,
596 shape.as_ptr(),
597 shape.len(),
598 dtype.into(),
599 stream.as_ref().as_ptr(),
600 )
601 })
602}
603
604#[generate_macro(customize(forwarding_shim = true))]
606#[deprecated(
607 since = "0.26.0",
608 note = "use `with_stream` or `with_device` around `ones_dtype`"
609)]
610pub fn ones_dtype_device(
611 shape: &[i32],
612 dtype: Dtype,
613 #[optional] stream: impl AsRef<Stream>,
614) -> Result<Array> {
615 crate::with_stream(stream.as_ref(), || ones_dtype(shape, dtype))
616}
617
618pub fn eye<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
620 Array::eye::<T>(n, m, k)
621}
622
623#[generate_macro(customize(forwarding_shim = true))]
625#[deprecated(
626 since = "0.26.0",
627 note = "use `with_stream` or `with_device` around `eye`"
628)]
629pub fn eye_device<T: ArrayElement>(
630 n: i32,
631 #[optional] m: Option<i32>,
632 #[optional] k: Option<i32>,
633 #[optional] stream: impl AsRef<Stream>,
634) -> Result<Array> {
635 crate::with_stream(stream.as_ref(), || eye::<T>(n, m, k))
636}
637
638pub fn full<T: ArrayElement>(shape: &[i32], values: impl AsRef<Array>) -> Result<Array> {
640 Array::full::<T>(shape, values)
641}
642
643#[generate_macro(customize(forwarding_shim = true))]
645#[deprecated(
646 since = "0.26.0",
647 note = "use `with_stream` or `with_device` around `full`"
648)]
649pub fn full_device<T: ArrayElement>(
650 shape: &[i32],
651 values: impl AsRef<Array>,
652 #[optional] stream: impl AsRef<Stream>,
653) -> Result<Array> {
654 crate::with_stream(stream.as_ref(), || full::<T>(shape, values))
655}
656
657pub fn identity<T: ArrayElement>(n: i32) -> Result<Array> {
659 Array::identity::<T>(n)
660}
661
662#[generate_macro(customize(forwarding_shim = true))]
664#[deprecated(
665 since = "0.26.0",
666 note = "use `with_stream` or `with_device` around `identity`"
667)]
668pub fn identity_device<T: ArrayElement>(
669 n: i32,
670 #[optional] stream: impl AsRef<Stream>,
671) -> Result<Array> {
672 crate::with_stream(stream.as_ref(), || identity::<T>(n))
673}
674
675pub fn arange<U, T>(
677 start: impl Into<Option<U>>,
678 stop: U,
679 step: impl Into<Option<U>>,
680) -> Result<Array>
681where
682 U: NumCast,
683 T: ArrayElement,
684{
685 Array::arange::<U, T>(start, stop, step)
686}
687
688#[generate_macro(customize(forwarding_shim = true))]
690#[deprecated(
691 since = "0.26.0",
692 note = "use `with_stream` or `with_device` around `arange`"
693)]
694pub fn arange_device<U, T>(
695 #[optional] start: impl Into<Option<U>>,
696 #[named] stop: U,
697 #[optional] step: impl Into<Option<U>>,
698 #[optional] stream: impl AsRef<Stream>,
699) -> Result<Array>
700where
701 U: NumCast,
702 T: ArrayElement,
703{
704 crate::with_stream(stream.as_ref(), || arange::<U, T>(start, stop, step))
705}
706
707pub fn linspace<U, T>(start: U, stop: U, options: LinspaceOptions) -> Result<Array>
731where
732 U: NumCast,
733 T: ArrayElement,
734{
735 let stream = Stream::thread_local_or_default();
736 let start: f64 = NumCast::from(start).unwrap();
737 let stop: f64 = NumCast::from(stop).unwrap();
738 Array::try_from_op(|res| unsafe {
739 mlx_sys::mlx_linspace_endpoint(
740 res,
741 start,
742 stop,
743 options.count,
744 options.endpoint,
745 T::DTYPE.into(),
746 stream.as_ref().as_ptr(),
747 )
748 })
749}
750
751#[generate_macro(customize(forwarding_shim = true))]
753#[deprecated(
754 since = "0.26.0",
755 note = "use `with_stream` or `with_device` around `linspace`"
756)]
757pub fn linspace_device<U, T>(
758 start: U,
759 stop: U,
760 #[optional] count: impl Into<Option<i32>>,
761 #[optional] stream: impl AsRef<Stream>,
762) -> Result<Array>
763where
764 U: NumCast,
765 T: ArrayElement,
766{
767 crate::with_stream(stream.as_ref(), || {
768 linspace::<U, T>(
769 start,
770 stop,
771 LinspaceOptions {
772 count: count.into().unwrap_or(50),
773 endpoint: true,
774 },
775 )
776 })
777}
778
779pub fn repeat_axis<T: ArrayElement>(array: Array, count: i32, axis: i32) -> Result<Array> {
781 Array::repeat_axis::<T>(array, count, axis)
782}
783
784#[generate_macro(customize(forwarding_shim = true))]
786#[deprecated(
787 since = "0.26.0",
788 note = "use `with_stream` or `with_device` around `repeat_axis`"
789)]
790pub fn repeat_axis_device<T: ArrayElement>(
791 array: Array,
792 count: i32,
793 axis: i32,
794 #[optional] stream: impl AsRef<Stream>,
795) -> Result<Array> {
796 crate::with_stream(stream.as_ref(), || repeat_axis::<T>(array, count, axis))
797}
798
799pub fn repeat<T: ArrayElement>(array: Array, count: i32) -> Result<Array> {
801 Array::repeat::<T>(array, count)
802}
803
804#[generate_macro(customize(forwarding_shim = true))]
806#[deprecated(
807 since = "0.26.0",
808 note = "use `with_stream` or `with_device` around `repeat`"
809)]
810pub fn repeat_device<T: ArrayElement>(
811 array: Array,
812 count: i32,
813 #[optional] stream: impl AsRef<Stream>,
814) -> Result<Array> {
815 crate::with_stream(stream.as_ref(), || repeat::<T>(array, count))
816}
817
818pub fn tri<T: ArrayElement>(n: i32, m: Option<i32>, k: Option<i32>) -> Result<Array> {
820 Array::tri::<T>(n, m, k)
821}
822
823#[generate_macro(customize(forwarding_shim = true))]
825#[deprecated(
826 since = "0.26.0",
827 note = "use `with_stream` or `with_device` around `tri`"
828)]
829pub fn tri_device<T: ArrayElement>(
830 n: i32,
831 #[optional] m: Option<i32>,
832 #[optional] k: Option<i32>,
833 #[optional] stream: impl AsRef<Stream>,
834) -> Result<Array> {
835 crate::with_stream(stream.as_ref(), || tri::<T>(n, m, k))
836}
837
838pub fn tril(a: impl AsRef<Array>, k: impl Into<Option<i32>>) -> Result<Array> {
846 let stream = Stream::thread_local_or_default();
847 let a = a.as_ref();
848 let k = k.into().unwrap_or(0);
849 Array::try_from_op(|res| unsafe {
850 mlx_sys::mlx_tril(res, a.as_ptr(), k, stream.as_ref().as_ptr())
851 })
852}
853
854#[generate_macro(customize(forwarding_shim = true))]
856#[deprecated(
857 since = "0.26.0",
858 note = "use `with_stream` or `with_device` around `tril`"
859)]
860pub fn tril_device(
861 a: impl AsRef<Array>,
862 #[optional] k: impl Into<Option<i32>>,
863 #[optional] stream: impl AsRef<Stream>,
864) -> Result<Array> {
865 crate::with_stream(stream.as_ref(), || tril(a, k))
866}
867
868pub fn triu(a: impl AsRef<Array>, k: impl Into<Option<i32>>) -> Result<Array> {
875 let stream = Stream::thread_local_or_default();
876 let a = a.as_ref();
877 let k = k.into().unwrap_or(0);
878 Array::try_from_op(|res| unsafe {
879 mlx_sys::mlx_triu(res, a.as_ptr(), k, stream.as_ref().as_ptr())
880 })
881}
882
883#[generate_macro(customize(forwarding_shim = true))]
885#[deprecated(
886 since = "0.26.0",
887 note = "use `with_stream` or `with_device` around `triu`"
888)]
889pub fn triu_device(
890 a: impl AsRef<Array>,
891 #[optional] k: impl Into<Option<i32>>,
892 #[optional] stream: impl AsRef<Stream>,
893) -> Result<Array> {
894 crate::with_stream(stream.as_ref(), || triu(a, k))
895}
896
897#[cfg(test)]
898mod tests {
899 use super::*;
900 use crate::{
901 array, dtype::Dtype, test_utils::assert_array_eq, test_utils::tolerances, with_device,
902 Device,
903 };
904 use half::f16;
905
906 #[test]
907 fn test_zeros() {
908 let array = Array::zeros::<f32>(&[2, 3]).unwrap();
909 assert_eq!(array.shape(), &[2, 3]);
910 assert_eq!(array.dtype(), Dtype::Float32);
911
912 let data: &[f32] = array.as_slice();
913 assert_eq!(data, &[0.0; 6]);
914 }
915
916 #[test]
917 fn test_zeros_try() {
918 let array = Array::zeros::<f32>(&[2, 3]);
919 assert!(array.is_ok());
920
921 let array = Array::zeros::<f32>(&[-1, 3]);
922 assert!(array.is_err());
923 }
924
925 #[test]
926 fn test_ones() {
927 let array = Array::ones::<f16>(&[2, 3]).unwrap();
928 assert_eq!(array.shape(), &[2, 3]);
929 assert_eq!(array.dtype(), Dtype::Float16);
930
931 let data: &[f16] = array.as_slice();
932 assert_eq!(data, &[f16::from_f32(1.0); 6]);
933 }
934
935 #[test]
936 fn test_eye() {
937 let array = Array::eye::<f32>(3, None, None).unwrap();
938 assert_eq!(array.shape(), &[3, 3]);
939 assert_eq!(array.dtype(), Dtype::Float32);
940
941 let data: &[f32] = array.as_slice();
942 assert_eq!(data, &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]);
943 }
944
945 #[test]
946 fn test_full_scalar() {
947 let array = Array::full::<f32>(&[2, 3], array!(7f32)).unwrap();
948 assert_eq!(array.shape(), &[2, 3]);
949 assert_eq!(array.dtype(), Dtype::Float32);
950
951 assert_array_eq(
952 array,
953 Array::from_slice(&[7.0; 6], &[2, 3]),
954 tolerances::EXACT.rtol,
955 tolerances::EXACT.atol,
956 );
957 }
958
959 #[test]
960 fn test_full_array() {
961 let source = with_device(Device::cpu(), || Array::zeros::<f32>(&[1, 3])).unwrap();
962 let array = Array::full::<f32>(&[2, 3], source).unwrap();
963 assert_eq!(array.shape(), &[2, 3]);
964 assert_eq!(array.dtype(), Dtype::Float32);
965
966 assert_array_eq(
967 array,
968 Array::from_slice(&[0.0; 6], &[2, 3]),
969 tolerances::EXACT.rtol,
970 tolerances::EXACT.atol,
971 );
972 }
973
974 #[test]
975 fn test_full_try() {
976 let source = Array::zeros::<f32>(&[1, 3]).unwrap();
977 let array = Array::full::<f32>(&[2, 3], source);
978 assert!(array.is_ok());
979
980 let source = Array::zeros::<f32>(&[1, 3]).unwrap();
981 let array = Array::full::<f32>(&[-1, 3], source);
982 assert!(array.is_err());
983 }
984
985 #[test]
986 fn test_identity() {
987 let array = Array::identity::<f32>(3).unwrap();
988 assert_eq!(array.shape(), &[3, 3]);
989 assert_eq!(array.dtype(), Dtype::Float32);
990
991 let data: &[f32] = array.as_slice();
992 assert_eq!(data, &[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]);
993 }
994
995 #[test]
996 fn test_arange() {
997 let array = Array::arange::<_, f32>(None, 50, None).unwrap();
998 assert_eq!(array.shape(), &[50]);
999 assert_eq!(array.dtype(), Dtype::Float32);
1000
1001 let data: &[f32] = array.as_slice();
1002 let expected: Vec<f32> = (0..50).map(|x| x as f32).collect();
1003 assert_eq!(data, expected.as_slice());
1004
1005 let array = Array::arange::<_, i32>(0, 50, None).unwrap();
1006 assert_eq!(array.shape(), &[50]);
1007 assert_eq!(array.dtype(), Dtype::Int32);
1008
1009 let data: &[i32] = array.as_slice();
1010 let expected: Vec<i32> = (0..50).collect();
1011 assert_eq!(data, expected.as_slice());
1012
1013 let result = Array::arange::<_, bool>(None, 50, None);
1014 assert!(result.is_err());
1015
1016 let result = Array::arange::<_, f32>(f64::NEG_INFINITY, 50.0, None);
1017 assert!(result.is_err());
1018
1019 let result = Array::arange::<_, f32>(0.0, f64::INFINITY, None);
1020 assert!(result.is_err());
1021
1022 let result = Array::arange::<_, f32>(0.0, 50.0, f32::NAN);
1023 assert!(result.is_err());
1024
1025 let result = Array::arange::<_, f32>(f32::NAN, 50.0, None);
1026 assert!(result.is_err());
1027
1028 let result = Array::arange::<_, f32>(0.0, f32::NAN, None);
1029 assert!(result.is_err());
1030
1031 let result = Array::arange::<_, f32>(0, i32::MAX as i64 + 1, None);
1032 assert!(result.is_err());
1033 }
1034
1035 #[test]
1036 fn test_linspace_int() {
1037 let array = Array::linspace::<_, f32>(0, 50, None).unwrap();
1038 assert_eq!(array.shape(), &[50]);
1039 assert_eq!(array.dtype(), Dtype::Float32);
1040
1041 let expected_data: Vec<f32> = (0..50).map(|x| x as f32 * (50.0 / 49.0)).collect();
1042 let expected = Array::from_slice(&expected_data, &[50]);
1043 assert_eq!(array.shape(), expected.shape());
1044 assert_array_all_close!(array, expected);
1045 }
1046
1047 #[test]
1048 fn test_linspace_float() {
1049 let array = Array::linspace::<_, f32>(0., 50., None).unwrap();
1050 assert_eq!(array.shape(), &[50]);
1051 assert_eq!(array.dtype(), Dtype::Float32);
1052
1053 let expected_data: Vec<f32> = (0..50).map(|x| x as f32 * (50.0 / 49.0)).collect();
1054 let expected = Array::from_slice(&expected_data, &[50]);
1055 assert_eq!(array.shape(), expected.shape());
1056 assert_array_all_close!(array, expected);
1057 }
1058
1059 #[test]
1060 fn test_linspace_try() {
1061 let array = Array::linspace::<_, f32>(0, 50, None);
1062 assert!(array.is_ok());
1063
1064 let array = Array::linspace::<_, f32>(0, 50, Some(-1));
1065 assert!(array.is_err());
1066 }
1067
1068 #[test]
1069 fn test_repeat() {
1070 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1071 let array = Array::repeat_axis::<i32>(source, 4, 1).unwrap();
1072 assert_eq!(array.shape(), &[2, 8]);
1073 assert_eq!(array.dtype(), Dtype::Int32);
1074
1075 let data: &[i32] = array.as_slice();
1076 assert_eq!(data, [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
1077 }
1078
1079 #[test]
1080 fn test_repeat_try() {
1081 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1082 let array = Array::repeat_axis::<i32>(source, 4, 1);
1083 assert!(array.is_ok());
1084
1085 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1086 let array = Array::repeat_axis::<i32>(source, -1, 1);
1087 assert!(array.is_err());
1088 }
1089
1090 #[test]
1091 fn test_repeat_all() {
1092 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1093 let array = Array::repeat::<i32>(source, 4).unwrap();
1094 assert_eq!(array.shape(), &[16]);
1095 assert_eq!(array.dtype(), Dtype::Int32);
1096
1097 let data: &[i32] = array.as_slice();
1098 assert_eq!(data, [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]);
1099 }
1100
1101 #[test]
1102 fn test_repeat_all_try() {
1103 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1104 let array = Array::repeat::<i32>(source, 4);
1105 assert!(array.is_ok());
1106
1107 let source = Array::from_slice(&[0, 1, 2, 3], &[2, 2]);
1108 let array = Array::repeat::<i32>(source, -1);
1109 assert!(array.is_err());
1110 }
1111
1112 #[test]
1113 fn test_tri() {
1114 let array = Array::tri::<f32>(3, None, None).unwrap();
1115 assert_eq!(array.shape(), &[3, 3]);
1116 assert_eq!(array.dtype(), Dtype::Float32);
1117
1118 let data: &[f32] = array.as_slice();
1119 assert_eq!(data, &[1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0]);
1120 }
1121
1122 #[test]
1124 fn test_full_like() {
1125 let base_int = Array::from_slice(&[1i16, 2, 3], &[3]);
1127 let from_array_with_dtype =
1128 full_like(&base_int, &array!(7.5f32), Some(Dtype::Float16)).unwrap();
1129 assert_eq!(from_array_with_dtype.dtype(), Dtype::Float16);
1130 assert_eq!(from_array_with_dtype.shape(), &[3]);
1131
1132 assert_array_eq(
1133 from_array_with_dtype,
1134 Array::from_slice(&[f16::from_f32(7.5); 3], &[3]),
1135 tolerances::EXACT.rtol,
1136 tolerances::EXACT.atol,
1137 );
1138
1139 let from_array_default_dtype = full_like(&base_int, &array!(4.0f32), None).unwrap();
1141 assert_eq!(from_array_default_dtype.dtype(), Dtype::Int16);
1142 assert_array_eq(
1143 from_array_default_dtype,
1144 Array::from_slice(&[4_i16, 4, 4], &[3]),
1145 tolerances::EXACT.rtol,
1146 tolerances::EXACT.atol,
1147 );
1148
1149 let from_scalar_with_dtype =
1151 full_like(&base_int, &array!(3.25f32), Some(Dtype::Float32)).unwrap();
1152 assert_eq!(from_scalar_with_dtype.dtype(), Dtype::Float32);
1153 assert_array_eq(
1154 from_scalar_with_dtype,
1155 Array::from_slice(&[3.25_f32; 3], &[3]),
1156 tolerances::EXACT.rtol,
1157 tolerances::EXACT.atol,
1158 );
1159
1160 let base_float = Array::from_slice(&[1.0f32, 2.0f32], &[2]);
1162 let from_scalar_default_dtype = full_like(&base_float, &array!(2i32), None).unwrap();
1163 assert_eq!(from_scalar_default_dtype.dtype(), Dtype::Float32);
1164 assert_array_eq(
1165 from_scalar_default_dtype,
1166 Array::from_slice(&[2.0_f32; 2], &[2]),
1167 tolerances::EXACT.rtol,
1168 tolerances::EXACT.atol,
1169 );
1170 }
1171}