xobjects 0.5.15__tar.gz → 0.6.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xobjects-0.5.15/xobjects.egg-info → xobjects-0.6.1}/PKG-INFO +1 -1
- {xobjects-0.5.15 → xobjects-0.6.1}/pyproject.toml +1 -1
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_kernel.py +39 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_struct.py +32 -0
- xobjects-0.6.1/tests/test_to_dict.py +319 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/__init__.py +2 -2
- xobjects-0.6.1/xobjects/_version.py +1 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/array.py +18 -5
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/context_cpu.py +4 -2
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/context_cupy.py +2 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/context_pyopencl.py +2 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/hybrid_class.py +5 -13
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/ref.py +9 -2
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/struct.py +45 -2
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/test_helpers.py +2 -1
- {xobjects-0.5.15 → xobjects-0.6.1/xobjects.egg-info}/PKG-INFO +1 -1
- xobjects-0.5.15/tests/test_to_dict.py +0 -41
- xobjects-0.5.15/xobjects/_version.py +0 -1
- {xobjects-0.5.15 → xobjects-0.6.1}/Architecture.md +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/LICENSE +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/MANIFEST.in +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/README.md +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/setup.cfg +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/setup.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_align.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_array.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_buffer.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_capi.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_chunk.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_common.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_context_opencl.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_hybrid_class.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_linked_array.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_nplike_arrays.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_ref.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_scalars.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_shared_memory.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_strides.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_string.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_typeutils.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/tests/test_unionref.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/_patch_pyopencl_array.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/capi.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/context.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/general.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/headers/atomicadd.h +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/headers/common.h +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/linkedarray.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/scalar.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/specialize_source.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/string.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/typeutils.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects/union.py +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects.egg-info/SOURCES.txt +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects.egg-info/dependency_links.txt +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects.egg-info/entry_points.txt +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects.egg-info/requires.txt +0 -0
- {xobjects-0.5.15 → xobjects-0.6.1}/xobjects.egg-info/top_level.txt +0 -0
|
@@ -44,6 +44,45 @@ double my_mul(const int n, const double* x1,
|
|
|
44
44
|
assert y == 285.0
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
@for_all_test_contexts
|
|
48
|
+
def test_kernel_pointer_none_maps_to_null(test_context):
|
|
49
|
+
src_code = """
|
|
50
|
+
#include "xobjects/headers/common.h"
|
|
51
|
+
|
|
52
|
+
GPUKERN void ptr_is_null(
|
|
53
|
+
GPUGLMEM const double* x,
|
|
54
|
+
GPUGLMEM double* out
|
|
55
|
+
) {
|
|
56
|
+
VECTORIZE_OVER(tid, 1)
|
|
57
|
+
out[tid] = x == NULL ? 1.0 : 0.0;
|
|
58
|
+
END_VECTORIZE
|
|
59
|
+
}
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
kernel_descriptions = {
|
|
63
|
+
"ptr_is_null": xo.Kernel(
|
|
64
|
+
args=[
|
|
65
|
+
xo.Arg(xo.Float64, pointer=True, const=True, name="x"),
|
|
66
|
+
xo.Arg(xo.Float64, pointer=True, name="out"),
|
|
67
|
+
],
|
|
68
|
+
n_threads=1,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
test_context.add_kernels(
|
|
73
|
+
sources=[src_code],
|
|
74
|
+
kernels=kernel_descriptions,
|
|
75
|
+
save_source_as=None,
|
|
76
|
+
compile=True,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
out_dev = test_context.zeros(1, dtype=np.float64)
|
|
80
|
+
test_context.kernels.ptr_is_null(x=None, out=out_dev)
|
|
81
|
+
out_host = test_context.nparray_from_context_array(out_dev)
|
|
82
|
+
|
|
83
|
+
assert out_host[0] == 1.0
|
|
84
|
+
|
|
85
|
+
|
|
47
86
|
@for_all_test_contexts
|
|
48
87
|
def test_kernels(test_context):
|
|
49
88
|
src_code = """
|
|
@@ -333,6 +333,8 @@ def test_compile_kernels_only_if_needed(tmp_path, mocker):
|
|
|
333
333
|
def myfun(self):
|
|
334
334
|
return self._context.kernels.myfun(tc=self)
|
|
335
335
|
|
|
336
|
+
assert TestClass._kernels["myfun"].args[0].atype is TestClass._XoStruct
|
|
337
|
+
|
|
336
338
|
tc = TestClass(x=3, y=4, _context=test_context)
|
|
337
339
|
tc.compile_kernels(only_if_needed=True)
|
|
338
340
|
assert tc.myfun() == 12
|
|
@@ -343,3 +345,33 @@ def test_compile_kernels_only_if_needed(tmp_path, mocker):
|
|
|
343
345
|
tc.compile_kernels(only_if_needed=True)
|
|
344
346
|
assert tc.myfun() == 35
|
|
345
347
|
cffi_compile.assert_not_called()
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@requires_context("ContextCpu")
|
|
351
|
+
def test_thisclass_placeholder_on_struct():
|
|
352
|
+
test_context = xo.ContextCpu()
|
|
353
|
+
|
|
354
|
+
class TestStruct(xo.Struct):
|
|
355
|
+
x = xo.Float64
|
|
356
|
+
y = xo.Float64
|
|
357
|
+
|
|
358
|
+
_extra_c_sources = ["""
|
|
359
|
+
/*gpufun*/ double myfun(TestStruct tc){
|
|
360
|
+
double x = TestStruct_get_x(tc);
|
|
361
|
+
double y = TestStruct_get_y(tc);
|
|
362
|
+
return x * y;
|
|
363
|
+
}
|
|
364
|
+
"""]
|
|
365
|
+
_kernels = {
|
|
366
|
+
"myfun": xo.Kernel(
|
|
367
|
+
args=[xo.Arg(xo.ThisClass, name="tc")],
|
|
368
|
+
ret=xo.Arg(xo.Float64),
|
|
369
|
+
),
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
assert TestStruct._kernels["myfun"].args[0].atype is TestStruct
|
|
373
|
+
|
|
374
|
+
ts = TestStruct(x=3, y=4, _context=test_context)
|
|
375
|
+
ts.compile_kernels()
|
|
376
|
+
|
|
377
|
+
assert test_context.kernels.myfun(tc=ts) == 12
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import xobjects as xo
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_to_dict():
|
|
5
|
+
class A(xo.Struct):
|
|
6
|
+
a = xo.Float64[:]
|
|
7
|
+
b = xo.Int64
|
|
8
|
+
|
|
9
|
+
class Uref(xo.UnionRef):
|
|
10
|
+
_reftypes = (A,)
|
|
11
|
+
|
|
12
|
+
x = A(a=[2, 3], b=1)
|
|
13
|
+
u = Uref(x)
|
|
14
|
+
v = Uref(*u._to_dict())
|
|
15
|
+
|
|
16
|
+
assert v.get().a[0] == 2
|
|
17
|
+
assert v.get().a[1] == 3
|
|
18
|
+
assert v.get().b == 1
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_to_dict_array():
|
|
22
|
+
class A(xo.Struct):
|
|
23
|
+
a = xo.Float64[:]
|
|
24
|
+
|
|
25
|
+
class B(xo.Struct):
|
|
26
|
+
c = xo.Float64[:]
|
|
27
|
+
d = xo.Int64
|
|
28
|
+
|
|
29
|
+
class Uref(xo.UnionRef):
|
|
30
|
+
_reftypes = A, B
|
|
31
|
+
|
|
32
|
+
AUref = Uref[:]
|
|
33
|
+
|
|
34
|
+
a = AUref(10)
|
|
35
|
+
a[1] = A(a=[3])
|
|
36
|
+
a[5] = B(c=2, d=1)
|
|
37
|
+
|
|
38
|
+
b = AUref(a._to_dict())
|
|
39
|
+
|
|
40
|
+
assert b[1].a[0] == 3
|
|
41
|
+
assert b[5].d == 1
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_to_dict_unionref_none_roundtrip():
|
|
45
|
+
class A(xo.Struct):
|
|
46
|
+
x = xo.Int64
|
|
47
|
+
|
|
48
|
+
class B(xo.Struct):
|
|
49
|
+
y = xo.Int64
|
|
50
|
+
|
|
51
|
+
class Uref(xo.UnionRef):
|
|
52
|
+
_reftypes = (A, B)
|
|
53
|
+
|
|
54
|
+
uref = Uref(None)
|
|
55
|
+
|
|
56
|
+
assert uref._to_dict() is None
|
|
57
|
+
rebuilt = Uref(uref._to_dict())
|
|
58
|
+
assert rebuilt.get() is None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_to_dict_array_of_unionrefs_with_mixed_none_and_values():
|
|
62
|
+
class A(xo.Struct):
|
|
63
|
+
x = xo.Int64
|
|
64
|
+
|
|
65
|
+
class B(xo.Struct):
|
|
66
|
+
y = xo.Int64
|
|
67
|
+
|
|
68
|
+
class Uref(xo.UnionRef):
|
|
69
|
+
_reftypes = (A, B)
|
|
70
|
+
|
|
71
|
+
array_type = Uref[:]
|
|
72
|
+
items = array_type(4)
|
|
73
|
+
items[1] = A(x=5)
|
|
74
|
+
items[3] = B(y=9)
|
|
75
|
+
|
|
76
|
+
expected = [
|
|
77
|
+
None,
|
|
78
|
+
("A", {"x": 5}),
|
|
79
|
+
None,
|
|
80
|
+
("B", {"y": 9}),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
assert items._to_dict() == expected
|
|
84
|
+
rebuilt = array_type(items._to_dict())
|
|
85
|
+
assert rebuilt._to_dict() == expected
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_to_dict_array_multidimensional_static_shape():
|
|
89
|
+
array_type = xo.Float64[2, 3]
|
|
90
|
+
array = array_type([[1, 2, 3], [4, 5, 6]])
|
|
91
|
+
|
|
92
|
+
assert array._to_dict() == [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
|
|
93
|
+
rebuilt = array_type(array._to_dict())
|
|
94
|
+
assert rebuilt._to_dict() == array._to_dict()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_to_dict_array_multidimensional_dynamic_shape():
|
|
98
|
+
array_type = xo.Float64[:, :]
|
|
99
|
+
array = array_type(2, 3)
|
|
100
|
+
array[0, 0] = 1
|
|
101
|
+
array[0, 1] = 2
|
|
102
|
+
array[0, 2] = 3
|
|
103
|
+
array[1, 0] = 4
|
|
104
|
+
array[1, 1] = 5
|
|
105
|
+
array[1, 2] = 6
|
|
106
|
+
|
|
107
|
+
assert array._to_dict() == [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
|
|
108
|
+
rebuilt = array_type(array._to_dict())
|
|
109
|
+
assert rebuilt._to_dict() == array._to_dict()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_to_dict_array_of_structs():
|
|
113
|
+
class Item(xo.Struct):
|
|
114
|
+
value = xo.Int64
|
|
115
|
+
coords = xo.Float64[2]
|
|
116
|
+
|
|
117
|
+
array_type = Item[:]
|
|
118
|
+
items = array_type(
|
|
119
|
+
[
|
|
120
|
+
{"value": 3, "coords": [1, 2]},
|
|
121
|
+
{"value": 7, "coords": [4, 5]},
|
|
122
|
+
]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
assert items._to_dict() == [
|
|
126
|
+
{"value": 3, "coords": [1.0, 2.0]},
|
|
127
|
+
{"value": 7, "coords": [4.0, 5.0]},
|
|
128
|
+
]
|
|
129
|
+
rebuilt = array_type(items._to_dict())
|
|
130
|
+
assert rebuilt._to_dict() == items._to_dict()
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_to_dict_multidimensional_array_of_structs():
|
|
134
|
+
class Item(xo.Struct):
|
|
135
|
+
value = xo.Int64
|
|
136
|
+
coords = xo.Float64[2]
|
|
137
|
+
|
|
138
|
+
array_type = Item[:, :]
|
|
139
|
+
items = array_type(
|
|
140
|
+
[
|
|
141
|
+
[
|
|
142
|
+
{"value": 1, "coords": [1, 2]},
|
|
143
|
+
{"value": 2, "coords": [3, 4]},
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
{"value": 3, "coords": [5, 6]},
|
|
147
|
+
{"value": 4, "coords": [7, 8]},
|
|
148
|
+
],
|
|
149
|
+
]
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
expected = [
|
|
153
|
+
[
|
|
154
|
+
{"value": 1, "coords": [1.0, 2.0]},
|
|
155
|
+
{"value": 2, "coords": [3.0, 4.0]},
|
|
156
|
+
],
|
|
157
|
+
[
|
|
158
|
+
{"value": 3, "coords": [5.0, 6.0]},
|
|
159
|
+
{"value": 4, "coords": [7.0, 8.0]},
|
|
160
|
+
],
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
assert items._to_dict() == expected
|
|
164
|
+
rebuilt = array_type(items._to_dict())
|
|
165
|
+
assert rebuilt._to_dict() == expected
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def test_to_dict_multidimensional_array_of_structs_with_refs():
|
|
169
|
+
class Item(xo.Struct):
|
|
170
|
+
values = xo.Ref[xo.Float64[:]]
|
|
171
|
+
weight = xo.Int64
|
|
172
|
+
|
|
173
|
+
array_type = Item[:, :]
|
|
174
|
+
items = array_type(
|
|
175
|
+
[
|
|
176
|
+
[
|
|
177
|
+
{"values": [1, 2], "weight": 3},
|
|
178
|
+
{"values": [4, 5, 6], "weight": 7},
|
|
179
|
+
],
|
|
180
|
+
[
|
|
181
|
+
{"values": [8], "weight": 9},
|
|
182
|
+
{"values": [10, 11], "weight": 12},
|
|
183
|
+
],
|
|
184
|
+
]
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
expected = [
|
|
188
|
+
[
|
|
189
|
+
{"values": [1.0, 2.0], "weight": 3},
|
|
190
|
+
{"values": [4.0, 5.0, 6.0], "weight": 7},
|
|
191
|
+
],
|
|
192
|
+
[
|
|
193
|
+
{"values": [8.0], "weight": 9},
|
|
194
|
+
{"values": [10.0, 11.0], "weight": 12},
|
|
195
|
+
],
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
assert items._to_dict() == expected
|
|
199
|
+
rebuilt = array_type(items._to_dict())
|
|
200
|
+
assert rebuilt._to_dict() == expected
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def test_to_dict_struct_with_unionref_field():
|
|
204
|
+
class A(xo.Struct):
|
|
205
|
+
a = xo.Float64[:]
|
|
206
|
+
b = xo.Int64
|
|
207
|
+
|
|
208
|
+
class B(xo.Struct):
|
|
209
|
+
c = xo.Float64[:]
|
|
210
|
+
d = xo.Int64
|
|
211
|
+
|
|
212
|
+
class Uref(xo.UnionRef):
|
|
213
|
+
_reftypes = (A, B)
|
|
214
|
+
|
|
215
|
+
class Item(xo.Struct):
|
|
216
|
+
ref = Uref
|
|
217
|
+
weight = xo.Int64
|
|
218
|
+
|
|
219
|
+
item = Item(ref=("A", {"a": [1, 2], "b": 3}), weight=11)
|
|
220
|
+
|
|
221
|
+
expected = {
|
|
222
|
+
"ref": ("A", {"a": [1.0, 2.0], "b": 3}),
|
|
223
|
+
"weight": 11,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
assert item._to_dict() == expected
|
|
227
|
+
rebuilt = Item(item._to_dict())
|
|
228
|
+
assert rebuilt._to_dict() == expected
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_to_dict_struct_containing_array_of_structs_with_unionref_fields():
|
|
232
|
+
class A(xo.Struct):
|
|
233
|
+
a = xo.Float64[:]
|
|
234
|
+
b = xo.Int64
|
|
235
|
+
|
|
236
|
+
class B(xo.Struct):
|
|
237
|
+
c = xo.Float64[:]
|
|
238
|
+
d = xo.Int64
|
|
239
|
+
|
|
240
|
+
class Uref(xo.UnionRef):
|
|
241
|
+
_reftypes = (A, B)
|
|
242
|
+
|
|
243
|
+
class Item(xo.Struct):
|
|
244
|
+
ref = Uref
|
|
245
|
+
weight = xo.Int64
|
|
246
|
+
|
|
247
|
+
class Container(xo.Struct):
|
|
248
|
+
items = Item[:]
|
|
249
|
+
tag = xo.Int64
|
|
250
|
+
|
|
251
|
+
container = Container(
|
|
252
|
+
items=[
|
|
253
|
+
{"ref": ("A", {"a": [1, 2], "b": 3}), "weight": 11},
|
|
254
|
+
{"ref": ("B", {"c": [4, 5], "d": 6}), "weight": 12},
|
|
255
|
+
],
|
|
256
|
+
tag=99,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
expected = {
|
|
260
|
+
"items": [
|
|
261
|
+
{"ref": ("A", {"a": [1.0, 2.0], "b": 3}), "weight": 11},
|
|
262
|
+
{"ref": ("B", {"c": [4.0, 5.0], "d": 6}), "weight": 12},
|
|
263
|
+
],
|
|
264
|
+
"tag": 99,
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
assert container._to_dict() == expected
|
|
268
|
+
rebuilt = Container(container._to_dict())
|
|
269
|
+
assert rebuilt._to_dict() == expected
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_to_dict_struct_containing_multidimensional_array_of_structs_with_unionref_fields():
|
|
273
|
+
class A(xo.Struct):
|
|
274
|
+
a = xo.Float64[:]
|
|
275
|
+
b = xo.Int64
|
|
276
|
+
|
|
277
|
+
class B(xo.Struct):
|
|
278
|
+
c = xo.Float64[:]
|
|
279
|
+
d = xo.Int64
|
|
280
|
+
|
|
281
|
+
class Uref(xo.UnionRef):
|
|
282
|
+
_reftypes = (A, B)
|
|
283
|
+
|
|
284
|
+
class Item(xo.Struct):
|
|
285
|
+
ref = Uref
|
|
286
|
+
weight = xo.Int64
|
|
287
|
+
|
|
288
|
+
class Container(xo.Struct):
|
|
289
|
+
items = Item[:, :]
|
|
290
|
+
|
|
291
|
+
container = Container(
|
|
292
|
+
items=[
|
|
293
|
+
[
|
|
294
|
+
{"ref": ("A", {"a": [1, 2], "b": 3}), "weight": 11},
|
|
295
|
+
{"ref": ("B", {"c": [4, 5], "d": 6}), "weight": 12},
|
|
296
|
+
],
|
|
297
|
+
[
|
|
298
|
+
{"ref": ("B", {"c": [7], "d": 8}), "weight": 13},
|
|
299
|
+
{"ref": ("A", {"a": [9, 10], "b": 14}), "weight": 15},
|
|
300
|
+
],
|
|
301
|
+
]
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
expected = {
|
|
305
|
+
"items": [
|
|
306
|
+
[
|
|
307
|
+
{"ref": ("A", {"a": [1.0, 2.0], "b": 3}), "weight": 11},
|
|
308
|
+
{"ref": ("B", {"c": [4.0, 5.0], "d": 6}), "weight": 12},
|
|
309
|
+
],
|
|
310
|
+
[
|
|
311
|
+
{"ref": ("B", {"c": [7.0], "d": 8}), "weight": 13},
|
|
312
|
+
{"ref": ("A", {"a": [9.0, 10.0], "b": 14}), "weight": 15},
|
|
313
|
+
],
|
|
314
|
+
]
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
assert container._to_dict() == expected
|
|
318
|
+
rebuilt = Container(container._to_dict())
|
|
319
|
+
assert rebuilt._to_dict() == expected
|
|
@@ -17,7 +17,7 @@ from .scalar import (
|
|
|
17
17
|
)
|
|
18
18
|
from .array import Array
|
|
19
19
|
from .string import String
|
|
20
|
-
from .struct import Struct, Field
|
|
20
|
+
from .struct import Struct, Field, ThisClass
|
|
21
21
|
from .ref import Ref, UnionRef
|
|
22
22
|
|
|
23
23
|
from .context_cpu import ContextCpu
|
|
@@ -30,7 +30,7 @@ from .specialize_source import specialize_source
|
|
|
30
30
|
|
|
31
31
|
from .typeutils import context_default, get_a_buffer
|
|
32
32
|
|
|
33
|
-
from .hybrid_class import JEncoder, HybridClass, MetaHybridClass
|
|
33
|
+
from .hybrid_class import JEncoder, HybridClass, MetaHybridClass
|
|
34
34
|
|
|
35
35
|
from .linkedarray import BypassLinked
|
|
36
36
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.1"
|
|
@@ -15,6 +15,7 @@ from .typeutils import (
|
|
|
15
15
|
_to_slot_size,
|
|
16
16
|
default_conf,
|
|
17
17
|
)
|
|
18
|
+
from .ref import is_ref, is_unionref
|
|
18
19
|
from .scalar import Int64, is_scalar
|
|
19
20
|
|
|
20
21
|
log = logging.getLogger(__name__)
|
|
@@ -693,16 +694,28 @@ class Array(metaclass=MetaArray):
|
|
|
693
694
|
raise NameError("`_to_json` has been removed. Use `_to_dict` instead.")
|
|
694
695
|
|
|
695
696
|
def _to_dict(self):
|
|
696
|
-
|
|
697
|
-
|
|
697
|
+
if hasattr(self._itemtype, "_dtype"):
|
|
698
|
+
return self.to_nparray().tolist()
|
|
699
|
+
|
|
700
|
+
out = np.empty(dtype=object, shape=self._shape)
|
|
701
|
+
|
|
702
|
+
for idx in self._iter_index():
|
|
703
|
+
idx = idx if isinstance(idx, tuple) else (idx,)
|
|
704
|
+
v = self[idx]
|
|
705
|
+
|
|
698
706
|
if hasattr(v, "_to_dict"):
|
|
699
707
|
vdata = v._to_dict()
|
|
700
708
|
else:
|
|
701
709
|
vdata = v
|
|
702
|
-
|
|
710
|
+
|
|
711
|
+
if v is not None and (
|
|
712
|
+
is_ref(self._itemtype) or is_unionref(self._itemtype)
|
|
713
|
+
):
|
|
703
714
|
vdata = (v.__class__.__name__, vdata)
|
|
704
|
-
|
|
705
|
-
|
|
715
|
+
|
|
716
|
+
out[idx] = vdata
|
|
717
|
+
|
|
718
|
+
return out.tolist()
|
|
706
719
|
|
|
707
720
|
|
|
708
721
|
def is_index(atype):
|
|
@@ -316,7 +316,7 @@ class ContextCpu(XContext):
|
|
|
316
316
|
if _forbid_compile:
|
|
317
317
|
raise RuntimeError("Compilation is forbidden")
|
|
318
318
|
|
|
319
|
-
if os.environ.get(
|
|
319
|
+
if os.environ.get("XOBJECTS_FORBID_COMPILE"):
|
|
320
320
|
raise RuntimeError(
|
|
321
321
|
"Compilation is forbidden by the environment variable "
|
|
322
322
|
"XOBJECTS_FORBID_COMPILE"
|
|
@@ -466,7 +466,7 @@ class ContextCpu(XContext):
|
|
|
466
466
|
return Path(output_file)
|
|
467
467
|
finally:
|
|
468
468
|
# Clean temp files
|
|
469
|
-
if
|
|
469
|
+
if "XOBJECTS_KEEP_BUILD_FILES" not in os.environ:
|
|
470
470
|
files_to_remove = [
|
|
471
471
|
module_name + ".c",
|
|
472
472
|
module_name + ".o",
|
|
@@ -799,6 +799,8 @@ class KernelCpu:
|
|
|
799
799
|
|
|
800
800
|
def to_function_arg(self, arg, value):
|
|
801
801
|
if arg.pointer:
|
|
802
|
+
if value is None:
|
|
803
|
+
return self.ffi_interface.NULL
|
|
802
804
|
if hasattr(arg.atype, "_dtype"): # it is numerical scalar
|
|
803
805
|
if hasattr(value, "dtype"): # nparray
|
|
804
806
|
slice_first_elem = value[tuple(value.ndim * [slice(0, 1)])]
|
|
@@ -661,6 +661,8 @@ class KernelCupy(object):
|
|
|
661
661
|
|
|
662
662
|
def to_function_arg(self, arg, value):
|
|
663
663
|
if arg.pointer:
|
|
664
|
+
if value is None:
|
|
665
|
+
return 0
|
|
664
666
|
if hasattr(arg.atype, "_dtype"): # it is numerical scalar
|
|
665
667
|
if hasattr(value, "dtype"): # nparray
|
|
666
668
|
assert isinstance(value, cupy.ndarray)
|
|
@@ -127,8 +127,11 @@ class MetaHybridClass(type):
|
|
|
127
127
|
|
|
128
128
|
# Take xofields from data['_xofields'] or from bases
|
|
129
129
|
xofields = _build_xofields_dict(bases, data)
|
|
130
|
+
xostruct_data = xofields.copy()
|
|
131
|
+
if "_kernels" in data.keys():
|
|
132
|
+
xostruct_data["_kernels"] = data["_kernels"]
|
|
130
133
|
|
|
131
|
-
_XoStruct = type(_XoStruct_name, (Struct,),
|
|
134
|
+
_XoStruct = type(_XoStruct_name, (Struct,), xostruct_data)
|
|
132
135
|
|
|
133
136
|
if "_rename" in data.keys():
|
|
134
137
|
rename = data["_rename"]
|
|
@@ -184,14 +187,7 @@ class MetaHybridClass(type):
|
|
|
184
187
|
new_class._XoStruct._depends_on.extend(data["_depends_on"])
|
|
185
188
|
|
|
186
189
|
if "_kernels" in data.keys():
|
|
187
|
-
|
|
188
|
-
for nn, kk in kernels.items():
|
|
189
|
-
for aa in kk.args:
|
|
190
|
-
if aa.atype is ThisClass:
|
|
191
|
-
aa.atype = new_class._XoStruct
|
|
192
|
-
if isclass(aa.atype) and issubclass(aa.atype, HybridClass):
|
|
193
|
-
aa.atype = aa.atype._XoStruct
|
|
194
|
-
new_class._XoStruct._kernels.update(kernels)
|
|
190
|
+
new_class._kernels = new_class._XoStruct._kernels
|
|
195
191
|
|
|
196
192
|
for ii, tt in enumerate(new_class._XoStruct._depends_on):
|
|
197
193
|
if isclass(tt) and issubclass(tt, HybridClass):
|
|
@@ -422,7 +418,3 @@ class HybridClass(metaclass=MetaHybridClass):
|
|
|
422
418
|
vvrepr = repr(vv)
|
|
423
419
|
args.append(f"{fname}={vvrepr}")
|
|
424
420
|
return f'{type(self).__name__}({", ".join(args)})'
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
class ThisClass: # Place holder
|
|
428
|
-
pass
|
|
@@ -9,7 +9,6 @@ import numpy as np
|
|
|
9
9
|
|
|
10
10
|
from .typeutils import Info, dispatch_arg, allocate_on_buffer, default_conf
|
|
11
11
|
from .scalar import Int64
|
|
12
|
-
from .array import Array
|
|
13
12
|
|
|
14
13
|
log = logging.getLogger(__name__)
|
|
15
14
|
|
|
@@ -72,6 +71,8 @@ class Ref(metaclass=MetaRef):
|
|
|
72
71
|
return Info(size=self._size)
|
|
73
72
|
|
|
74
73
|
def __getitem__(self, shape):
|
|
74
|
+
from .array import Array
|
|
75
|
+
|
|
75
76
|
return Array.mk_arrayclass(self, shape)
|
|
76
77
|
|
|
77
78
|
def _gen_data_paths(self, base=None):
|
|
@@ -182,7 +183,9 @@ class MetaUnionRef(type):
|
|
|
182
183
|
else:
|
|
183
184
|
if value is None:
|
|
184
185
|
xobj = None
|
|
185
|
-
elif isinstance(
|
|
186
|
+
elif isinstance(
|
|
187
|
+
value, (tuple, list)
|
|
188
|
+
): # accept list as it might be coming from JSON
|
|
186
189
|
if len(value) == 0:
|
|
187
190
|
xobj = None
|
|
188
191
|
typeid = None
|
|
@@ -213,6 +216,8 @@ class MetaUnionRef(type):
|
|
|
213
216
|
Int64._array_to_buffer(buffer, offset, ref)
|
|
214
217
|
|
|
215
218
|
def __getitem__(cls, shape):
|
|
219
|
+
from .array import Array
|
|
220
|
+
|
|
216
221
|
return Array.mk_arrayclass(cls, shape)
|
|
217
222
|
|
|
218
223
|
def _pre_init(cls, *arg, **kwargs):
|
|
@@ -298,6 +303,8 @@ class UnionRef(metaclass=MetaUnionRef):
|
|
|
298
303
|
|
|
299
304
|
def _to_dict(self):
|
|
300
305
|
v = self.get()
|
|
306
|
+
if v is None:
|
|
307
|
+
return None
|
|
301
308
|
classname = v.__class__.__name__
|
|
302
309
|
if hasattr(v, "_to_dict"):
|
|
303
310
|
v = v._to_dict()
|
|
@@ -46,6 +46,7 @@ Field instance:
|
|
|
46
46
|
|
|
47
47
|
"""
|
|
48
48
|
|
|
49
|
+
import copy
|
|
49
50
|
import logging
|
|
50
51
|
from typing import Callable, Optional
|
|
51
52
|
|
|
@@ -63,10 +64,23 @@ from .scalar import Int64
|
|
|
63
64
|
from .array import Array
|
|
64
65
|
from .context import Source, Arg, Kernel
|
|
65
66
|
from .context_cpu import ContextCpu
|
|
67
|
+
from .ref import is_unionref
|
|
66
68
|
|
|
67
69
|
log = logging.getLogger(__name__)
|
|
68
70
|
|
|
69
71
|
|
|
72
|
+
class ThisClass: # Place holder
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _resolve_kernel_arg_type(owner, atype):
|
|
77
|
+
if atype is ThisClass:
|
|
78
|
+
return owner
|
|
79
|
+
if hasattr(atype, "_XoStruct"):
|
|
80
|
+
return atype._XoStruct
|
|
81
|
+
return atype
|
|
82
|
+
|
|
83
|
+
|
|
70
84
|
class Field:
|
|
71
85
|
def __init__(
|
|
72
86
|
self, ftype, default=None, readonly=False, default_factory=None
|
|
@@ -265,7 +279,26 @@ class MetaStruct(type):
|
|
|
265
279
|
if "_kernels" not in data.keys():
|
|
266
280
|
data["_kernels"] = {}
|
|
267
281
|
|
|
268
|
-
|
|
282
|
+
new_class = type.__new__(cls, name, bases, data)
|
|
283
|
+
resolved_kernels = {}
|
|
284
|
+
for kernel_name, kernel in (new_class._kernels or {}).items():
|
|
285
|
+
resolved_kernel = copy.copy(kernel)
|
|
286
|
+
resolved_kernel.args = []
|
|
287
|
+
for arg in kernel.args:
|
|
288
|
+
resolved_arg = copy.copy(arg)
|
|
289
|
+
resolved_arg.atype = _resolve_kernel_arg_type(
|
|
290
|
+
new_class, resolved_arg.atype
|
|
291
|
+
)
|
|
292
|
+
resolved_kernel.args.append(resolved_arg)
|
|
293
|
+
if isinstance(kernel.ret, Arg):
|
|
294
|
+
resolved_ret = copy.copy(kernel.ret)
|
|
295
|
+
resolved_ret.atype = _resolve_kernel_arg_type(
|
|
296
|
+
new_class, resolved_ret.atype
|
|
297
|
+
)
|
|
298
|
+
resolved_kernel.ret = resolved_ret
|
|
299
|
+
resolved_kernels[kernel_name] = resolved_kernel
|
|
300
|
+
new_class._kernels = resolved_kernels
|
|
301
|
+
return new_class
|
|
269
302
|
|
|
270
303
|
def __getitem__(cls, shape):
|
|
271
304
|
return Array.mk_arrayclass(cls, shape)
|
|
@@ -374,6 +407,15 @@ class Struct(metaclass=MetaStruct):
|
|
|
374
407
|
out = {}
|
|
375
408
|
for field in self._fields:
|
|
376
409
|
v = field.__get__(self)
|
|
410
|
+
if is_unionref(field.ftype):
|
|
411
|
+
if v is None:
|
|
412
|
+
out[field.name] = None
|
|
413
|
+
else:
|
|
414
|
+
classname = v.__class__.__name__
|
|
415
|
+
if hasattr(v, "_to_dict"):
|
|
416
|
+
v = v._to_dict()
|
|
417
|
+
out[field.name] = (classname, v)
|
|
418
|
+
continue
|
|
377
419
|
if hasattr(v, "_to_dict"):
|
|
378
420
|
v = v._to_dict()
|
|
379
421
|
out[field.name] = v
|
|
@@ -485,6 +527,7 @@ class Struct(metaclass=MetaStruct):
|
|
|
485
527
|
get_suitable_kernel,
|
|
486
528
|
XSK_PREBUILT_KERNELS_LOCATION,
|
|
487
529
|
)
|
|
530
|
+
|
|
488
531
|
kernel_info = get_suitable_kernel(
|
|
489
532
|
config={},
|
|
490
533
|
tracker_element_classes=[],
|
|
@@ -496,7 +539,7 @@ class Struct(metaclass=MetaStruct):
|
|
|
496
539
|
Print.suppress = _print_state
|
|
497
540
|
if kernel_info:
|
|
498
541
|
kernels = context.kernels_from_file(
|
|
499
|
-
module_name=kernel_info[
|
|
542
|
+
module_name=kernel_info["module_name"],
|
|
500
543
|
containing_dir=XSK_PREBUILT_KERNELS_LOCATION,
|
|
501
544
|
kernel_descriptions=cls._kernels,
|
|
502
545
|
)
|
|
@@ -107,8 +107,9 @@ def fix_random_seed(seed: int):
|
|
|
107
107
|
|
|
108
108
|
return decorator
|
|
109
109
|
|
|
110
|
+
|
|
110
111
|
def skip_if_forbid_compile():
|
|
111
|
-
if os.environ.get(
|
|
112
|
+
if os.environ.get("XOBJECTS_FORBID_COMPILE"):
|
|
112
113
|
pytest.skip(
|
|
113
114
|
"Compilation is forbidden by the environment variable "
|
|
114
115
|
"XOBJECTS_FORBID_COMPILE"
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import xobjects as xo
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def test_to_dict():
|
|
5
|
-
class A(xo.Struct):
|
|
6
|
-
a = xo.Float64[:]
|
|
7
|
-
b = xo.Int64
|
|
8
|
-
|
|
9
|
-
class Uref(xo.UnionRef):
|
|
10
|
-
_reftypes = (A,)
|
|
11
|
-
|
|
12
|
-
x = A(a=[2, 3], b=1)
|
|
13
|
-
u = Uref(x)
|
|
14
|
-
v = Uref(*u._to_dict())
|
|
15
|
-
|
|
16
|
-
assert v.get().a[0] == 2
|
|
17
|
-
assert v.get().a[1] == 3
|
|
18
|
-
assert v.get().b == 1
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def test_to_dict_array():
|
|
22
|
-
class A(xo.Struct):
|
|
23
|
-
a = xo.Float64[:]
|
|
24
|
-
|
|
25
|
-
class B(xo.Struct):
|
|
26
|
-
c = xo.Float64[:]
|
|
27
|
-
d = xo.Int64
|
|
28
|
-
|
|
29
|
-
class Uref(xo.UnionRef):
|
|
30
|
-
_reftypes = A, B
|
|
31
|
-
|
|
32
|
-
AUref = Uref[:]
|
|
33
|
-
|
|
34
|
-
a = AUref(10)
|
|
35
|
-
a[1] = A(a=[3])
|
|
36
|
-
a[5] = B(c=2, d=1)
|
|
37
|
-
|
|
38
|
-
b = AUref(a._to_dict())
|
|
39
|
-
|
|
40
|
-
assert b[1].a[0] == 3
|
|
41
|
-
assert b[5].d == 1
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.5.15"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|