Skip to content

Shaped array

shaped_array

ShapedArray dataclass

Bases: Generic[_T]

A helper structure to represent instances of type MemRefType, TensorType, VectorType, etc. in the interpreter.

Source code in xdsl/interpreters/shaped_array.py
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
@dataclass
class ShapedArray(Generic[_T]):
    """
    A helper structure to represent instances of type MemRefType, TensorType, VectorType, etc.
    in the interpreter.
    """

    _data: TypedPtr[_T]
    shape: list[int]

    @property
    def element_type(self) -> PackableType[_T]:
        return self._data.xtype

    @property
    def size(self) -> int:
        return prod(self.shape)

    @property
    def data(self) -> list[_T]:
        return self._data.get_list(self.size)

    @property
    def data_ptr(self) -> TypedPtr[_T]:
        return self._data

    def copy(self) -> Self:
        return type(self)(self._data.copy(), self.shape.copy())

    def with_shape(self, new_shape: Sequence[int]) -> Self:
        return type(self)(self._data.copy(), list(new_shape))

    def offset(self, index: Sequence[int]) -> int:
        """
        Returns the index of the element in `self.data` for a given tuple of indices
        """
        if len(index) != len(self.shape):
            raise ValueError(f"Invalid indices {index} for shape {self.shape}")
        # For each dimension, the number of elements in the nested arrays
        strides = ShapedType.strides_for_shape(self.shape)
        offset = sum(i * stride for i, stride in zip(index, strides, strict=True))
        return offset

    def load(self, index: Sequence[int]) -> _T:
        """
        Returns the element for a given tuple of indices
        """
        return self._data[self.offset(index)]

    def store(self, index: Sequence[int], value: _T) -> None:
        """
        Returns the element for a given tuple of indices
        """
        self._data[self.offset(index)] = value

    def indices(self) -> Iterable[tuple[int, ...]]:
        """
        Iterates over the indices of this shaped array.
        """
        yield from product(*(range(dim) for dim in self.shape))

    def transposed(self, dim0: int, dim1: int) -> Self:
        """
        Returns a new ShapedArray, with the dimensions `dim0` and `dim1` transposed.
        """
        new_shape = list(self.shape)
        new_shape[dim0], new_shape[dim1] = new_shape[dim1], new_shape[dim0]
        old_list = self.data
        new_data = type(self.data_ptr).new(old_list, xtype=self.data_ptr.xtype)

        result = type(self)(new_data, new_shape)

        for source_index in self.indices():
            dest_index = list(source_index)
            dest_index[dim0], dest_index[dim1] = source_index[dim1], source_index[dim0]
            result.store(tuple(dest_index), self.load(source_index))

        return result

    def __format__(self, format_spec: str) -> str:
        prod_dims: list[int] = list(accumulate(reversed(self.shape), operator.mul))
        size = prod_dims[-1]
        result = "[" * len(self.shape)

        for i in range(size):
            d = self._data[i]
            if i:
                n = sum(not i % p for p in prod_dims)
                result += "]" * n
                result += ", "
                result += "[" * n
            result += f"{d}"

        result += "]" * len(self.shape)
        return result

shape: list[int] instance-attribute

element_type: PackableType[_T] property

size: int property

data: list[_T] property

data_ptr: TypedPtr[_T] property

__init__(_data: TypedPtr[_T], shape: list[int]) -> None

copy() -> Self

Source code in xdsl/interpreters/shaped_array.py
44
45
def copy(self) -> Self:
    return type(self)(self._data.copy(), self.shape.copy())

with_shape(new_shape: Sequence[int]) -> Self

Source code in xdsl/interpreters/shaped_array.py
47
48
def with_shape(self, new_shape: Sequence[int]) -> Self:
    return type(self)(self._data.copy(), list(new_shape))

offset(index: Sequence[int]) -> int

Returns the index of the element in self.data for a given tuple of indices

Source code in xdsl/interpreters/shaped_array.py
50
51
52
53
54
55
56
57
58
59
def offset(self, index: Sequence[int]) -> int:
    """
    Returns the index of the element in `self.data` for a given tuple of indices
    """
    if len(index) != len(self.shape):
        raise ValueError(f"Invalid indices {index} for shape {self.shape}")
    # For each dimension, the number of elements in the nested arrays
    strides = ShapedType.strides_for_shape(self.shape)
    offset = sum(i * stride for i, stride in zip(index, strides, strict=True))
    return offset

load(index: Sequence[int]) -> _T

Returns the element for a given tuple of indices

Source code in xdsl/interpreters/shaped_array.py
61
62
63
64
65
def load(self, index: Sequence[int]) -> _T:
    """
    Returns the element for a given tuple of indices
    """
    return self._data[self.offset(index)]

store(index: Sequence[int], value: _T) -> None

Returns the element for a given tuple of indices

Source code in xdsl/interpreters/shaped_array.py
67
68
69
70
71
def store(self, index: Sequence[int], value: _T) -> None:
    """
    Returns the element for a given tuple of indices
    """
    self._data[self.offset(index)] = value

indices() -> Iterable[tuple[int, ...]]

Iterates over the indices of this shaped array.

Source code in xdsl/interpreters/shaped_array.py
73
74
75
76
77
def indices(self) -> Iterable[tuple[int, ...]]:
    """
    Iterates over the indices of this shaped array.
    """
    yield from product(*(range(dim) for dim in self.shape))

transposed(dim0: int, dim1: int) -> Self

Returns a new ShapedArray, with the dimensions dim0 and dim1 transposed.

Source code in xdsl/interpreters/shaped_array.py
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def transposed(self, dim0: int, dim1: int) -> Self:
    """
    Returns a new ShapedArray, with the dimensions `dim0` and `dim1` transposed.
    """
    new_shape = list(self.shape)
    new_shape[dim0], new_shape[dim1] = new_shape[dim1], new_shape[dim0]
    old_list = self.data
    new_data = type(self.data_ptr).new(old_list, xtype=self.data_ptr.xtype)

    result = type(self)(new_data, new_shape)

    for source_index in self.indices():
        dest_index = list(source_index)
        dest_index[dim0], dest_index[dim1] = source_index[dim1], source_index[dim0]
        result.store(tuple(dest_index), self.load(source_index))

    return result

__format__(format_spec: str) -> str

Source code in xdsl/interpreters/shaped_array.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def __format__(self, format_spec: str) -> str:
    prod_dims: list[int] = list(accumulate(reversed(self.shape), operator.mul))
    size = prod_dims[-1]
    result = "[" * len(self.shape)

    for i in range(size):
        d = self._data[i]
        if i:
            n = sum(not i % p for p in prod_dims)
            result += "]" * n
            result += ", "
            result += "[" * n
        result += f"{d}"

    result += "]" * len(self.shape)
    return result