Skip to content

Commit c43dcfb

Browse files
authored
Merge pull request #819 from hameerabbasi/format-factories
Introduce format factories
2 parents e9b560b + 67d45f1 commit c43dcfb

File tree

8 files changed

+203
-123
lines changed

8 files changed

+203
-123
lines changed

ci/Finch-array-api-xfails.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ array_api_tests/test_signatures.py::test_array_method_signature[__setitem__]
7070
# not implemented
7171
array_api_tests/test_creation_functions.py::test_meshgrid
7272

73+
# buggy
74+
array_api_tests/test_creation_functions.py::test_full_like
75+
7376
# test_array_object
7477

7578
array_api_tests/test_array_object.py::test_getitem

sparse/mlir_backend/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"to enable MLIR backend."
1010
) from e
1111

12-
from . import levels
12+
from . import formats
1313
from ._array import Array
1414
from ._conversions import asarray, from_constituent_arrays, to_numpy, to_scipy
1515
from ._dtypes import (
@@ -37,7 +37,7 @@
3737
"asdtype",
3838
"to_numpy",
3939
"to_scipy",
40-
"levels",
40+
"formats",
4141
"reshape",
4242
"from_constituent_arrays",
4343
"int8",

sparse/mlir_backend/_array.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy as np
22

33
from ._dtypes import DType
4-
from .levels import StorageFormat
4+
from .formats import ConcreteFormat
55

66

77
class Array:
@@ -26,7 +26,7 @@ def dtype(self) -> DType:
2626
return self._storage.get_storage_format().dtype
2727

2828
@property
29-
def format(self) -> StorageFormat:
29+
def format(self) -> ConcreteFormat:
3030
return self._storage.get_storage_format()
3131

3232
def _get_mlir_type(self):
@@ -41,7 +41,7 @@ def copy(self) -> "Array":
4141
arrs = tuple(arr.copy() for arr in self.get_constituent_arrays())
4242
return from_constituent_arrays(format=self.format, arrays=arrs, shape=self.shape)
4343

44-
def asformat(self, format: StorageFormat) -> "Array":
44+
def asformat(self, format: ConcreteFormat) -> "Array":
4545
from ._ops import asformat
4646

4747
return asformat(self, format=format)

sparse/mlir_backend/_conversions.py

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import numpy as np
44

55
from ._array import Array
6-
from .levels import Level, LevelFormat, LevelProperties, StorageFormat, get_storage_format
6+
from .formats import ConcreteFormat, Coo, Csf, Dense, Level, LevelFormat
77

88
try:
99
import scipy.sparse as sps
@@ -31,26 +31,17 @@ def _from_numpy(arr: np.ndarray, copy: bool | None = None) -> Array:
3131
if copy:
3232
arr = arr.copy(order="C")
3333
arr_flat = np.ascontiguousarray(arr).reshape(-1)
34-
levels = (Level(LevelFormat.Dense),) * arr.ndim
35-
dense_format = get_storage_format(
36-
levels=levels,
37-
order="C",
38-
pos_width=64,
39-
crd_width=64,
40-
dtype=arr.dtype,
41-
)
34+
dense_format = Dense().with_ndim(arr.ndim).with_dtype(arr.dtype).build()
4235
return from_constituent_arrays(format=dense_format, arrays=(arr_flat,), shape=arr.shape)
4336

4437

4538
def to_numpy(arr: Array) -> np.ndarray:
46-
storage_format: StorageFormat = arr.format
47-
48-
if not all(LevelFormat.Dense == level.format for level in storage_format.levels):
49-
raise TypeError(f"Cannot convert a non-dense array to NumPy. `{storage_format=}`")
39+
if not Dense.is_this_format(arr.format):
40+
raise TypeError(f"Cannot convert a non-dense array to NumPy. `{arr.format=}`")
5041

5142
(data,) = arr.get_constituent_arrays()
52-
arg_order = [0] * storage_format.storage_rank
53-
for i, o in enumerate(storage_format.order):
43+
arg_order = [0] * arr.format.storage_rank
44+
for i, o in enumerate(arr.format.order):
5445
arg_order[o] = i
5546
arg_order = tuple(arg_order)
5647
storage_shape = tuple(int(arr.shape[o]) for o in arg_order)
@@ -63,22 +54,17 @@ def _from_scipy(arr: ScipySparseArray, copy: bool | None = None) -> Array:
6354
raise TypeError(f"`arr` is not a `scipy.sparse` array, `{type(arr)=}`.")
6455
match arr.format:
6556
case "csr" | "csc":
57+
order = (0, 1) if arr.format == "csr" else (1, 0)
6658
pos_width = arr.indptr.dtype.itemsize * 8
6759
crd_width = arr.indices.dtype.itemsize * 8
68-
csx_format = get_storage_format(
69-
levels=(
70-
Level(LevelFormat.Dense),
71-
Level(
72-
LevelFormat.Compressed,
73-
LevelProperties(0)
74-
if arr.has_canonical_format
75-
else LevelProperties.NonUnique | LevelProperties.NonOrdered,
76-
),
77-
),
78-
order=(0, 1) if arr.format == "csr" else (1, 0),
79-
pos_width=pos_width,
80-
crd_width=crd_width,
81-
dtype=arr.dtype,
60+
csx_format = (
61+
Csf()
62+
.with_ndim(2, canonical=arr.has_canonical_format)
63+
.with_dtype(arr.dtype)
64+
.with_crd_width(crd_width)
65+
.with_pos_width(pos_width)
66+
.with_order(order)
67+
.build()
8268
)
8369

8470
indptr = arr.indptr
@@ -108,19 +94,13 @@ def _from_scipy(arr: ScipySparseArray, copy: bool | None = None) -> Array:
10894
row = row.copy()
10995
col = col.copy()
11096

111-
level_props = LevelProperties(0)
112-
if not arr.has_canonical_format:
113-
level_props |= LevelProperties.NonOrdered
114-
115-
coo_format = get_storage_format(
116-
levels=(
117-
Level(LevelFormat.Compressed, level_props | LevelProperties.NonUnique),
118-
Level(LevelFormat.Singleton, level_props | LevelProperties.SOA),
119-
),
120-
order=(0, 1),
121-
pos_width=pos_width,
122-
crd_width=crd_width,
123-
dtype=arr.dtype,
97+
coo_format = (
98+
Coo()
99+
.with_ndim(2, canonical=arr.has_canonical_format)
100+
.with_dtype(arr.dtype)
101+
.with_pos_width(pos_width)
102+
.with_crd_width(crd_width)
103+
.build()
124104
)
125105

126106
return from_constituent_arrays(format=coo_format, arrays=(pos, row, col, data), shape=arr.shape)
@@ -162,6 +142,6 @@ def asarray(arr, copy: bool | None = None) -> Array:
162142
return _from_numpy(np.asarray(arr), copy=copy)
163143

164144

165-
def from_constituent_arrays(*, format: StorageFormat, arrays: tuple[np.ndarray, ...], shape: tuple[int, ...]) -> Array:
145+
def from_constituent_arrays(*, format: ConcreteFormat, arrays: tuple[np.ndarray, ...], shape: tuple[int, ...]) -> Array:
166146
storage = format._get_ctypes_type().from_constituent_arrays(arrays)
167147
return Array(storage=storage, shape=shape)

sparse/mlir_backend/_ops.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from ._common import as_shape, fn_cache
1313
from ._core import CWD, DEBUG, OPT_LEVEL, SHARED_LIBS, ctx, pm
1414
from ._dtypes import DType, IeeeComplexFloatingDType, IeeeRealFloatingDType, IntegerDType
15-
from .levels import StorageFormat, _determine_format
15+
from .formats import ConcreteFormat, _determine_format
1616

1717

1818
@fn_cache
@@ -181,7 +181,7 @@ def add(x1: Array, x2: Array, /) -> Array:
181181
return Array(storage=ret_storage, shape=tuple(out_tensor_type.shape))
182182

183183

184-
def asformat(x: Array, /, format: StorageFormat) -> Array:
184+
def asformat(x: Array, /, format: ConcreteFormat) -> Array:
185185
if format.rank != x.ndim:
186186
raise ValueError(f"`format.rank != `self.ndim`, {format.rank=}, {x.ndim=}")
187187

0 commit comments

Comments
 (0)