@@ -124,19 +124,20 @@ def __init__(
124
124
ctypes .pointer (_cshape .c_array ), ctypes .pointer (strides_cshape ), dtype .c_api_value ,
125
125
pointer_source .value ))
126
126
127
- def __str__ (self ) -> str : # FIXME
127
+ def __str__ (self ) -> str :
128
+ # TODO change the look of array str. E.g., like np.array
128
129
if not _in_display_dims_limit (self .shape ):
129
130
return _metadata_string (self .dtype , self .shape )
130
131
131
132
return _metadata_string (self .dtype ) + _array_as_str (self )
132
133
133
- def __repr__ (self ) -> str : # FIXME
134
+ def __repr__ (self ) -> str :
134
135
# return _metadata_string(self.dtype, self.shape)
135
136
# TODO change the look of array representation. E.g., like np.array
136
137
return _array_as_str (self )
137
138
138
139
def __len__ (self ) -> int :
139
- return self .shape [0 ] if self .shape else 0 # type: ignore[return-value]
140
+ return self .shape [0 ] if self .shape else 0
140
141
141
142
# Arithmetic Operators
142
143
@@ -475,17 +476,17 @@ def T(self) -> Array:
475
476
raise NotImplementedError
476
477
477
478
@property
478
- def size (self ) -> None | int :
479
+ def size (self ) -> int :
479
480
# NOTE previously - elements()
480
481
out = c_dim_t (0 )
481
482
safe_call (backend .get ().af_get_elements (ctypes .pointer (out ), self .arr ))
482
483
return out .value
483
484
484
485
@property
485
486
def ndim (self ) -> int :
486
- nd = ctypes .c_uint (0 )
487
- safe_call (backend .get ().af_get_numdims (ctypes .pointer (nd ), self .arr ))
488
- return nd .value
487
+ out = ctypes .c_uint (0 )
488
+ safe_call (backend .get ().af_get_numdims (ctypes .pointer (out ), self .arr ))
489
+ return out .value
489
490
490
491
@property
491
492
def shape (self ) -> ShapeType :
@@ -510,6 +511,62 @@ def scalar(self) -> int | float | bool | complex:
510
511
safe_call (backend .get ().af_get_scalar (ctypes .pointer (out ), self .arr ))
511
512
return out .value # type: ignore[no-any-return] # FIXME
512
513
514
+ def is_empty (self ) -> bool :
515
+ """
516
+ Check if the array is empty i.e. it has no elements.
517
+ """
518
+ out = ctypes .c_bool ()
519
+ safe_call (backend .get ().af_is_empty (ctypes .pointer (out ), self .arr ))
520
+ return out .value
521
+
522
+ def to_list (self , row_major : bool = False ) -> list : # FIXME return typings
523
+ if self .is_empty ():
524
+ return []
525
+
526
+ array = _reorder (self ) if row_major else self
527
+ ctypes_array = _get_ctypes_array (array )
528
+
529
+ if array .ndim == 1 :
530
+ return list (ctypes_array )
531
+
532
+ out = []
533
+ for i in range (array .size ):
534
+ idx = i
535
+ sub_list = []
536
+ for j in range (array .ndim ):
537
+ div = array .shape [j ]
538
+ sub_list .append (idx % div )
539
+ idx //= div
540
+ out .append (ctypes_array [sub_list [::- 1 ]]) # type: ignore[call-overload] # FIXME
541
+ return out
542
+
543
+ def to_ctype_array (self , row_major : bool = False ) -> ctypes .Array :
544
+ if self .is_empty ():
545
+ raise RuntimeError ("Can not convert an empty array to ctype." )
546
+
547
+ array = _reorder (self ) if row_major else self
548
+ return _get_ctypes_array (array )
549
+
550
+
551
+ def _get_ctypes_array (array : Array ) -> ctypes .Array :
552
+ c_shape = array .dtype .c_type * array .size
553
+ ctypes_array = c_shape ()
554
+ safe_call (backend .get ().af_get_data_ptr (ctypes .pointer (ctypes_array ), array .arr ))
555
+ return ctypes_array
556
+
557
+
558
+ def _reorder (array : Array ) -> Array :
559
+ """
560
+ Returns a reordered array to help interoperate with row major formats.
561
+ """
562
+ if array .ndim == 1 :
563
+ return array
564
+
565
+ out = Array ()
566
+ c_shape = CShape (* (tuple (reversed (range (array .ndim ))) + tuple (range (array .ndim , 4 ))))
567
+ safe_call (backend .get ().af_reorder (ctypes .pointer (out .arr ), array .arr , * c_shape ))
568
+ return out
569
+
513
570
514
571
def _array_as_str (array : Array ) -> str :
515
572
arr_str = ctypes .c_char_p (0 )
0 commit comments