@@ -6,6 +6,7 @@ Implements Item type.
66
77from builtin.type_aliases import Origin
88from memory import UnsafePointer, memset_zero, memcpy
9+ from os import abort
910from sys import simdwidthof
1011from utils import Variant
1112
@@ -18,6 +19,10 @@ alias item = Item
1819
1920@register_passable
2021struct Item (CollectionElement ):
22+ """
23+ Specifies the indices of an item of an array.
24+ """
25+
2126 var _buf : UnsafePointer[Int]
2227 var ndim : Int
2328
@@ -63,15 +68,14 @@ struct Item(CollectionElement):
6368 for i in range (self .ndim):
6469 (self ._buf + i).init_pointee_copy(Int(args[i]))
6570
66- @always_inline (" nodebug" )
6771 fn __init__ (
6872 out self ,
73+ * ,
6974 ndim : Int,
7075 initialized : Bool,
7176 ) raises :
7277 """
7378 Construct Item with number of dimensions.
74-
7579 This method is useful when you want to create a Item with given ndim
7680 without knowing the Item values.
7781
@@ -80,15 +84,62 @@ struct Item(CollectionElement):
8084 initialized: Whether the shape is initialized.
8185 If yes, the values will be set to 0.
8286 If no, the values will be uninitialized.
87+
88+ Raises:
89+ Error: If the number of dimensions is negative.
8390 """
8491 if ndim < 0 :
85- raise Error(" Number of dimensions must be non-negative." )
92+ raise Error(
93+ " \n Error in `Item.__init__()`: "
94+ " Number of dimensions must be non-negative."
95+ )
96+
8697 self .ndim = ndim
8798 self ._buf = UnsafePointer[Int]().alloc(ndim)
8899 if initialized:
89100 for i in range (ndim):
90101 (self ._buf + i).init_pointee_copy(0 )
91102
103+ fn __init__ (out self , idx : Int, shape : NDArrayShape) raises :
104+ """
105+ Get indices of the i-th item of the array of the given shape.
106+ The item traverse the array in C-order.
107+
108+ Args:
109+ idx: The i-th item of the array.
110+ shape: The strides of the array.
111+
112+ Examples:
113+
114+ The following example demonstrates how to get the indices (coordinates)
115+ of the 123-th item of a 3D array with shape (20, 30, 40).
116+
117+ ```console
118+ >>> from numojo.prelude import *
119+ >>> var item = Item(123, Shape(20, 30, 40))
120+ >>> print(item)
121+ Item at index: (0,3,3) Length: 3
122+ ```
123+ """
124+
125+ if (idx < 0 ) or (idx >= shape.size_of_array()):
126+ raise Error(
127+ String(
128+ " \n Error in `Item.__init__(out self, idx: Int, shape:"
129+ " NDArrayShape)`: idx {} out of range [{} , {} )."
130+ ).format(idx, 0 , shape.size_of_array())
131+ )
132+
133+ self .ndim = shape.ndim
134+ self ._buf = UnsafePointer[Int]().alloc(self .ndim)
135+
136+ var strides = NDArrayStrides(shape, order = " C" )
137+ var remainder = idx
138+
139+ for i in range (self .ndim):
140+ (self ._buf + i).init_pointee_copy(remainder // strides._buf[i])
141+ remainder %= strides._buf[i]
142+
92143 @always_inline (" nodebug" )
93144 fn __copyinit__ (mut self , other : Self):
94145 """ Copy construct the tuple.
@@ -115,7 +166,7 @@ struct Item(CollectionElement):
115166
116167 @always_inline (" nodebug" )
117168 fn __getitem__ [T : Indexer](self , idx : T) raises -> Int:
118- """ Get the value at the specified index.
169+ """ Gets the value at the specified index.
119170
120171 Parameter:
121172 T: Type of values. It can be converted to `Int` with `Int()`.
@@ -205,6 +256,37 @@ struct Item(CollectionElement):
205256 + String(self .ndim)
206257 )
207258
259+ # ===-------------------------------------------------------------------===#
260+ # Other methods
261+ # ===-------------------------------------------------------------------===#
262+
263+ fn offset (self , strides : NDArrayStrides) -> Int:
264+ """
265+ Calculates the offset of the item according to strides.
266+
267+ Args:
268+ strides: The strides of the array.
269+
270+ Returns:
271+ The offset of the item.
272+
273+ Examples:
274+
275+ ```mojo
276+ from numojo.prelude import *
277+ var item = Item(1 , 2 , 3 )
278+ var strides = nm.Strides(4 , 3 , 2 )
279+ print (item.offset(strides))
280+ # This prints `16`.
281+ ```
282+ .
283+ """
284+
285+ var offset : Int = 0
286+ for i in range (self .ndim):
287+ offset += self ._buf[i] * strides._buf[i]
288+ return offset
289+
208290
209291@value
210292struct _ItemIter[
0 commit comments