xnd 0.2.0dev6 → 0.2.0dev7
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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/Rakefile +1 -1
- data/ext/ruby_xnd/GPATH +0 -0
- data/ext/ruby_xnd/GRTAGS +0 -0
- data/ext/ruby_xnd/GTAGS +0 -0
- data/ext/ruby_xnd/extconf.rb +8 -5
- data/ext/ruby_xnd/gc_guard.c +53 -2
- data/ext/ruby_xnd/gc_guard.h +8 -2
- data/ext/ruby_xnd/include/overflow.h +147 -0
- data/ext/ruby_xnd/include/ruby_xnd.h +62 -0
- data/ext/ruby_xnd/include/xnd.h +590 -0
- data/ext/ruby_xnd/lib/libxnd.a +0 -0
- data/ext/ruby_xnd/lib/libxnd.so +1 -0
- data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
- data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
- data/ext/ruby_xnd/ruby_xnd.c +556 -47
- data/ext/ruby_xnd/ruby_xnd.h +2 -1
- data/ext/ruby_xnd/xnd/Makefile +80 -0
- data/ext/ruby_xnd/xnd/config.h +26 -0
- data/ext/ruby_xnd/xnd/config.h.in +3 -0
- data/ext/ruby_xnd/xnd/config.log +421 -0
- data/ext/ruby_xnd/xnd/config.status +1023 -0
- data/ext/ruby_xnd/xnd/configure +376 -8
- data/ext/ruby_xnd/xnd/configure.ac +48 -7
- data/ext/ruby_xnd/xnd/doc/xnd/index.rst +3 -1
- data/ext/ruby_xnd/xnd/doc/xnd/{types.rst → xnd.rst} +3 -18
- data/ext/ruby_xnd/xnd/libxnd/Makefile +142 -0
- data/ext/ruby_xnd/xnd/libxnd/Makefile.in +43 -3
- data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +19 -3
- data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +42 -3
- data/ext/ruby_xnd/xnd/libxnd/bitmaps.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/bounds.c +366 -0
- data/ext/ruby_xnd/xnd/libxnd/bounds.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/contrib.h +98 -0
- data/ext/ruby_xnd/xnd/libxnd/contrib/bfloat16.h +213 -0
- data/ext/ruby_xnd/xnd/libxnd/copy.c +155 -4
- data/ext/ruby_xnd/xnd/libxnd/copy.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.cu +121 -0
- data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.h +58 -0
- data/ext/ruby_xnd/xnd/libxnd/equal.c +195 -7
- data/ext/ruby_xnd/xnd/libxnd/equal.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/inline.h +32 -0
- data/ext/ruby_xnd/xnd/libxnd/libxnd.a +0 -0
- data/ext/ruby_xnd/xnd/libxnd/libxnd.so +1 -0
- data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0 +1 -0
- data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0.2.0dev3 +0 -0
- data/ext/ruby_xnd/xnd/libxnd/shape.c +207 -0
- data/ext/ruby_xnd/xnd/libxnd/shape.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/split.c +2 -2
- data/ext/ruby_xnd/xnd/libxnd/split.o +0 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/Makefile +39 -0
- data/ext/ruby_xnd/xnd/libxnd/xnd.c +613 -91
- data/ext/ruby_xnd/xnd/libxnd/xnd.h +145 -4
- data/ext/ruby_xnd/xnd/libxnd/xnd.o +0 -0
- data/ext/ruby_xnd/xnd/python/test_xnd.py +1125 -50
- data/ext/ruby_xnd/xnd/python/xnd/__init__.py +609 -124
- data/ext/ruby_xnd/xnd/python/xnd/_version.py +1 -0
- data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +1652 -101
- data/ext/ruby_xnd/xnd/python/xnd/libxnd.a +0 -0
- data/ext/ruby_xnd/xnd/python/xnd/libxnd.so +1 -0
- data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0 +1 -0
- data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0.2.0dev3 +0 -0
- data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +1 -1
- data/ext/ruby_xnd/xnd/python/xnd/util.h +25 -0
- data/ext/ruby_xnd/xnd/python/xnd/xnd.h +590 -0
- data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +106 -6
- data/ext/ruby_xnd/xnd/python/xnd_support.py +4 -0
- data/ext/ruby_xnd/xnd/setup.py +46 -4
- data/lib/ruby_xnd.so +0 -0
- data/lib/xnd.rb +39 -3
- data/lib/xnd/version.rb +2 -2
- data/xnd.gemspec +2 -1
- metadata +58 -5
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = '0.2.0dev3'
|
@@ -41,6 +41,7 @@
|
|
41
41
|
#include "pyndtypes.h"
|
42
42
|
#include "xnd.h"
|
43
43
|
#include "util.h"
|
44
|
+
#include "overflow.h"
|
44
45
|
#include "docstrings.h"
|
45
46
|
|
46
47
|
#define XND_MODULE
|
@@ -77,6 +78,13 @@ seterr_int(ndt_context_t *ctx)
|
|
77
78
|
return -1;
|
78
79
|
}
|
79
80
|
|
81
|
+
static const ndt_t *
|
82
|
+
seterr_ndt(ndt_context_t *ctx)
|
83
|
+
{
|
84
|
+
(void)Ndt_SetError(ctx);
|
85
|
+
return NULL;
|
86
|
+
}
|
87
|
+
|
80
88
|
|
81
89
|
/****************************************************************************/
|
82
90
|
/* Singletons */
|
@@ -162,7 +170,7 @@ mblock_dealloc(MemoryBlockObject *self)
|
|
162
170
|
}
|
163
171
|
|
164
172
|
static MemoryBlockObject *
|
165
|
-
mblock_empty(PyObject *type)
|
173
|
+
mblock_empty(PyObject *type, uint32_t flags)
|
166
174
|
{
|
167
175
|
NDT_STATIC_CONTEXT(ctx);
|
168
176
|
MemoryBlockObject *self;
|
@@ -177,7 +185,7 @@ mblock_empty(PyObject *type)
|
|
177
185
|
return NULL;
|
178
186
|
}
|
179
187
|
|
180
|
-
self->xnd = xnd_empty_from_type(
|
188
|
+
self->xnd = xnd_empty_from_type(NDT(type), XND_OWN_EMBEDDED|flags, &ctx);
|
181
189
|
if (self->xnd == NULL) {
|
182
190
|
Py_DECREF(self);
|
183
191
|
return (MemoryBlockObject *)seterr(&ctx);
|
@@ -189,11 +197,11 @@ mblock_empty(PyObject *type)
|
|
189
197
|
}
|
190
198
|
|
191
199
|
static MemoryBlockObject *
|
192
|
-
mblock_from_typed_value(PyObject *type, PyObject *value)
|
200
|
+
mblock_from_typed_value(PyObject *type, PyObject *value, uint32_t flags)
|
193
201
|
{
|
194
202
|
MemoryBlockObject *self;
|
195
203
|
|
196
|
-
self = mblock_empty(type);
|
204
|
+
self = mblock_empty(type, flags);
|
197
205
|
if (self == NULL) {
|
198
206
|
return NULL;
|
199
207
|
}
|
@@ -219,7 +227,8 @@ mblock_from_xnd(xnd_t *src)
|
|
219
227
|
return (MemoryBlockObject *)seterr(&ctx);
|
220
228
|
}
|
221
229
|
|
222
|
-
type = Ndt_FromType(
|
230
|
+
type = Ndt_FromType(x->master.type);
|
231
|
+
ndt_decref(x->master.type);
|
223
232
|
if (type == NULL) {
|
224
233
|
xnd_del(x);
|
225
234
|
return NULL;
|
@@ -242,7 +251,8 @@ static PyObject *
|
|
242
251
|
type_from_buffer(const Py_buffer *view)
|
243
252
|
{
|
244
253
|
NDT_STATIC_CONTEXT(ctx);
|
245
|
-
|
254
|
+
PyObject *ret;
|
255
|
+
const ndt_t *t, *type;
|
246
256
|
int64_t shape, step;
|
247
257
|
int64_t i;
|
248
258
|
|
@@ -269,20 +279,31 @@ type_from_buffer(const Py_buffer *view)
|
|
269
279
|
if (ndt_itemsize(type) != view->itemsize) {
|
270
280
|
PyErr_SetString(PyExc_RuntimeError,
|
271
281
|
"mismatch between computed itemsize and buffer itemsize");
|
272
|
-
|
282
|
+
ndt_decref(type);
|
273
283
|
return NULL;
|
274
284
|
}
|
275
285
|
|
276
286
|
for (i=view->ndim-1, t=type; i>=0; i--, type=t) {
|
277
287
|
shape = view->shape[i];
|
288
|
+
|
278
289
|
step = view->strides[i] / view->itemsize;
|
290
|
+
if (step * view->itemsize != view->strides[i]) {
|
291
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
292
|
+
"strides supplied by exporter are not a multiple of itemsize");
|
293
|
+
ndt_decref(type);
|
294
|
+
return NULL;
|
295
|
+
}
|
296
|
+
|
279
297
|
t = ndt_fixed_dim(type, shape, step, &ctx);
|
298
|
+
ndt_decref(type);
|
280
299
|
if (t == NULL) {
|
281
300
|
return seterr(&ctx);
|
282
301
|
}
|
283
302
|
}
|
284
303
|
|
285
|
-
|
304
|
+
ret = Ndt_FromType(t);
|
305
|
+
ndt_decref(t);
|
306
|
+
return ret;
|
286
307
|
}
|
287
308
|
|
288
309
|
static MemoryBlockObject *
|
@@ -306,15 +327,6 @@ mblock_from_buffer(PyObject *obj)
|
|
306
327
|
return NULL;
|
307
328
|
}
|
308
329
|
|
309
|
-
if (!PyBuffer_IsContiguous(self->view, 'A')) {
|
310
|
-
/* Conversion from buf+strides to steps+linear_index is not possible
|
311
|
-
if the start of the original data is missing. */
|
312
|
-
PyErr_SetString(PyExc_NotImplementedError,
|
313
|
-
"conversion from non-contiguous buffers is not implemented");
|
314
|
-
Py_DECREF(self);
|
315
|
-
return NULL;
|
316
|
-
}
|
317
|
-
|
318
330
|
self->type = type_from_buffer(self->view);
|
319
331
|
if (self->type == NULL) {
|
320
332
|
Py_DECREF(self);
|
@@ -332,16 +344,19 @@ mblock_from_buffer(PyObject *obj)
|
|
332
344
|
self->xnd->master.bitmap.size = 0;
|
333
345
|
self->xnd->master.bitmap.next = NULL;
|
334
346
|
self->xnd->master.index = 0;
|
335
|
-
self->xnd->master.type =
|
347
|
+
self->xnd->master.type = NDT(self->type);
|
336
348
|
self->xnd->master.ptr = self->view->buf;
|
337
349
|
|
338
350
|
return self;
|
339
351
|
}
|
340
352
|
|
341
353
|
static MemoryBlockObject *
|
342
|
-
mblock_from_buffer_and_type(PyObject *obj, PyObject *type
|
354
|
+
mblock_from_buffer_and_type(PyObject *obj, PyObject *type, int64_t linear_index,
|
355
|
+
int64_t bufsize)
|
343
356
|
{
|
357
|
+
NDT_STATIC_CONTEXT(ctx);
|
344
358
|
MemoryBlockObject *self;
|
359
|
+
const ndt_t *t;
|
345
360
|
|
346
361
|
if (!Ndt_Check(type)) {
|
347
362
|
PyErr_SetString(PyExc_TypeError, "expected ndt object");
|
@@ -359,20 +374,27 @@ mblock_from_buffer_and_type(PyObject *obj, PyObject *type)
|
|
359
374
|
return NULL;
|
360
375
|
}
|
361
376
|
|
362
|
-
if (PyObject_GetBuffer(obj, self->view,
|
377
|
+
if (PyObject_GetBuffer(obj, self->view, PyBUF_SIMPLE) < 0) {
|
363
378
|
Py_DECREF(self);
|
364
379
|
return NULL;
|
365
380
|
}
|
366
381
|
|
367
|
-
if (
|
368
|
-
|
369
|
-
if the start of the original data is missing. */
|
370
|
-
PyErr_SetString(PyExc_NotImplementedError,
|
371
|
-
"conversion from non-contiguous buffers is not implemented");
|
382
|
+
if (self->view->readonly) {
|
383
|
+
PyErr_SetString(PyExc_ValueError, "buffer is readonly");
|
372
384
|
Py_DECREF(self);
|
373
385
|
return NULL;
|
374
386
|
}
|
375
387
|
|
388
|
+
if (bufsize < 0) {
|
389
|
+
bufsize = self->view->len;
|
390
|
+
}
|
391
|
+
|
392
|
+
t = NDT(type);
|
393
|
+
if (xnd_bounds_check(t, linear_index, bufsize, &ctx) < 0) {
|
394
|
+
Py_DECREF(self);
|
395
|
+
return (MemoryBlockObject *)seterr(&ctx);
|
396
|
+
}
|
397
|
+
|
376
398
|
Py_INCREF(type);
|
377
399
|
self->type = type;
|
378
400
|
|
@@ -386,8 +408,8 @@ mblock_from_buffer_and_type(PyObject *obj, PyObject *type)
|
|
386
408
|
self->xnd->master.bitmap.data = NULL;
|
387
409
|
self->xnd->master.bitmap.size = 0;
|
388
410
|
self->xnd->master.bitmap.next = NULL;
|
389
|
-
self->xnd->master.index =
|
390
|
-
self->xnd->master.type =
|
411
|
+
self->xnd->master.index = linear_index;
|
412
|
+
self->xnd->master.type = t;
|
391
413
|
self->xnd->master.ptr = self->view->buf;
|
392
414
|
|
393
415
|
return self;
|
@@ -508,6 +530,47 @@ get_uint(PyObject *v, uint64_t max)
|
|
508
530
|
return x;
|
509
531
|
}
|
510
532
|
|
533
|
+
static int
|
534
|
+
union_tag_and_value_from_tuple(uint8_t *tag, PyObject **value, const ndt_t *t, PyObject *tuple)
|
535
|
+
{
|
536
|
+
PyObject *name;
|
537
|
+
int64_t i;
|
538
|
+
|
539
|
+
assert(t->tag == Union);
|
540
|
+
assert(PyTuple_Check(tuple));
|
541
|
+
|
542
|
+
if (PyTuple_GET_SIZE(tuple) != 2) {
|
543
|
+
PyErr_SetString(PyExc_ValueError,
|
544
|
+
"unions are represented by a tuple (tag, value), "
|
545
|
+
"where 'tag' is a string");
|
546
|
+
return -1;
|
547
|
+
}
|
548
|
+
|
549
|
+
name = PyTuple_GET_ITEM(tuple, 0);
|
550
|
+
if (!PyUnicode_Check(name)) {
|
551
|
+
PyErr_SetString(PyExc_TypeError,
|
552
|
+
"unions are represented by a tuple (tag, value), "
|
553
|
+
"where 'tag' is a string");
|
554
|
+
return -1;
|
555
|
+
}
|
556
|
+
|
557
|
+
for (i = 0; i < t->Union.ntags; i++) {
|
558
|
+
if (PyUnicode_CompareWithASCIIString(name, t->Union.tags[i]) == 0) {
|
559
|
+
break;
|
560
|
+
}
|
561
|
+
}
|
562
|
+
|
563
|
+
if (i == t->Union.ntags) {
|
564
|
+
PyErr_Format(PyExc_ValueError, "'%s' s not a valid tag", name);
|
565
|
+
return -1;
|
566
|
+
}
|
567
|
+
|
568
|
+
*tag = (uint8_t)i;
|
569
|
+
*value = PyTuple_GET_ITEM(tuple, 1);
|
570
|
+
|
571
|
+
return 0;
|
572
|
+
}
|
573
|
+
|
511
574
|
static int
|
512
575
|
mblock_init(xnd_t * const x, PyObject *v)
|
513
576
|
{
|
@@ -597,6 +660,27 @@ mblock_init(xnd_t * const x, PyObject *v)
|
|
597
660
|
return 0;
|
598
661
|
}
|
599
662
|
|
663
|
+
case VarDimElem: {
|
664
|
+
int64_t start, step, shape;
|
665
|
+
|
666
|
+
shape = ndt_var_indices(&start, &step, t, x->index, &ctx);
|
667
|
+
if (shape < 0) {
|
668
|
+
return seterr_int(&ctx);
|
669
|
+
}
|
670
|
+
|
671
|
+
const int64_t i = adjust_index(t->VarDimElem.index, shape, &ctx);
|
672
|
+
if (i < 0) {
|
673
|
+
return seterr_int(&ctx);
|
674
|
+
}
|
675
|
+
|
676
|
+
xnd_t next = xnd_var_dim_next(x, start, step, i);
|
677
|
+
if (mblock_init(&next, v) < 0) {
|
678
|
+
return -1;
|
679
|
+
}
|
680
|
+
|
681
|
+
return 0;
|
682
|
+
}
|
683
|
+
|
600
684
|
case Tuple: {
|
601
685
|
const int64_t shape = t->Tuple.shape;
|
602
686
|
int64_t i;
|
@@ -670,6 +754,32 @@ mblock_init(xnd_t * const x, PyObject *v)
|
|
670
754
|
return 0;
|
671
755
|
}
|
672
756
|
|
757
|
+
case Union: {
|
758
|
+
PyObject *tmp;
|
759
|
+
uint8_t tag;
|
760
|
+
|
761
|
+
if (!PyTuple_Check(v)) {
|
762
|
+
PyErr_Format(PyExc_TypeError,
|
763
|
+
"xnd: expected tuple, not '%.200s'", Py_TYPE(v)->tp_name);
|
764
|
+
return -1;
|
765
|
+
}
|
766
|
+
|
767
|
+
if (union_tag_and_value_from_tuple(&tag, &tmp, t, v) < 0) {
|
768
|
+
return -1;
|
769
|
+
}
|
770
|
+
|
771
|
+
xnd_clear(x, XND_OWN_EMBEDDED);
|
772
|
+
XND_UNION_TAG(x->ptr) = tag;
|
773
|
+
|
774
|
+
xnd_t next = xnd_union_next(x, &ctx);
|
775
|
+
if (next.ptr == NULL) {
|
776
|
+
Py_DECREF(tmp);
|
777
|
+
return seterr_int(&ctx);
|
778
|
+
}
|
779
|
+
|
780
|
+
return mblock_init(&next, tmp);
|
781
|
+
}
|
782
|
+
|
673
783
|
case Ref: {
|
674
784
|
xnd_t next = xnd_ref_next(x, &ctx);
|
675
785
|
if (next.ptr == NULL) {
|
@@ -806,6 +916,15 @@ mblock_init(xnd_t * const x, PyObject *v)
|
|
806
916
|
return 0;
|
807
917
|
}
|
808
918
|
|
919
|
+
case BFloat16: {
|
920
|
+
double tmp = PyFloat_AsDouble(v);
|
921
|
+
if (tmp == -1 && PyErr_Occurred()) {
|
922
|
+
return -1;
|
923
|
+
}
|
924
|
+
xnd_bfloat_pack(x->ptr, tmp);
|
925
|
+
return 0;
|
926
|
+
}
|
927
|
+
|
809
928
|
case Float16: {
|
810
929
|
#if PY_VERSION_HEX >= 0x03060000
|
811
930
|
double tmp = PyFloat_AsDouble(v);
|
@@ -836,6 +955,16 @@ mblock_init(xnd_t * const x, PyObject *v)
|
|
836
955
|
return _PyFloat_Pack8(tmp, (unsigned char *)x->ptr, le(t->flags));
|
837
956
|
}
|
838
957
|
|
958
|
+
case BComplex32: {
|
959
|
+
Py_complex c = PyComplex_AsCComplex(v);
|
960
|
+
if (c.real == -1.0 && PyErr_Occurred()) {
|
961
|
+
return -1;
|
962
|
+
}
|
963
|
+
xnd_bfloat_pack(x->ptr, c.real);
|
964
|
+
xnd_bfloat_pack(x->ptr+2, c.imag);
|
965
|
+
return 0;
|
966
|
+
}
|
967
|
+
|
839
968
|
case Complex32: {
|
840
969
|
#if PY_VERSION_HEX >= 0x03060000
|
841
970
|
Py_complex c = PyComplex_AsCComplex(v);
|
@@ -1054,6 +1183,43 @@ mblock_init(xnd_t * const x, PyObject *v)
|
|
1054
1183
|
return 0;
|
1055
1184
|
}
|
1056
1185
|
|
1186
|
+
case Array: {
|
1187
|
+
bool overflow = false;
|
1188
|
+
|
1189
|
+
if (!PyList_Check(v)) {
|
1190
|
+
PyErr_Format(PyExc_TypeError,
|
1191
|
+
"xnd: expected list, not '%.200s'", Py_TYPE(v)->tp_name);
|
1192
|
+
return -1;
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
const Py_ssize_t shape = PyList_GET_SIZE(v);
|
1196
|
+
const int64_t size = MULi64(shape, t->Array.itemsize, &overflow);
|
1197
|
+
if (overflow) {
|
1198
|
+
ndt_err_format(&ctx, NDT_ValueError,
|
1199
|
+
"datasize of flexible array is too large");
|
1200
|
+
return seterr_int(&ctx);
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
char *data = ndt_aligned_calloc(t->align, size);
|
1204
|
+
if (data == NULL) {
|
1205
|
+
PyErr_NoMemory();
|
1206
|
+
return -1;
|
1207
|
+
}
|
1208
|
+
|
1209
|
+
xnd_clear(x, XND_OWN_EMBEDDED);
|
1210
|
+
XND_ARRAY_SHAPE(x->ptr) = shape;
|
1211
|
+
XND_ARRAY_DATA(x->ptr) = data;
|
1212
|
+
|
1213
|
+
for (int64_t i = 0; i < shape; i++) {
|
1214
|
+
xnd_t next = xnd_array_next(x, i);
|
1215
|
+
if (mblock_init(&next, PyList_GET_ITEM(v, i)) < 0) {
|
1216
|
+
return -1;
|
1217
|
+
}
|
1218
|
+
}
|
1219
|
+
|
1220
|
+
return 0;
|
1221
|
+
}
|
1222
|
+
|
1057
1223
|
case Categorical: {
|
1058
1224
|
int64_t k;
|
1059
1225
|
|
@@ -1225,20 +1391,59 @@ pyxnd_from_mblock(PyTypeObject *tp, MemoryBlockObject *mblock)
|
|
1225
1391
|
return (PyObject *)self;
|
1226
1392
|
}
|
1227
1393
|
|
1394
|
+
static uint32_t
|
1395
|
+
device_flags(PyObject *tuple)
|
1396
|
+
{
|
1397
|
+
PyObject *device;
|
1398
|
+
PyObject *no;
|
1399
|
+
|
1400
|
+
if (!PyTuple_Check(tuple) || PyTuple_GET_SIZE(tuple) != 2) {
|
1401
|
+
PyErr_SetString(PyExc_TypeError,
|
1402
|
+
"device argument must be of the form (device_name, device_no)");
|
1403
|
+
return UINT32_MAX;
|
1404
|
+
}
|
1405
|
+
|
1406
|
+
device = PyTuple_GET_ITEM(tuple, 0);
|
1407
|
+
if (!PyUnicode_Check(device) ||
|
1408
|
+
PyUnicode_CompareWithASCIIString(device, "cuda") != 0) {
|
1409
|
+
PyErr_SetString(PyExc_ValueError,
|
1410
|
+
"currently only 'cuda' is supported as a device name");
|
1411
|
+
return UINT32_MAX;
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
no = PyTuple_GET_ITEM(tuple, 1);
|
1415
|
+
if (!PyLong_Check(no) || PyLong_AsLong(no) != -1) {
|
1416
|
+
PyErr_SetString(PyExc_ValueError,
|
1417
|
+
"currently only 'cuda:managed' is supported as a device");
|
1418
|
+
return UINT32_MAX;
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
return XND_CUDA_MANAGED;
|
1422
|
+
}
|
1423
|
+
|
1228
1424
|
static PyObject *
|
1229
1425
|
pyxnd_new(PyTypeObject *tp, PyObject *args, PyObject *kwds)
|
1230
1426
|
{
|
1231
|
-
static char *kwlist[] = {"type", "value", NULL};
|
1427
|
+
static char *kwlist[] = {"type", "value", "device", NULL};
|
1232
1428
|
PyObject *type = NULL;
|
1233
1429
|
PyObject *value = NULL;
|
1430
|
+
PyObject *tuple = Py_None;
|
1234
1431
|
MemoryBlockObject *mblock;
|
1432
|
+
uint32_t flags = 0;
|
1235
1433
|
|
1236
|
-
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &type,
|
1237
|
-
&value)) {
|
1434
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &type,
|
1435
|
+
&value, &tuple)) {
|
1238
1436
|
return NULL;
|
1239
1437
|
}
|
1240
1438
|
|
1241
|
-
|
1439
|
+
if (tuple != Py_None) {
|
1440
|
+
flags = device_flags(tuple);
|
1441
|
+
if (flags == UINT32_MAX) {
|
1442
|
+
return NULL;
|
1443
|
+
}
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
mblock = mblock_from_typed_value(type, value, flags);
|
1242
1447
|
if (mblock == NULL) {
|
1243
1448
|
return NULL;
|
1244
1449
|
}
|
@@ -1247,16 +1452,32 @@ pyxnd_new(PyTypeObject *tp, PyObject *args, PyObject *kwds)
|
|
1247
1452
|
}
|
1248
1453
|
|
1249
1454
|
static PyObject *
|
1250
|
-
pyxnd_empty(PyTypeObject *tp, PyObject *
|
1455
|
+
pyxnd_empty(PyTypeObject *tp, PyObject *args, PyObject *kwds)
|
1251
1456
|
{
|
1457
|
+
static char *kwlist[] = {"type", "device", NULL};
|
1458
|
+
PyObject *type = Py_None;
|
1459
|
+
PyObject *tuple = Py_None;
|
1252
1460
|
MemoryBlockObject *mblock;
|
1461
|
+
uint32_t flags = 0;
|
1462
|
+
|
1463
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &type,
|
1464
|
+
&tuple)) {
|
1465
|
+
return NULL;
|
1466
|
+
}
|
1467
|
+
|
1468
|
+
if (tuple != Py_None) {
|
1469
|
+
flags = device_flags(tuple);
|
1470
|
+
if (flags == UINT32_MAX) {
|
1471
|
+
return NULL;
|
1472
|
+
}
|
1473
|
+
}
|
1253
1474
|
|
1254
1475
|
type = Ndt_FromObject(type);
|
1255
1476
|
if (type == NULL) {
|
1256
1477
|
return NULL;
|
1257
1478
|
}
|
1258
1479
|
|
1259
|
-
mblock = mblock_empty(type);
|
1480
|
+
mblock = mblock_empty(type, flags);
|
1260
1481
|
Py_DECREF(type);
|
1261
1482
|
if (mblock == NULL) {
|
1262
1483
|
return NULL;
|
@@ -1290,7 +1511,7 @@ pyxnd_from_buffer_and_type(PyTypeObject *tp, PyObject *args, PyObject *kwds)
|
|
1290
1511
|
return NULL;
|
1291
1512
|
}
|
1292
1513
|
|
1293
|
-
mblock = mblock_from_buffer_and_type(obj, type);
|
1514
|
+
mblock = mblock_from_buffer_and_type(obj, type, 0, -1);
|
1294
1515
|
if (mblock == NULL) {
|
1295
1516
|
return NULL;
|
1296
1517
|
}
|
@@ -1402,6 +1623,23 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1402
1623
|
return lst;
|
1403
1624
|
}
|
1404
1625
|
|
1626
|
+
case VarDimElem: {
|
1627
|
+
int64_t start, step, shape;
|
1628
|
+
|
1629
|
+
shape = ndt_var_indices(&start, &step, t, x->index, &ctx);
|
1630
|
+
if (shape < 0) {
|
1631
|
+
return seterr(&ctx);
|
1632
|
+
}
|
1633
|
+
|
1634
|
+
const int64_t i = adjust_index(t->VarDimElem.index, shape, &ctx);
|
1635
|
+
if (i < 0) {
|
1636
|
+
return seterr(&ctx);
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
const xnd_t next = xnd_var_dim_next(x, start, step, i);
|
1640
|
+
return _pyxnd_value(&next, maxshape);
|
1641
|
+
}
|
1642
|
+
|
1405
1643
|
case Tuple: {
|
1406
1644
|
PyObject *tuple, *v;
|
1407
1645
|
int64_t shape, i;
|
@@ -1485,6 +1723,37 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1485
1723
|
return dict;
|
1486
1724
|
}
|
1487
1725
|
|
1726
|
+
case Union: {
|
1727
|
+
PyObject *tuple, *tag, *v;
|
1728
|
+
|
1729
|
+
tuple = PyTuple_New(2);
|
1730
|
+
if (tuple == NULL) {
|
1731
|
+
return NULL;
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
const uint8_t i = XND_UNION_TAG(x->ptr);
|
1735
|
+
tag = PyUnicode_FromString(t->Union.tags[i]);
|
1736
|
+
if (tag == NULL) {
|
1737
|
+
Py_DECREF(tuple);
|
1738
|
+
return NULL;
|
1739
|
+
}
|
1740
|
+
PyTuple_SET_ITEM(tuple, 0, tag);
|
1741
|
+
|
1742
|
+
const xnd_t next = xnd_union_next(x, &ctx);
|
1743
|
+
if (next.ptr == NULL) {
|
1744
|
+
return seterr(&ctx);
|
1745
|
+
}
|
1746
|
+
|
1747
|
+
v = _pyxnd_value(&next, maxshape);
|
1748
|
+
if (v == NULL) {
|
1749
|
+
Py_DECREF(tuple);
|
1750
|
+
return NULL;
|
1751
|
+
}
|
1752
|
+
PyTuple_SET_ITEM(tuple, 1, v);
|
1753
|
+
|
1754
|
+
return tuple;
|
1755
|
+
}
|
1756
|
+
|
1488
1757
|
case Ref: {
|
1489
1758
|
const xnd_t next = xnd_ref_next(x, &ctx);
|
1490
1759
|
if (next.ptr == NULL) {
|
@@ -1570,6 +1839,11 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1570
1839
|
return PyLong_FromUnsignedLongLong(tmp);
|
1571
1840
|
}
|
1572
1841
|
|
1842
|
+
case BFloat16: {
|
1843
|
+
double tmp = xnd_bfloat_unpack(x->ptr);
|
1844
|
+
return PyFloat_FromDouble(tmp);
|
1845
|
+
}
|
1846
|
+
|
1573
1847
|
case Float16: {
|
1574
1848
|
#if PY_VERSION_HEX >= 0x03060000
|
1575
1849
|
double tmp = _PyFloat_Unpack2((unsigned char *)x->ptr, le(t->flags));
|
@@ -1600,6 +1874,13 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1600
1874
|
return PyFloat_FromDouble(tmp);
|
1601
1875
|
}
|
1602
1876
|
|
1877
|
+
case BComplex32: {
|
1878
|
+
Py_complex c;
|
1879
|
+
c.real = xnd_bfloat_unpack(x->ptr);
|
1880
|
+
c.imag = xnd_bfloat_unpack(x->ptr+2);
|
1881
|
+
return PyComplex_FromCComplex(c);
|
1882
|
+
}
|
1883
|
+
|
1603
1884
|
case Complex32: {
|
1604
1885
|
#if PY_VERSION_HEX >= 0x03060000
|
1605
1886
|
Py_complex c;
|
@@ -1681,8 +1962,8 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1681
1962
|
}
|
1682
1963
|
|
1683
1964
|
case String: {
|
1684
|
-
const char *s =
|
1685
|
-
Py_ssize_t size =
|
1965
|
+
const char *s = XND_STRING_DATA(x->ptr);
|
1966
|
+
Py_ssize_t size = strlen(s);
|
1686
1967
|
|
1687
1968
|
return PyUnicode_FromStringAndSize(s, size);
|
1688
1969
|
}
|
@@ -1694,6 +1975,38 @@ _pyxnd_value(const xnd_t * const x, const int64_t maxshape)
|
|
1694
1975
|
return bytes_from_string_and_size(s, size);
|
1695
1976
|
}
|
1696
1977
|
|
1978
|
+
case Array: {
|
1979
|
+
PyObject *lst, *v;
|
1980
|
+
int64_t shape;
|
1981
|
+
|
1982
|
+
shape = XND_ARRAY_SHAPE(x->ptr);
|
1983
|
+
if (shape > maxshape) {
|
1984
|
+
shape = maxshape;
|
1985
|
+
}
|
1986
|
+
|
1987
|
+
lst = list_new(shape);
|
1988
|
+
if (lst == NULL) {
|
1989
|
+
return NULL;
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
for (int64_t i = 0; i < shape; i++) {
|
1993
|
+
if (i == maxshape-1) {
|
1994
|
+
PyList_SET_ITEM(lst, i, xnd_ellipsis());
|
1995
|
+
break;
|
1996
|
+
}
|
1997
|
+
|
1998
|
+
const xnd_t next = xnd_array_next(x, i);
|
1999
|
+
v = _pyxnd_value(&next, maxshape);
|
2000
|
+
if (v == NULL) {
|
2001
|
+
Py_DECREF(lst);
|
2002
|
+
return NULL;
|
2003
|
+
}
|
2004
|
+
PyList_SET_ITEM(lst, i, v);
|
2005
|
+
}
|
2006
|
+
|
2007
|
+
return lst;
|
2008
|
+
}
|
2009
|
+
|
1697
2010
|
case Categorical: {
|
1698
2011
|
int64_t k;
|
1699
2012
|
|
@@ -1760,10 +2073,11 @@ pyxnd_view_move_type(const XndObject *src, xnd_t *x)
|
|
1760
2073
|
XndObject *view;
|
1761
2074
|
PyObject *type;
|
1762
2075
|
|
1763
|
-
type =
|
2076
|
+
type = Ndt_FromType(x->type);
|
1764
2077
|
if (type == NULL) {
|
1765
2078
|
return NULL;
|
1766
2079
|
}
|
2080
|
+
ndt_decref(x->type);
|
1767
2081
|
|
1768
2082
|
view = pyxnd_alloc(Py_TYPE(src));
|
1769
2083
|
if (view == NULL) {
|
@@ -1813,6 +2127,24 @@ pyxnd_len(const xnd_t *x)
|
|
1813
2127
|
return safe_downcast(shape);
|
1814
2128
|
}
|
1815
2129
|
|
2130
|
+
case VarDimElem: {
|
2131
|
+
NDT_STATIC_CONTEXT(ctx);
|
2132
|
+
int64_t start, step, shape;
|
2133
|
+
|
2134
|
+
shape = ndt_var_indices(&start, &step, t, x->index, &ctx);
|
2135
|
+
if (shape < 0) {
|
2136
|
+
return seterr_int(&ctx);
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
const int64_t i = adjust_index(t->VarDimElem.index, shape, &ctx);
|
2140
|
+
if (i < 0) {
|
2141
|
+
return seterr_int(&ctx);
|
2142
|
+
}
|
2143
|
+
|
2144
|
+
const xnd_t next = xnd_var_dim_next(x, start, step, i);
|
2145
|
+
return pyxnd_len(&next);
|
2146
|
+
}
|
2147
|
+
|
1816
2148
|
case Tuple: {
|
1817
2149
|
return safe_downcast(t->Tuple.shape);
|
1818
2150
|
}
|
@@ -1821,6 +2153,20 @@ pyxnd_len(const xnd_t *x)
|
|
1821
2153
|
return safe_downcast(t->Record.shape);
|
1822
2154
|
}
|
1823
2155
|
|
2156
|
+
case Array: {
|
2157
|
+
const int64_t shape = XND_ARRAY_SHAPE(x->ptr);
|
2158
|
+
return safe_downcast(shape);
|
2159
|
+
}
|
2160
|
+
|
2161
|
+
case Union: {
|
2162
|
+
const xnd_t next = xnd_union_next(x, &ctx);
|
2163
|
+
if (next.ptr == NULL) {
|
2164
|
+
return seterr_int(&ctx);
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
return pyxnd_len(&next);
|
2168
|
+
}
|
2169
|
+
|
1824
2170
|
case Ref: {
|
1825
2171
|
const xnd_t next = xnd_ref_next(x, &ctx);
|
1826
2172
|
if (next.ptr == NULL) {
|
@@ -1932,7 +2278,7 @@ convert_key(xnd_index_t *indices, int *len, PyObject *key)
|
|
1932
2278
|
}
|
1933
2279
|
}
|
1934
2280
|
|
1935
|
-
*len = size;
|
2281
|
+
*len = (int)size;
|
1936
2282
|
return flags;
|
1937
2283
|
}
|
1938
2284
|
|
@@ -1962,36 +2308,99 @@ pyxnd_subscript(XndObject *self, PyObject *key)
|
|
1962
2308
|
return pyxnd_view_move_type(self, &x);
|
1963
2309
|
}
|
1964
2310
|
|
1965
|
-
static void
|
1966
|
-
free_slices(xnd_t *lst, int64_t start, int64_t stop)
|
1967
|
-
{
|
1968
|
-
for (int64_t i = start; i < stop; i++) {
|
1969
|
-
ndt_del((ndt_t *)lst[i].type);
|
1970
|
-
}
|
1971
|
-
|
1972
|
-
ndt_free(lst);
|
1973
|
-
}
|
1974
|
-
|
1975
2311
|
static PyObject *
|
1976
|
-
|
2312
|
+
pyxnd_reshape(PyObject *self, PyObject *args, PyObject *kwds)
|
1977
2313
|
{
|
1978
|
-
static char *kwlist[] = {"
|
2314
|
+
static char *kwlist[] = {"shape", "order", NULL};
|
1979
2315
|
NDT_STATIC_CONTEXT(ctx);
|
1980
|
-
PyObject *
|
1981
|
-
PyObject *
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1986
|
-
|
1987
|
-
|
2316
|
+
PyObject *tuple = NULL;
|
2317
|
+
PyObject *order = Py_None;
|
2318
|
+
int64_t shape[NDT_MAX_DIM];
|
2319
|
+
char ord = 'C';
|
2320
|
+
Py_ssize_t n;
|
2321
|
+
|
2322
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &tuple,
|
2323
|
+
&order)) {
|
1988
2324
|
return NULL;
|
1989
2325
|
}
|
1990
2326
|
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
2327
|
+
if (order != Py_None) {
|
2328
|
+
const char *c = PyUnicode_AsUTF8(order);
|
2329
|
+
if (strlen(c) != 1) {
|
2330
|
+
PyErr_SetString(PyExc_TypeError,
|
2331
|
+
"'order' argument must be a 'C', 'F' or 'A'");
|
2332
|
+
return NULL;
|
2333
|
+
}
|
2334
|
+
ord = c[0];
|
2335
|
+
}
|
2336
|
+
|
2337
|
+
if (!PyTuple_Check(tuple)) {
|
2338
|
+
PyErr_SetString(PyExc_TypeError,
|
2339
|
+
"'shape' argument must be a tuple");
|
2340
|
+
return NULL;
|
2341
|
+
}
|
2342
|
+
|
2343
|
+
n = PyTuple_GET_SIZE(tuple);
|
2344
|
+
if (n > NDT_MAX_DIM) {
|
2345
|
+
PyErr_SetString(PyExc_ValueError, "too many dimensions");
|
2346
|
+
return NULL;
|
2347
|
+
}
|
2348
|
+
|
2349
|
+
for (int i = 0; i < n; i++) {
|
2350
|
+
shape[i] = PyLong_AsLongLong(PyTuple_GET_ITEM(tuple, i));
|
2351
|
+
if (shape[i] < 0) {
|
2352
|
+
if (PyErr_Occurred()) {
|
2353
|
+
return NULL;
|
2354
|
+
}
|
2355
|
+
PyErr_SetString(PyExc_ValueError, "negative dimension size");
|
2356
|
+
return NULL;
|
2357
|
+
}
|
2358
|
+
}
|
2359
|
+
|
2360
|
+
xnd_t view = xnd_reshape(XND(self), shape, (int)n, ord, &ctx);
|
2361
|
+
if (xnd_err_occurred(&view)) {
|
2362
|
+
return seterr(&ctx);
|
2363
|
+
}
|
2364
|
+
|
2365
|
+
return pyxnd_view_move_type((XndObject *)self, &view);
|
2366
|
+
}
|
2367
|
+
|
2368
|
+
static void
|
2369
|
+
free_slices(xnd_t *lst, int64_t start, int64_t stop)
|
2370
|
+
{
|
2371
|
+
for (int64_t i = start; i < stop; i++) {
|
2372
|
+
ndt_decref(lst[i].type);
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
ndt_free(lst);
|
2376
|
+
}
|
2377
|
+
|
2378
|
+
static PyObject *
|
2379
|
+
pyxnd_split(PyObject *self, PyObject *args, PyObject *kwds)
|
2380
|
+
{
|
2381
|
+
static char *kwlist[] = {"n", "max_outer", NULL};
|
2382
|
+
NDT_STATIC_CONTEXT(ctx);
|
2383
|
+
PyObject *max = Py_None;
|
2384
|
+
PyObject *nparts;
|
2385
|
+
int max_outer = NDT_MAX_DIM;
|
2386
|
+
PyObject *res;
|
2387
|
+
xnd_t *slices;
|
2388
|
+
int64_t n;
|
2389
|
+
|
2390
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &nparts, &max)) {
|
2391
|
+
return NULL;
|
2392
|
+
}
|
2393
|
+
|
2394
|
+
n = PyLong_AsLongLong(nparts);
|
2395
|
+
if (n == -1 && PyErr_Occurred()) {
|
2396
|
+
return NULL;
|
2397
|
+
}
|
2398
|
+
|
2399
|
+
if (n < 1 || n > INT32_MAX) {
|
2400
|
+
PyErr_SetString(PyExc_ValueError,
|
2401
|
+
"n must be in [1, INT32_MAX]");
|
2402
|
+
return NULL;
|
2403
|
+
}
|
1995
2404
|
|
1996
2405
|
if (max != Py_None) {
|
1997
2406
|
long l = PyLong_AsLong(max);
|
@@ -2011,7 +2420,7 @@ pyxnd_split(PyObject *self, PyObject *args, PyObject *kwds)
|
|
2011
2420
|
return seterr(&ctx);
|
2012
2421
|
}
|
2013
2422
|
|
2014
|
-
res = PyList_New(n);
|
2423
|
+
res = PyList_New((Py_ssize_t)n);
|
2015
2424
|
if (res == NULL) {
|
2016
2425
|
free_slices(slices, 0, n);
|
2017
2426
|
return NULL;
|
@@ -2038,7 +2447,6 @@ pyxnd_assign(XndObject *self, PyObject *key, PyObject *value)
|
|
2038
2447
|
NDT_STATIC_CONTEXT(ctx);
|
2039
2448
|
xnd_index_t indices[NDT_MAX_DIM];
|
2040
2449
|
xnd_t x;
|
2041
|
-
int free_type = 0;
|
2042
2450
|
int ret, len;
|
2043
2451
|
uint8_t flags;
|
2044
2452
|
|
@@ -2057,20 +2465,7 @@ pyxnd_assign(XndObject *self, PyObject *key, PyObject *value)
|
|
2057
2465
|
return -1;
|
2058
2466
|
}
|
2059
2467
|
|
2060
|
-
|
2061
|
-
x = xnd_multikey(&self->xnd, indices, len, &ctx);
|
2062
|
-
if (x.ptr == NULL) {
|
2063
|
-
return seterr_int(&ctx);
|
2064
|
-
}
|
2065
|
-
free_type = 1;
|
2066
|
-
}
|
2067
|
-
else {
|
2068
|
-
x = xnd_subtree(&self->xnd, indices, len, &ctx);
|
2069
|
-
if (x.ptr == NULL) {
|
2070
|
-
return seterr_int(&ctx);
|
2071
|
-
}
|
2072
|
-
}
|
2073
|
-
|
2468
|
+
x = xnd_subscript(&self->xnd, indices, len, &ctx);
|
2074
2469
|
if (x.ptr == NULL) {
|
2075
2470
|
return seterr_int(&ctx);
|
2076
2471
|
}
|
@@ -2085,10 +2480,7 @@ pyxnd_assign(XndObject *self, PyObject *key, PyObject *value)
|
|
2085
2480
|
ret = mblock_init(&x, value);
|
2086
2481
|
}
|
2087
2482
|
|
2088
|
-
|
2089
|
-
ndt_del((ndt_t *)x.type);
|
2090
|
-
}
|
2091
|
-
|
2483
|
+
ndt_decref(x.type);
|
2092
2484
|
return ret;
|
2093
2485
|
}
|
2094
2486
|
|
@@ -2108,6 +2500,65 @@ pyxnd_item(XndObject *self, Py_ssize_t index)
|
|
2108
2500
|
return res;
|
2109
2501
|
}
|
2110
2502
|
|
2503
|
+
static PyObject *
|
2504
|
+
pyxnd_transpose(PyObject *self, PyObject *args, PyObject *kwds)
|
2505
|
+
{
|
2506
|
+
static char *kwlist[] = {"permute", NULL};
|
2507
|
+
NDT_STATIC_CONTEXT(ctx);
|
2508
|
+
PyObject *permute = Py_None;
|
2509
|
+
int p[NDT_MAX_ARGS];
|
2510
|
+
const ndt_t *t;
|
2511
|
+
xnd_t x;
|
2512
|
+
|
2513
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &permute)) {
|
2514
|
+
return NULL;
|
2515
|
+
}
|
2516
|
+
|
2517
|
+
if (permute != Py_None) {
|
2518
|
+
if (!PyList_Check(permute) && !PyTuple_Check(permute)) {
|
2519
|
+
PyErr_SetString(PyExc_TypeError,
|
2520
|
+
"the 'permute' argument must be a list or a tuple");
|
2521
|
+
return NULL;
|
2522
|
+
}
|
2523
|
+
|
2524
|
+
const Py_ssize_t len = PySequence_Fast_GET_SIZE(permute);
|
2525
|
+
|
2526
|
+
if (len > NDT_MAX_ARGS) {
|
2527
|
+
PyErr_SetString(PyExc_ValueError, "permutation list too long");
|
2528
|
+
return NULL;
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
for (int i = 0; i < len; i++) {
|
2532
|
+
int v = PyLong_AsLong(PySequence_Fast_GET_ITEM(permute, i));
|
2533
|
+
if (v == -1 && PyErr_Occurred()) {
|
2534
|
+
return NULL;
|
2535
|
+
}
|
2536
|
+
|
2537
|
+
if (v < 0 || v > INT_MAX) {
|
2538
|
+
PyErr_SetString(PyExc_ValueError,
|
2539
|
+
"permutation index out of bounds");
|
2540
|
+
return NULL;
|
2541
|
+
}
|
2542
|
+
|
2543
|
+
p[i] = (int)v;
|
2544
|
+
}
|
2545
|
+
|
2546
|
+
t = ndt_transpose(XND_TYPE(self), p, (int)len, &ctx);
|
2547
|
+
}
|
2548
|
+
else {
|
2549
|
+
t = ndt_transpose(XND_TYPE(self), NULL, 0, &ctx);
|
2550
|
+
}
|
2551
|
+
|
2552
|
+
if (t == NULL) {
|
2553
|
+
return seterr(&ctx);
|
2554
|
+
}
|
2555
|
+
|
2556
|
+
x = *XND(self);
|
2557
|
+
x.type = t;
|
2558
|
+
|
2559
|
+
return pyxnd_view_move_type((XndObject *)self, &x);
|
2560
|
+
}
|
2561
|
+
|
2111
2562
|
static PyObject *
|
2112
2563
|
pyxnd_short_value(PyObject *self, PyObject *args, PyObject *kwds)
|
2113
2564
|
{
|
@@ -2165,6 +2616,13 @@ pyxnd_type(PyObject *self, PyObject *args UNUSED)
|
|
2165
2616
|
return TYPE_OWNER(self);
|
2166
2617
|
}
|
2167
2618
|
|
2619
|
+
static PyObject *
|
2620
|
+
pyxnd_dtype(PyObject *self, PyObject *args UNUSED)
|
2621
|
+
{
|
2622
|
+
const ndt_t *dtype = ndt_dtype(XND_TYPE(self));
|
2623
|
+
return Ndt_FromType(dtype);
|
2624
|
+
}
|
2625
|
+
|
2168
2626
|
static PyObject *
|
2169
2627
|
pyxnd_ndim(PyObject *self, PyObject *args UNUSED)
|
2170
2628
|
{
|
@@ -2185,13 +2643,273 @@ pyxnd_align(PyObject *self, PyObject *args UNUSED)
|
|
2185
2643
|
return PyLong_FromUnsignedLong(align);
|
2186
2644
|
}
|
2187
2645
|
|
2646
|
+
static PyObject *
|
2647
|
+
pyxnd_device(XndObject *self, PyObject *args UNUSED)
|
2648
|
+
{
|
2649
|
+
uint32_t flags = self->mblock->xnd->flags;
|
2650
|
+
|
2651
|
+
if (flags & XND_CUDA_MANAGED) {
|
2652
|
+
return PyUnicode_FromString("cuda:managed");
|
2653
|
+
}
|
2654
|
+
|
2655
|
+
Py_RETURN_NONE;
|
2656
|
+
}
|
2657
|
+
|
2658
|
+
static PyObject *
|
2659
|
+
pyxnd_copy_contiguous(PyObject *self, PyObject *args, PyObject *kwargs)
|
2660
|
+
{
|
2661
|
+
static char *kwlist[] = {"dtype", NULL};
|
2662
|
+
NDT_STATIC_CONTEXT(ctx);
|
2663
|
+
XndObject *src = (XndObject *)self;
|
2664
|
+
PyObject *dtype = Py_None;
|
2665
|
+
PyObject *dest;
|
2666
|
+
const ndt_t *t;
|
2667
|
+
|
2668
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &dtype)) {
|
2669
|
+
return NULL;
|
2670
|
+
}
|
2671
|
+
|
2672
|
+
if (dtype != Py_None) {
|
2673
|
+
if (!Ndt_Check(dtype)) {
|
2674
|
+
PyErr_Format(PyExc_TypeError,
|
2675
|
+
"dtype argument must be 'ndt', got '%.200s'",
|
2676
|
+
Py_TYPE(dtype)->tp_name);
|
2677
|
+
return NULL;
|
2678
|
+
}
|
2679
|
+
t = ndt_copy_contiguous_dtype(XND_TYPE(src), NDT(dtype), XND_INDEX(src),
|
2680
|
+
&ctx);
|
2681
|
+
}
|
2682
|
+
else {
|
2683
|
+
t = ndt_copy_contiguous(XND_TYPE(src), XND_INDEX(src), &ctx);
|
2684
|
+
}
|
2685
|
+
|
2686
|
+
if (t == NULL) {
|
2687
|
+
return seterr(&ctx);
|
2688
|
+
}
|
2689
|
+
|
2690
|
+
dest = Xnd_EmptyFromType(Py_TYPE(src), t, 0);
|
2691
|
+
ndt_decref(t);
|
2692
|
+
if (dest == NULL) {
|
2693
|
+
return NULL;
|
2694
|
+
}
|
2695
|
+
|
2696
|
+
if (xnd_copy(XND(dest), XND(src), src->mblock->xnd->flags, &ctx) < 0) {
|
2697
|
+
Py_DECREF(dest);
|
2698
|
+
return seterr(&ctx);
|
2699
|
+
}
|
2700
|
+
|
2701
|
+
return dest;
|
2702
|
+
}
|
2703
|
+
|
2704
|
+
static PyObject *
|
2705
|
+
pyxnd_tobytes(PyObject *self, PyObject *args UNUSED)
|
2706
|
+
{
|
2707
|
+
NDT_STATIC_CONTEXT(ctx);
|
2708
|
+
XndObject *src = (XndObject *)self;
|
2709
|
+
const ndt_t *t = XND_TYPE(self);
|
2710
|
+
PyObject *b;
|
2711
|
+
|
2712
|
+
if (!ndt_is_pointer_free(t)) {
|
2713
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2714
|
+
"tobytes() is not implemented for memory blocks with pointers");
|
2715
|
+
return NULL;
|
2716
|
+
}
|
2717
|
+
|
2718
|
+
if (ndt_is_optional(t) || ndt_subtree_is_optional(t)) {
|
2719
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2720
|
+
"serializing bitmaps is not implemented");
|
2721
|
+
return NULL;
|
2722
|
+
}
|
2723
|
+
|
2724
|
+
if (!ndt_is_ndarray(t)) {
|
2725
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2726
|
+
"tobytes() is only implemented for ndarrays");
|
2727
|
+
return NULL;
|
2728
|
+
}
|
2729
|
+
|
2730
|
+
const bool contiguous = ndt_is_c_contiguous(t) || ndt_is_f_contiguous(t) ||
|
2731
|
+
ndt_is_var_contiguous(t);
|
2732
|
+
|
2733
|
+
if (contiguous) {
|
2734
|
+
ndt_incref(t);
|
2735
|
+
}
|
2736
|
+
else {
|
2737
|
+
t = ndt_copy_contiguous(XND_TYPE(src), XND_INDEX(src), &ctx);
|
2738
|
+
if (t == NULL) {
|
2739
|
+
return seterr(&ctx);
|
2740
|
+
}
|
2741
|
+
}
|
2742
|
+
|
2743
|
+
b = PyBytes_FromStringAndSize(NULL, t->datasize);
|
2744
|
+
if (b == NULL) {
|
2745
|
+
ndt_decref(t);
|
2746
|
+
return NULL;
|
2747
|
+
}
|
2748
|
+
char *cp = PyBytes_AS_STRING(b);
|
2749
|
+
|
2750
|
+
|
2751
|
+
if (contiguous) {
|
2752
|
+
char *ptr = XND(src)->ptr;
|
2753
|
+
if (t->ndim != 0) {
|
2754
|
+
ptr += XND_INDEX(src) * t->Concrete.FixedDim.itemsize;
|
2755
|
+
}
|
2756
|
+
|
2757
|
+
memcpy(cp, ptr, t->datasize);
|
2758
|
+
}
|
2759
|
+
else {
|
2760
|
+
xnd_t x = xnd_error;
|
2761
|
+
x.type = t;
|
2762
|
+
x.ptr = cp;
|
2763
|
+
|
2764
|
+
if (xnd_copy(&x, XND(src), src->mblock->xnd->flags, &ctx) < 0) {
|
2765
|
+
Py_DECREF(b);
|
2766
|
+
ndt_decref(t);
|
2767
|
+
return seterr(&ctx);
|
2768
|
+
}
|
2769
|
+
}
|
2770
|
+
|
2771
|
+
ndt_decref(t);
|
2772
|
+
return b;
|
2773
|
+
}
|
2774
|
+
|
2775
|
+
static PyObject *
|
2776
|
+
_serialize(XndObject *self)
|
2777
|
+
{
|
2778
|
+
NDT_STATIC_CONTEXT(ctx);
|
2779
|
+
bool overflow = false;
|
2780
|
+
const xnd_t *x = XND(self);
|
2781
|
+
const ndt_t *t = XND_TYPE(self);
|
2782
|
+
PyObject *result;
|
2783
|
+
char *cp, *s;
|
2784
|
+
int64_t tlen;
|
2785
|
+
int64_t size;
|
2786
|
+
|
2787
|
+
if (!ndt_is_pointer_free(t)) {
|
2788
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2789
|
+
"serializing memory blocks with pointers is not implemented");
|
2790
|
+
return NULL;
|
2791
|
+
}
|
2792
|
+
|
2793
|
+
if (ndt_is_optional(t) || ndt_subtree_is_optional(t)) {
|
2794
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2795
|
+
"serializing bitmaps is not implemented");
|
2796
|
+
return NULL;
|
2797
|
+
}
|
2798
|
+
|
2799
|
+
if (!ndt_is_c_contiguous(t) && !ndt_is_f_contiguous(t) &&
|
2800
|
+
!ndt_is_var_contiguous(t)) {
|
2801
|
+
PyErr_SetString(PyExc_NotImplementedError,
|
2802
|
+
"serializing non-contiguous memory blocks is not implemented");
|
2803
|
+
return NULL;
|
2804
|
+
}
|
2805
|
+
|
2806
|
+
tlen = ndt_serialize(&s, t, &ctx);
|
2807
|
+
if (tlen < 0) {
|
2808
|
+
return seterr(&ctx);
|
2809
|
+
}
|
2810
|
+
|
2811
|
+
size = ADDi64(t->datasize, tlen, &overflow);
|
2812
|
+
size = ADDi64(size, 8, &overflow);
|
2813
|
+
if (overflow) {
|
2814
|
+
PyErr_SetString(PyExc_OverflowError, "too large to serialize");
|
2815
|
+
ndt_free(s);
|
2816
|
+
return NULL;
|
2817
|
+
}
|
2818
|
+
|
2819
|
+
result = PyBytes_FromStringAndSize(NULL, size);
|
2820
|
+
cp = PyBytes_AS_STRING(result);
|
2821
|
+
|
2822
|
+
char *ptr = x->ptr;
|
2823
|
+
if (t->ndim != 0) {
|
2824
|
+
ptr = x->ptr + x->index * t->Concrete.FixedDim.itemsize;
|
2825
|
+
}
|
2826
|
+
|
2827
|
+
memcpy(cp, ptr, t->datasize); cp += t->datasize;
|
2828
|
+
memcpy(cp, s, tlen); cp += tlen;
|
2829
|
+
memcpy(cp, &t->datasize, 8);
|
2830
|
+
ndt_free(s);
|
2831
|
+
|
2832
|
+
return result;
|
2833
|
+
}
|
2834
|
+
|
2835
|
+
static PyObject *
|
2836
|
+
pyxnd_serialize(PyObject *self, PyObject *args UNUSED)
|
2837
|
+
{
|
2838
|
+
return _serialize((XndObject *)self);
|
2839
|
+
}
|
2840
|
+
|
2841
|
+
static PyObject *
|
2842
|
+
pyxnd_deserialize(PyTypeObject *tp, PyObject *v)
|
2843
|
+
{
|
2844
|
+
NDT_STATIC_CONTEXT(ctx);
|
2845
|
+
MemoryBlockObject *mblock;
|
2846
|
+
bool overflow = false;
|
2847
|
+
int64_t mblock_size;
|
2848
|
+
|
2849
|
+
if (!PyBytes_Check(v)) {
|
2850
|
+
PyErr_Format(PyExc_TypeError,
|
2851
|
+
"expected bytes object, not '%.200s'", Py_TYPE(v)->tp_name);
|
2852
|
+
return NULL;
|
2853
|
+
}
|
2854
|
+
|
2855
|
+
const int64_t size = PyBytes_GET_SIZE(v);
|
2856
|
+
if (size < 8) {
|
2857
|
+
goto invalid_format;
|
2858
|
+
}
|
2859
|
+
|
2860
|
+
const char *s = PyBytes_AS_STRING(v);
|
2861
|
+
memcpy(&mblock_size, s+size-8, 8);
|
2862
|
+
if (mblock_size < 0) {
|
2863
|
+
goto invalid_format;
|
2864
|
+
}
|
2865
|
+
|
2866
|
+
const int64_t tmp = ADDi64(mblock_size, 8, &overflow);
|
2867
|
+
const int64_t tlen = size-tmp;
|
2868
|
+
if (overflow || tlen < 0) {
|
2869
|
+
goto invalid_format;
|
2870
|
+
}
|
2871
|
+
|
2872
|
+
const ndt_t *t = ndt_deserialize(s+mblock_size, tlen, &ctx);
|
2873
|
+
if (t == NULL) {
|
2874
|
+
return seterr(&ctx);
|
2875
|
+
}
|
2876
|
+
|
2877
|
+
if (t->datasize != mblock_size) {
|
2878
|
+
goto invalid_format;
|
2879
|
+
}
|
2880
|
+
|
2881
|
+
PyObject *type = Ndt_FromType(t);
|
2882
|
+
ndt_decref(t);
|
2883
|
+
if (type == NULL) {
|
2884
|
+
return NULL;
|
2885
|
+
}
|
2886
|
+
|
2887
|
+
mblock = mblock_empty(type, XND_OWN_EMBEDDED);
|
2888
|
+
Py_DECREF(type);
|
2889
|
+
if (mblock == NULL) {
|
2890
|
+
return NULL;
|
2891
|
+
}
|
2892
|
+
|
2893
|
+
memcpy(mblock->xnd->master.ptr, s, mblock_size);
|
2894
|
+
|
2895
|
+
return pyxnd_from_mblock(tp, mblock);
|
2896
|
+
|
2897
|
+
|
2898
|
+
invalid_format:
|
2899
|
+
PyErr_SetString(PyExc_ValueError,
|
2900
|
+
"invalid format for xnd deserialization");
|
2901
|
+
return NULL;
|
2902
|
+
}
|
2903
|
+
|
2188
2904
|
|
2189
2905
|
static PyGetSetDef pyxnd_getsets [] =
|
2190
2906
|
{
|
2191
2907
|
{ "type", (getter)pyxnd_type, NULL, doc_type, NULL},
|
2908
|
+
{ "dtype", (getter)pyxnd_dtype, NULL, NULL, NULL},
|
2192
2909
|
{ "value", (getter)pyxnd_value, NULL, doc_value, NULL},
|
2193
2910
|
{ "align", (getter)pyxnd_align, NULL, doc_align, NULL},
|
2194
2911
|
{ "ndim", (getter)pyxnd_ndim, NULL, doc_ndim, NULL},
|
2912
|
+
{ "device", (getter)pyxnd_device, NULL, NULL, NULL},
|
2195
2913
|
{NULL}
|
2196
2914
|
};
|
2197
2915
|
|
@@ -2214,12 +2932,18 @@ static PyMethodDef pyxnd_methods [] =
|
|
2214
2932
|
/* Methods */
|
2215
2933
|
{ "short_value", (PyCFunction)pyxnd_short_value, METH_VARARGS|METH_KEYWORDS, doc_short_value },
|
2216
2934
|
{ "strict_equal", (PyCFunction)pyxnd_strict_equal, METH_O, NULL },
|
2935
|
+
{ "copy_contiguous", (PyCFunction)pyxnd_copy_contiguous, METH_VARARGS|METH_KEYWORDS, NULL },
|
2217
2936
|
{ "split", (PyCFunction)pyxnd_split, METH_VARARGS|METH_KEYWORDS, NULL },
|
2937
|
+
{ "transpose", (PyCFunction)pyxnd_transpose, METH_VARARGS|METH_KEYWORDS, NULL },
|
2938
|
+
{ "tobytes", (PyCFunction)pyxnd_tobytes, METH_NOARGS, NULL },
|
2939
|
+
{ "_reshape", (PyCFunction)pyxnd_reshape, METH_VARARGS|METH_KEYWORDS, NULL },
|
2940
|
+
{ "_serialize", (PyCFunction)pyxnd_serialize, METH_NOARGS, NULL },
|
2218
2941
|
|
2219
2942
|
/* Class methods */
|
2220
|
-
{ "empty", (PyCFunction)pyxnd_empty,
|
2943
|
+
{ "empty", (PyCFunction)pyxnd_empty, METH_VARARGS|METH_KEYWORDS|METH_CLASS, doc_empty },
|
2221
2944
|
{ "from_buffer", (PyCFunction)pyxnd_from_buffer, METH_O|METH_CLASS, doc_from_buffer },
|
2222
|
-
{ "
|
2945
|
+
{ "from_buffer_and_type", (PyCFunction)pyxnd_from_buffer_and_type, METH_VARARGS|METH_KEYWORDS|METH_CLASS, NULL },
|
2946
|
+
{ "deserialize", (PyCFunction)pyxnd_deserialize, METH_O|METH_CLASS, NULL },
|
2223
2947
|
|
2224
2948
|
{ NULL, NULL, 1 }
|
2225
2949
|
};
|
@@ -2455,32 +3179,856 @@ static PyTypeObject Xnd_Type =
|
|
2455
3179
|
|
2456
3180
|
|
2457
3181
|
/****************************************************************************/
|
2458
|
-
/*
|
3182
|
+
/* Type inference */
|
2459
3183
|
/****************************************************************************/
|
2460
3184
|
|
2461
|
-
|
3185
|
+
/**********************************************************************/
|
3186
|
+
/* Extract data and shapes from a value (possibly a nested list) */
|
3187
|
+
/**********************************************************************/
|
2462
3188
|
|
3189
|
+
#undef max
|
2463
3190
|
static int
|
2464
|
-
|
3191
|
+
max(int x, int y)
|
2465
3192
|
{
|
2466
|
-
return
|
3193
|
+
return x >= y ? x : y;
|
2467
3194
|
}
|
2468
3195
|
|
3196
|
+
#undef min
|
2469
3197
|
static int
|
2470
|
-
|
3198
|
+
min(int x, int y)
|
2471
3199
|
{
|
2472
|
-
return
|
3200
|
+
return x <= y ? x : y;
|
2473
3201
|
}
|
2474
3202
|
|
2475
|
-
|
2476
|
-
|
3203
|
+
#define XND_NONE 0x0001U
|
3204
|
+
#define XND_DATA 0x0002U
|
3205
|
+
#define XND_LIST 0x0004U
|
3206
|
+
|
3207
|
+
static inline int
|
3208
|
+
check_level(int level)
|
2477
3209
|
{
|
2478
|
-
|
2479
|
-
|
3210
|
+
if (level >= NDT_MAX_DIM) {
|
3211
|
+
PyErr_Format(PyExc_ValueError,
|
3212
|
+
"too many dimensions, max %d", NDT_MAX_DIM);
|
3213
|
+
return -1;
|
3214
|
+
}
|
3215
|
+
|
3216
|
+
return 0;
|
3217
|
+
}
|
3218
|
+
|
3219
|
+
static int
|
3220
|
+
search(int level, PyObject *v, PyObject *data, PyObject *acc[NDT_MAX_DIM],
|
3221
|
+
int *min_level, int *max_level)
|
3222
|
+
{
|
3223
|
+
PyObject *shape;
|
3224
|
+
PyObject *item;
|
3225
|
+
Py_ssize_t len, i;
|
3226
|
+
int next_level;
|
3227
|
+
int ret;
|
3228
|
+
|
3229
|
+
if (PyList_Check(v)) {
|
3230
|
+
if (check_level(level) < 0) {
|
3231
|
+
return -1;
|
3232
|
+
}
|
3233
|
+
|
3234
|
+
len = PyList_GET_SIZE(v);
|
3235
|
+
shape = PyLong_FromSsize_t(len);
|
3236
|
+
if (shape == NULL) {
|
3237
|
+
return -1;
|
3238
|
+
}
|
3239
|
+
|
3240
|
+
ret = PyList_Append(acc[level], shape);
|
3241
|
+
Py_DECREF(shape);
|
3242
|
+
if (ret < 0) {
|
3243
|
+
return -1;
|
3244
|
+
}
|
3245
|
+
|
3246
|
+
next_level = level + 1;
|
3247
|
+
*max_level = max(next_level, *max_level);
|
3248
|
+
|
3249
|
+
if (len == 0) {
|
3250
|
+
*min_level = min(next_level, *min_level);
|
3251
|
+
}
|
3252
|
+
else {
|
3253
|
+
uint32_t types = 0;
|
3254
|
+
for (i = 0; i < len; i++) {
|
3255
|
+
item = PyList_GET_ITEM(v, i);
|
3256
|
+
if (item == Py_None) {
|
3257
|
+
types |= XND_NONE;
|
3258
|
+
}
|
3259
|
+
else if (PyList_Check(item)) {
|
3260
|
+
types |= XND_LIST;
|
3261
|
+
}
|
3262
|
+
else {
|
3263
|
+
types |= XND_DATA;
|
3264
|
+
}
|
3265
|
+
}
|
3266
|
+
|
3267
|
+
if (!(types & XND_LIST)) {
|
3268
|
+
for (i = 0; i < len; i++) {
|
3269
|
+
item = PyList_GET_ITEM(v, i);
|
3270
|
+
if (PyList_Append(data, item) < 0) {
|
3271
|
+
return -1;
|
3272
|
+
}
|
3273
|
+
}
|
3274
|
+
*min_level = min(next_level, *min_level);
|
3275
|
+
}
|
3276
|
+
else if (!(types & XND_DATA)) {
|
3277
|
+
if (check_level(next_level) < 0) {
|
3278
|
+
return -1;
|
3279
|
+
}
|
3280
|
+
|
3281
|
+
for (i = 0; i < len; i++) {
|
3282
|
+
item = PyList_GET_ITEM(v, i);
|
3283
|
+
if (item == Py_None) {
|
3284
|
+
if (PyList_Append(acc[next_level], item) < 0) {
|
3285
|
+
return -1;
|
3286
|
+
}
|
3287
|
+
}
|
3288
|
+
else {
|
3289
|
+
if (search(next_level, item, data, acc,
|
3290
|
+
min_level, max_level) < 0) {
|
3291
|
+
return -1;
|
3292
|
+
}
|
3293
|
+
}
|
3294
|
+
}
|
3295
|
+
}
|
3296
|
+
else {
|
3297
|
+
PyErr_Format(PyExc_ValueError,
|
3298
|
+
"lists that contain both data and lists cannot be typed");
|
3299
|
+
return -1;
|
3300
|
+
}
|
3301
|
+
}
|
3302
|
+
}
|
3303
|
+
else {
|
3304
|
+
if (PyList_Append(data, v) < 0) {
|
3305
|
+
return -1;
|
3306
|
+
}
|
3307
|
+
*min_level = min(level, *min_level);
|
3308
|
+
}
|
3309
|
+
|
3310
|
+
return 0;
|
2480
3311
|
}
|
2481
3312
|
|
2482
3313
|
static PyObject *
|
2483
|
-
|
3314
|
+
data_shapes(PyObject *m UNUSED, PyObject *v)
|
3315
|
+
{
|
3316
|
+
PyObject *acc[NDT_MAX_DIM] = {NULL};
|
3317
|
+
PyObject *data = NULL;
|
3318
|
+
PyObject *shapes = NULL;
|
3319
|
+
PyObject *tuple = NULL;
|
3320
|
+
int min_level = NDT_MAX_DIM;
|
3321
|
+
int max_level = 0;
|
3322
|
+
int i, k;
|
3323
|
+
|
3324
|
+
data = PyList_New(0);
|
3325
|
+
if (data == NULL) {
|
3326
|
+
return NULL;
|
3327
|
+
}
|
3328
|
+
|
3329
|
+
for (i = 0; i < NDT_MAX_DIM; i++) {
|
3330
|
+
acc[i] = PyList_New(0);
|
3331
|
+
if (acc[i] == NULL) {
|
3332
|
+
goto error;
|
3333
|
+
}
|
3334
|
+
}
|
3335
|
+
|
3336
|
+
if (search(0, v, data, acc, &min_level, &max_level) < 0) {
|
3337
|
+
goto error;
|
3338
|
+
}
|
3339
|
+
|
3340
|
+
if (min_level != max_level) {
|
3341
|
+
PyErr_Format(PyExc_ValueError,
|
3342
|
+
"unbalanced nested list: min depth: %d max depth: %d",
|
3343
|
+
min_level, max_level);
|
3344
|
+
goto error;
|
3345
|
+
}
|
3346
|
+
|
3347
|
+
shapes = PyList_New(max_level);
|
3348
|
+
if (shapes == NULL) {
|
3349
|
+
goto error;
|
3350
|
+
}
|
3351
|
+
|
3352
|
+
for (i=0, k=max_level-1; i < max_level; i++, k--) {
|
3353
|
+
PyList_SET_ITEM(shapes, i, acc[k]);
|
3354
|
+
}
|
3355
|
+
|
3356
|
+
for (; i < NDT_MAX_DIM; i++) {
|
3357
|
+
Py_DECREF(acc[i]);
|
3358
|
+
}
|
3359
|
+
|
3360
|
+
tuple = PyTuple_New(2);
|
3361
|
+
if (tuple == NULL) {
|
3362
|
+
Py_DECREF(data);
|
3363
|
+
Py_DECREF(shapes);
|
3364
|
+
return NULL;
|
3365
|
+
}
|
3366
|
+
PyTuple_SET_ITEM(tuple, 0, data);
|
3367
|
+
PyTuple_SET_ITEM(tuple, 1, shapes);
|
3368
|
+
|
3369
|
+
return tuple;
|
3370
|
+
|
3371
|
+
error:
|
3372
|
+
Py_XDECREF(data);
|
3373
|
+
for (i = 0; i < NDT_MAX_DIM; i++) {
|
3374
|
+
Py_XDECREF(acc[i]);
|
3375
|
+
}
|
3376
|
+
return NULL;
|
3377
|
+
}
|
3378
|
+
|
3379
|
+
|
3380
|
+
/**********************************************************************/
|
3381
|
+
/* Construct fixed or var dimensions from a list of shape lists */
|
3382
|
+
/**********************************************************************/
|
3383
|
+
|
3384
|
+
static bool
|
3385
|
+
require_var(PyObject *lst)
|
3386
|
+
{
|
3387
|
+
PyObject *shapes;
|
3388
|
+
PyObject *v, *w;
|
3389
|
+
Py_ssize_t len;
|
3390
|
+
Py_ssize_t i, k;
|
3391
|
+
|
3392
|
+
assert(PyList_Check(lst));
|
3393
|
+
|
3394
|
+
for (i = 0; i < PyList_GET_SIZE(lst); i++) {
|
3395
|
+
shapes = PyList_GET_ITEM(lst, i);
|
3396
|
+
assert(PyList_Check(shapes));
|
3397
|
+
|
3398
|
+
len = PyList_GET_SIZE(shapes);
|
3399
|
+
if (len == 0) {
|
3400
|
+
continue;
|
3401
|
+
}
|
3402
|
+
|
3403
|
+
v = PyList_GET_ITEM(shapes, 0);
|
3404
|
+
if (v == Py_None) {
|
3405
|
+
return true;
|
3406
|
+
}
|
3407
|
+
assert(PyLong_Check(v));
|
3408
|
+
|
3409
|
+
for (k = 1; k < PyList_GET_SIZE(shapes); k++) {
|
3410
|
+
w = PyList_GET_ITEM(shapes, k);
|
3411
|
+
if (w == Py_None) {
|
3412
|
+
return true;
|
3413
|
+
}
|
3414
|
+
assert(PyLong_Check(w));
|
3415
|
+
|
3416
|
+
if (long_compare((PyLongObject *)v, (PyLongObject *)w) != 0) {
|
3417
|
+
return true;
|
3418
|
+
}
|
3419
|
+
}
|
3420
|
+
}
|
3421
|
+
|
3422
|
+
return false;
|
3423
|
+
}
|
3424
|
+
|
3425
|
+
static const ndt_t *
|
3426
|
+
fixed_from_shapes(PyObject *lst, const ndt_t *type)
|
3427
|
+
{
|
3428
|
+
NDT_STATIC_CONTEXT(ctx);
|
3429
|
+
PyObject *shapes;
|
3430
|
+
PyObject *v;
|
3431
|
+
Py_ssize_t len;
|
3432
|
+
Py_ssize_t shape;
|
3433
|
+
Py_ssize_t i;
|
3434
|
+
const ndt_t *t;
|
3435
|
+
|
3436
|
+
assert(PyList_Check(lst));
|
3437
|
+
|
3438
|
+
ndt_incref(type);
|
3439
|
+
|
3440
|
+
for (i=0, t=type; i < PyList_GET_SIZE(lst); i++, type=t) {
|
3441
|
+
shapes = PyList_GET_ITEM(lst, i);
|
3442
|
+
assert(PyList_Check(shapes));
|
3443
|
+
|
3444
|
+
len = PyList_GET_SIZE(shapes);
|
3445
|
+
|
3446
|
+
if (len == 0) {
|
3447
|
+
shape = 0;
|
3448
|
+
}
|
3449
|
+
else {
|
3450
|
+
v = PyList_GET_ITEM(shapes, 0);
|
3451
|
+
shape = PyLong_AsSsize_t(v);
|
3452
|
+
if (shape < 0) {
|
3453
|
+
ndt_decref(t);
|
3454
|
+
return NULL;
|
3455
|
+
}
|
3456
|
+
}
|
3457
|
+
|
3458
|
+
t = ndt_fixed_dim(type, shape, INT64_MAX, &ctx);
|
3459
|
+
ndt_decref(type);
|
3460
|
+
if (t == NULL) {
|
3461
|
+
return seterr_ndt(&ctx);
|
3462
|
+
}
|
3463
|
+
}
|
3464
|
+
|
3465
|
+
return t;
|
3466
|
+
}
|
3467
|
+
|
3468
|
+
static const ndt_t *
|
3469
|
+
var_from_shapes(PyObject *lst, const ndt_t *dtype)
|
3470
|
+
{
|
3471
|
+
NDT_STATIC_CONTEXT(ctx);
|
3472
|
+
bool overflow = false;
|
3473
|
+
const ndt_t *t;
|
3474
|
+
ndt_offsets_t *offsets;
|
3475
|
+
int32_t *ptr;
|
3476
|
+
int64_t sum;
|
3477
|
+
Py_ssize_t len, slen;
|
3478
|
+
Py_ssize_t shape;
|
3479
|
+
Py_ssize_t i, k;
|
3480
|
+
bool opt;
|
3481
|
+
|
3482
|
+
assert(PyList_Check(lst));
|
3483
|
+
len = PyList_GET_SIZE(lst);
|
3484
|
+
|
3485
|
+
ndt_incref(dtype);
|
3486
|
+
|
3487
|
+
for (i=0, t=dtype; i < len; i++, dtype=t) {
|
3488
|
+
PyObject *shapes = PyList_GET_ITEM(lst, i);
|
3489
|
+
assert(PyList_Check(shapes));
|
3490
|
+
slen = PyList_GET_SIZE(shapes);
|
3491
|
+
|
3492
|
+
if (slen+1 > INT32_MAX) {
|
3493
|
+
PyErr_SetString(PyExc_ValueError,
|
3494
|
+
"variable dimension is too large");
|
3495
|
+
return NULL;
|
3496
|
+
}
|
3497
|
+
|
3498
|
+
offsets = ndt_offsets_new((int32_t)(slen+1), &ctx);
|
3499
|
+
if (offsets == NULL) {
|
3500
|
+
return seterr_ndt(&ctx);
|
3501
|
+
}
|
3502
|
+
|
3503
|
+
ptr = (int32_t *)offsets->v;
|
3504
|
+
sum = 0;
|
3505
|
+
ptr[0] = 0;
|
3506
|
+
opt = false;
|
3507
|
+
|
3508
|
+
for (k = 0; k < slen; k++) {
|
3509
|
+
PyObject *v = PyList_GET_ITEM(shapes, k);
|
3510
|
+
|
3511
|
+
if (v == Py_None) {
|
3512
|
+
shape = 0;
|
3513
|
+
opt = true;
|
3514
|
+
}
|
3515
|
+
else {
|
3516
|
+
shape = PyLong_AsSsize_t(v);
|
3517
|
+
if (shape < 0) {
|
3518
|
+
ndt_decref_offsets(offsets);
|
3519
|
+
return NULL;
|
3520
|
+
}
|
3521
|
+
}
|
3522
|
+
|
3523
|
+
sum = ADDi64(sum, shape, &overflow);
|
3524
|
+
if (overflow || sum > INT32_MAX) {
|
3525
|
+
PyErr_SetString(PyExc_ValueError,
|
3526
|
+
"variable dimension is too large");
|
3527
|
+
ndt_decref_offsets(offsets);
|
3528
|
+
return NULL;
|
3529
|
+
}
|
3530
|
+
|
3531
|
+
ptr[k+1] = (int32_t)sum;
|
3532
|
+
}
|
3533
|
+
|
3534
|
+
t = ndt_var_dim(dtype, offsets, 0, NULL, opt, &ctx);
|
3535
|
+
|
3536
|
+
ndt_decref(dtype);
|
3537
|
+
ndt_decref_offsets(offsets);
|
3538
|
+
|
3539
|
+
if (t == NULL) {
|
3540
|
+
return seterr_ndt(&ctx);
|
3541
|
+
}
|
3542
|
+
}
|
3543
|
+
|
3544
|
+
return t;
|
3545
|
+
}
|
3546
|
+
|
3547
|
+
|
3548
|
+
/**********************************************************************/
|
3549
|
+
/* Infer the dtype from a flat list of data */
|
3550
|
+
/**********************************************************************/
|
3551
|
+
|
3552
|
+
static const ndt_t *typeof(PyObject *v, bool replace_any, bool shortcut);
|
3553
|
+
|
3554
|
+
|
3555
|
+
#define XND_BOOL 0x0001U
|
3556
|
+
#define XND_FLOAT64 0x0002U
|
3557
|
+
#define XND_COMPLEX128 0x0004U
|
3558
|
+
#define XND_INT64 0x0008U
|
3559
|
+
#define XND_STRING 0x0010U
|
3560
|
+
#define XND_BYTES 0x0020U
|
3561
|
+
#define XND_OTHER 0x0040U
|
3562
|
+
|
3563
|
+
static inline uint32_t
|
3564
|
+
fast_dtypes(bool *opt, const PyObject *data)
|
3565
|
+
{
|
3566
|
+
uint32_t dtypes = 0;
|
3567
|
+
|
3568
|
+
assert(PyList_Check(data));
|
3569
|
+
|
3570
|
+
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(data); i++) {
|
3571
|
+
PyObject *v = PyList_GET_ITEM(data, i);
|
3572
|
+
|
3573
|
+
if (v == Py_None) {
|
3574
|
+
*opt = true;
|
3575
|
+
}
|
3576
|
+
else if (PyBool_Check(v)) {
|
3577
|
+
dtypes |= XND_BOOL;
|
3578
|
+
}
|
3579
|
+
else if (PyFloat_Check(v)) {
|
3580
|
+
dtypes |= XND_FLOAT64;
|
3581
|
+
}
|
3582
|
+
else if (PyComplex_Check(v)) {
|
3583
|
+
dtypes |= XND_COMPLEX128;
|
3584
|
+
}
|
3585
|
+
else if (PyLong_Check(v)) {
|
3586
|
+
dtypes |= XND_INT64;
|
3587
|
+
}
|
3588
|
+
else if (PyUnicode_Check(v)) {
|
3589
|
+
dtypes |= XND_STRING;
|
3590
|
+
}
|
3591
|
+
else if (PyBytes_Check(v)) {
|
3592
|
+
dtypes |= XND_BYTES;
|
3593
|
+
}
|
3594
|
+
else {
|
3595
|
+
dtypes |= XND_OTHER;
|
3596
|
+
}
|
3597
|
+
}
|
3598
|
+
|
3599
|
+
if (dtypes == 0) {
|
3600
|
+
dtypes |= XND_FLOAT64;
|
3601
|
+
}
|
3602
|
+
|
3603
|
+
return dtypes;
|
3604
|
+
}
|
3605
|
+
|
3606
|
+
static const ndt_t *
|
3607
|
+
unify_dtypes(const PyObject *data, bool shortcut)
|
3608
|
+
{
|
3609
|
+
NDT_STATIC_CONTEXT(ctx);
|
3610
|
+
PyObject *v;
|
3611
|
+
const ndt_t *dtype;
|
3612
|
+
const ndt_t *t, *u;
|
3613
|
+
Py_ssize_t i;
|
3614
|
+
|
3615
|
+
if (!PyList_Check(data) || PyList_GET_SIZE(data) == 0) {
|
3616
|
+
PyErr_Format(PyExc_RuntimeError,
|
3617
|
+
"internal error: unify_dtypes expects non-empty list");
|
3618
|
+
return NULL;
|
3619
|
+
}
|
3620
|
+
|
3621
|
+
v = PyList_GET_ITEM(data, 0);
|
3622
|
+
dtype = typeof(v, false, shortcut);
|
3623
|
+
if (dtype == NULL) {
|
3624
|
+
return NULL;
|
3625
|
+
}
|
3626
|
+
|
3627
|
+
for (i = 1; i < PyList_GET_SIZE(data); i++) {
|
3628
|
+
v = PyList_GET_ITEM(data, i);
|
3629
|
+
t = typeof(v, false, shortcut);
|
3630
|
+
if (t == NULL) {
|
3631
|
+
ndt_decref(dtype);
|
3632
|
+
return NULL;
|
3633
|
+
}
|
3634
|
+
|
3635
|
+
if (ndt_equal(t, dtype)) {
|
3636
|
+
ndt_decref(t);
|
3637
|
+
}
|
3638
|
+
else {
|
3639
|
+
u = ndt_unify(t, dtype, &ctx);
|
3640
|
+
ndt_decref(t);
|
3641
|
+
ndt_decref(dtype);
|
3642
|
+
if (u == NULL) {
|
3643
|
+
return seterr_ndt(&ctx);
|
3644
|
+
}
|
3645
|
+
dtype = u;
|
3646
|
+
}
|
3647
|
+
|
3648
|
+
if (shortcut && ndt_is_concrete(dtype)) {
|
3649
|
+
break;
|
3650
|
+
}
|
3651
|
+
}
|
3652
|
+
|
3653
|
+
if (ndt_is_abstract(dtype)) {
|
3654
|
+
const ndt_t *u = ndt_unify_replace_any(dtype, dtype, &ctx);
|
3655
|
+
ndt_decref(dtype);
|
3656
|
+
if (u == NULL) {
|
3657
|
+
return seterr_ndt(&ctx);
|
3658
|
+
}
|
3659
|
+
dtype = u;
|
3660
|
+
}
|
3661
|
+
|
3662
|
+
return dtype;
|
3663
|
+
}
|
3664
|
+
|
3665
|
+
const ndt_t *
|
3666
|
+
typeof_data(const PyObject *data, bool shortcut)
|
3667
|
+
{
|
3668
|
+
NDT_STATIC_CONTEXT(ctx);
|
3669
|
+
uint16_opt_t align = {None, 0};
|
3670
|
+
const ndt_t *dtype = NULL;
|
3671
|
+
bool opt = false;
|
3672
|
+
uint32_t dtypes;
|
3673
|
+
|
3674
|
+
dtypes = fast_dtypes(&opt, data);
|
3675
|
+
|
3676
|
+
switch (dtypes) {
|
3677
|
+
case XND_BOOL:
|
3678
|
+
dtype = ndt_primitive(Bool, opt, &ctx);
|
3679
|
+
break;
|
3680
|
+
case XND_FLOAT64:
|
3681
|
+
dtype = ndt_primitive(Float64, opt, &ctx);
|
3682
|
+
break;
|
3683
|
+
case XND_COMPLEX128:
|
3684
|
+
dtype = ndt_primitive(Complex128, opt, &ctx);
|
3685
|
+
break;
|
3686
|
+
case XND_INT64:
|
3687
|
+
dtype = ndt_primitive(Int64, opt, &ctx);
|
3688
|
+
break;
|
3689
|
+
case XND_STRING:
|
3690
|
+
dtype = ndt_string(opt, &ctx);
|
3691
|
+
break;
|
3692
|
+
case XND_BYTES:
|
3693
|
+
dtype = ndt_bytes(align, opt, &ctx);
|
3694
|
+
break;
|
3695
|
+
default:
|
3696
|
+
dtype = unify_dtypes(data, shortcut);
|
3697
|
+
if (dtype == NULL) {
|
3698
|
+
return NULL;
|
3699
|
+
}
|
3700
|
+
break;
|
3701
|
+
}
|
3702
|
+
|
3703
|
+
if (dtype == NULL) {
|
3704
|
+
return seterr_ndt(&ctx);
|
3705
|
+
}
|
3706
|
+
|
3707
|
+
return dtype;
|
3708
|
+
}
|
3709
|
+
|
3710
|
+
|
3711
|
+
/**********************************************************************/
|
3712
|
+
/* Main type inference */
|
3713
|
+
/**********************************************************************/
|
3714
|
+
|
3715
|
+
static const ndt_t *
|
3716
|
+
typeof_list_top(PyObject *v, const ndt_t *dtype)
|
3717
|
+
{
|
3718
|
+
PyObject *tuple;
|
3719
|
+
PyObject *shapes;
|
3720
|
+
const ndt_t *t;
|
3721
|
+
|
3722
|
+
assert(PyList_Check(v));
|
3723
|
+
|
3724
|
+
tuple = data_shapes(NULL, v);
|
3725
|
+
if (tuple == NULL) {
|
3726
|
+
return NULL;
|
3727
|
+
}
|
3728
|
+
shapes = PyTuple_GET_ITEM(tuple, 1);
|
3729
|
+
|
3730
|
+
if (require_var(shapes)) {
|
3731
|
+
t = var_from_shapes(shapes, dtype);
|
3732
|
+
}
|
3733
|
+
else {
|
3734
|
+
t = fixed_from_shapes(shapes, dtype);
|
3735
|
+
}
|
3736
|
+
|
3737
|
+
Py_DECREF(tuple);
|
3738
|
+
return t;
|
3739
|
+
}
|
3740
|
+
|
3741
|
+
static const ndt_t *
|
3742
|
+
typeof_list(PyObject *v, bool shortcut)
|
3743
|
+
{
|
3744
|
+
PyObject *tuple;
|
3745
|
+
PyObject *data;
|
3746
|
+
PyObject *shapes;
|
3747
|
+
const ndt_t *t, *dtype;
|
3748
|
+
|
3749
|
+
assert(PyList_Check(v));
|
3750
|
+
|
3751
|
+
tuple = data_shapes(NULL, v);
|
3752
|
+
if (tuple == NULL) {
|
3753
|
+
return NULL;
|
3754
|
+
}
|
3755
|
+
data = PyTuple_GET_ITEM(tuple, 0);
|
3756
|
+
shapes = PyTuple_GET_ITEM(tuple, 1);
|
3757
|
+
|
3758
|
+
dtype = typeof_data(data, shortcut);
|
3759
|
+
if (dtype == NULL) {
|
3760
|
+
Py_DECREF(tuple);
|
3761
|
+
return NULL;
|
3762
|
+
}
|
3763
|
+
|
3764
|
+
if (require_var(shapes)) {
|
3765
|
+
t = var_from_shapes(shapes, dtype);
|
3766
|
+
}
|
3767
|
+
else {
|
3768
|
+
t = fixed_from_shapes(shapes, dtype);
|
3769
|
+
}
|
3770
|
+
|
3771
|
+
ndt_decref(dtype);
|
3772
|
+
Py_DECREF(tuple);
|
3773
|
+
return t;
|
3774
|
+
}
|
3775
|
+
|
3776
|
+
static const ndt_t *
|
3777
|
+
typeof_tuple(PyObject *v, bool replace_any, bool shortcut)
|
3778
|
+
{
|
3779
|
+
NDT_STATIC_CONTEXT(ctx);
|
3780
|
+
uint16_opt_t none = {None, 0};
|
3781
|
+
ndt_field_t *fields;
|
3782
|
+
const ndt_t *t;
|
3783
|
+
int64_t shape;
|
3784
|
+
int64_t i;
|
3785
|
+
|
3786
|
+
assert(PyTuple_Check(v));
|
3787
|
+
|
3788
|
+
shape = PyTuple_GET_SIZE(v);
|
3789
|
+
if (shape == 0) {
|
3790
|
+
t = ndt_tuple(Nonvariadic, NULL, 0, none, none, false, &ctx);
|
3791
|
+
return t == NULL ? seterr_ndt(&ctx) : t;
|
3792
|
+
}
|
3793
|
+
|
3794
|
+
fields = ndt_calloc(shape, sizeof *fields);
|
3795
|
+
if (fields == NULL) {
|
3796
|
+
PyErr_NoMemory();
|
3797
|
+
return NULL;
|
3798
|
+
}
|
3799
|
+
|
3800
|
+
for (i = 0; i < shape; i++) {
|
3801
|
+
t = typeof(PyTuple_GET_ITEM(v, i), replace_any, shortcut);
|
3802
|
+
if (t == NULL) {
|
3803
|
+
ndt_field_array_del(fields, i);
|
3804
|
+
return NULL;
|
3805
|
+
}
|
3806
|
+
|
3807
|
+
fields[i].access = t->access;
|
3808
|
+
fields[i].name = NULL;
|
3809
|
+
fields[i].type = t;
|
3810
|
+
if (fields[i].access == Concrete) {
|
3811
|
+
fields[i].Concrete.align = t->align;
|
3812
|
+
fields[i].Concrete.explicit_align = false;
|
3813
|
+
fields[i].Concrete.pad = UINT16_MAX;
|
3814
|
+
fields[i].Concrete.explicit_pad = false;
|
3815
|
+
}
|
3816
|
+
}
|
3817
|
+
|
3818
|
+
t = ndt_tuple(Nonvariadic, fields, shape, none, none, false, &ctx);
|
3819
|
+
ndt_field_array_del(fields, shape);
|
3820
|
+
return t == NULL ? seterr_ndt(&ctx) : t;
|
3821
|
+
}
|
3822
|
+
|
3823
|
+
static const ndt_t *
|
3824
|
+
typeof_dict(PyObject *v, bool replace_any, bool shortcut)
|
3825
|
+
{
|
3826
|
+
NDT_STATIC_CONTEXT(ctx);
|
3827
|
+
uint16_opt_t none = {None, 0};
|
3828
|
+
PyObject *keys = NULL;
|
3829
|
+
PyObject *values = NULL;
|
3830
|
+
ndt_field_t *fields;
|
3831
|
+
const ndt_t *t;
|
3832
|
+
const char *cp;
|
3833
|
+
char *name;
|
3834
|
+
int64_t shape;
|
3835
|
+
int64_t i;
|
3836
|
+
|
3837
|
+
assert(PyDict_Check(v));
|
3838
|
+
|
3839
|
+
shape = PyMapping_Size(v);
|
3840
|
+
if (shape == 0) {
|
3841
|
+
t = ndt_record(Nonvariadic, NULL, 0, none, none, false, &ctx);
|
3842
|
+
return t == NULL ? seterr_ndt(&ctx) : t;
|
3843
|
+
}
|
3844
|
+
|
3845
|
+
keys = PyMapping_Keys(v);
|
3846
|
+
if (keys == NULL) {
|
3847
|
+
return NULL;
|
3848
|
+
}
|
3849
|
+
|
3850
|
+
values = PyMapping_Values(v);
|
3851
|
+
if (values == NULL) {
|
3852
|
+
Py_DECREF(keys);
|
3853
|
+
return NULL;
|
3854
|
+
}
|
3855
|
+
|
3856
|
+
fields = ndt_calloc(shape, sizeof *fields);
|
3857
|
+
if (fields == NULL) {
|
3858
|
+
Py_DECREF(keys);
|
3859
|
+
Py_DECREF(values);
|
3860
|
+
PyErr_NoMemory();
|
3861
|
+
return NULL;
|
3862
|
+
}
|
3863
|
+
|
3864
|
+
for (i = 0; i < shape; i++) {
|
3865
|
+
t = typeof(PyList_GET_ITEM(values, i), replace_any, shortcut);
|
3866
|
+
if (t == NULL) {
|
3867
|
+
ndt_field_array_del(fields, i);
|
3868
|
+
Py_DECREF(keys);
|
3869
|
+
Py_DECREF(values);
|
3870
|
+
return NULL;
|
3871
|
+
}
|
3872
|
+
|
3873
|
+
cp = PyUnicode_AsUTF8(PyList_GET_ITEM(keys, i));
|
3874
|
+
if (cp == NULL) {
|
3875
|
+
ndt_field_array_del(fields, i);
|
3876
|
+
ndt_decref(t);
|
3877
|
+
Py_DECREF(keys);
|
3878
|
+
Py_DECREF(values);
|
3879
|
+
return NULL;
|
3880
|
+
}
|
3881
|
+
|
3882
|
+
name = ndt_strdup(cp, &ctx);
|
3883
|
+
if (name == NULL) {
|
3884
|
+
ndt_field_array_del(fields, i);
|
3885
|
+
ndt_decref(t);
|
3886
|
+
Py_DECREF(keys);
|
3887
|
+
Py_DECREF(values);
|
3888
|
+
return seterr_ndt(&ctx);
|
3889
|
+
}
|
3890
|
+
|
3891
|
+
fields[i].access = t->access;
|
3892
|
+
fields[i].name = name;
|
3893
|
+
fields[i].type = t;
|
3894
|
+
if (fields[i].access == Concrete) {
|
3895
|
+
fields[i].Concrete.align = t->align;
|
3896
|
+
fields[i].Concrete.explicit_align = false;
|
3897
|
+
fields[i].Concrete.pad = UINT16_MAX;
|
3898
|
+
fields[i].Concrete.explicit_pad = false;
|
3899
|
+
}
|
3900
|
+
}
|
3901
|
+
|
3902
|
+
Py_DECREF(keys);
|
3903
|
+
Py_DECREF(values);
|
3904
|
+
|
3905
|
+
t = ndt_record(Nonvariadic, fields, shape, none, none, false, &ctx);
|
3906
|
+
ndt_field_array_del(fields, shape);
|
3907
|
+
return t == NULL ? seterr_ndt(&ctx) : t;
|
3908
|
+
}
|
3909
|
+
|
3910
|
+
static const ndt_t *
|
3911
|
+
typeof(PyObject *v, bool replace_any, bool shortcut)
|
3912
|
+
{
|
3913
|
+
NDT_STATIC_CONTEXT(ctx);
|
3914
|
+
const ndt_t *t;
|
3915
|
+
|
3916
|
+
if (PyList_Check(v)) {
|
3917
|
+
return typeof_list(v, shortcut);
|
3918
|
+
}
|
3919
|
+
if (PyTuple_Check(v)) {
|
3920
|
+
return typeof_tuple(v, replace_any, shortcut);
|
3921
|
+
}
|
3922
|
+
if (PyDict_Check(v)) {
|
3923
|
+
return typeof_dict(v, replace_any, shortcut);
|
3924
|
+
}
|
3925
|
+
|
3926
|
+
if (PyBool_Check(v)) {
|
3927
|
+
t = ndt_primitive(Bool, 0, &ctx);
|
3928
|
+
}
|
3929
|
+
else if (PyFloat_Check(v)) {
|
3930
|
+
t = ndt_primitive(Float64, 0, &ctx);
|
3931
|
+
}
|
3932
|
+
else if (PyComplex_Check(v)) {
|
3933
|
+
t = ndt_primitive(Complex128, 0, &ctx);
|
3934
|
+
}
|
3935
|
+
else if (PyLong_Check(v)) {
|
3936
|
+
t = ndt_primitive(Int64, 0, &ctx);
|
3937
|
+
}
|
3938
|
+
else if (PyUnicode_Check(v)) {
|
3939
|
+
t = ndt_string(false, &ctx);
|
3940
|
+
}
|
3941
|
+
else if (PyBytes_Check(v)) {
|
3942
|
+
uint16_opt_t align = {None, 0};
|
3943
|
+
t = ndt_bytes(align, false, &ctx);
|
3944
|
+
}
|
3945
|
+
else if (v == Py_None) {
|
3946
|
+
if (replace_any) {
|
3947
|
+
t = ndt_primitive(Float64, NDT_OPTION, &ctx);
|
3948
|
+
}
|
3949
|
+
else {
|
3950
|
+
t = ndt_any_kind(true, &ctx);
|
3951
|
+
}
|
3952
|
+
}
|
3953
|
+
else {
|
3954
|
+
PyErr_SetString(PyExc_ValueError, "type inference failed");
|
3955
|
+
return NULL;
|
3956
|
+
}
|
3957
|
+
|
3958
|
+
return t == NULL ? seterr_ndt(&ctx) : t;
|
3959
|
+
}
|
3960
|
+
|
3961
|
+
static PyObject *
|
3962
|
+
xnd_typeof(PyObject *m UNUSED, PyObject *args, PyObject *kwds)
|
3963
|
+
{
|
3964
|
+
static char *kwlist[] = {"value", "dtype", "shortcut", NULL};
|
3965
|
+
PyObject *value = NULL;
|
3966
|
+
PyObject *dtype = Py_None;
|
3967
|
+
PyObject *ret;
|
3968
|
+
const ndt_t *t;
|
3969
|
+
int shortcut = 0;
|
3970
|
+
|
3971
|
+
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|Op", kwlist, &value,
|
3972
|
+
&dtype, &shortcut)) {
|
3973
|
+
return NULL;
|
3974
|
+
}
|
3975
|
+
|
3976
|
+
if (dtype != Py_None) {
|
3977
|
+
if (!Ndt_Check(dtype)) {
|
3978
|
+
PyErr_Format(PyExc_ValueError, "dtype argument must be ndt");
|
3979
|
+
return NULL;
|
3980
|
+
}
|
3981
|
+
|
3982
|
+
if (PyList_Check(value)) {
|
3983
|
+
t = typeof_list_top(value, NDT(dtype));
|
3984
|
+
}
|
3985
|
+
else {
|
3986
|
+
t = NDT(dtype);
|
3987
|
+
ndt_incref(t);
|
3988
|
+
}
|
3989
|
+
}
|
3990
|
+
else {
|
3991
|
+
t = typeof(value, true, (bool)shortcut);
|
3992
|
+
}
|
3993
|
+
|
3994
|
+
if (t == NULL) {
|
3995
|
+
return NULL;
|
3996
|
+
}
|
3997
|
+
|
3998
|
+
ret = Ndt_FromType(t);
|
3999
|
+
|
4000
|
+
ndt_decref(t);
|
4001
|
+
return ret;
|
4002
|
+
}
|
4003
|
+
|
4004
|
+
|
4005
|
+
/****************************************************************************/
|
4006
|
+
/* C-API */
|
4007
|
+
/****************************************************************************/
|
4008
|
+
|
4009
|
+
static void **xnd_api[XND_MAX_API];
|
4010
|
+
|
4011
|
+
static int
|
4012
|
+
Xnd_CheckExact(const PyObject *v)
|
4013
|
+
{
|
4014
|
+
return Py_TYPE(v) == &Xnd_Type;
|
4015
|
+
}
|
4016
|
+
|
4017
|
+
static int
|
4018
|
+
Xnd_Check(const PyObject *v)
|
4019
|
+
{
|
4020
|
+
return PyObject_TypeCheck(v, &Xnd_Type);
|
4021
|
+
}
|
4022
|
+
|
4023
|
+
static const xnd_t *
|
4024
|
+
CONST_XND(const PyObject *v)
|
4025
|
+
{
|
4026
|
+
assert(Xnd_Check(v));
|
4027
|
+
return &((XndObject *)v)->xnd;
|
4028
|
+
}
|
4029
|
+
|
4030
|
+
static PyObject *
|
4031
|
+
Xnd_EmptyFromType(PyTypeObject *tp, const ndt_t *t, uint32_t flags)
|
2484
4032
|
{
|
2485
4033
|
MemoryBlockObject *mblock;
|
2486
4034
|
PyObject *type;
|
@@ -2490,7 +4038,7 @@ Xnd_EmptyFromType(PyTypeObject *tp, ndt_t *t)
|
|
2490
4038
|
return NULL;
|
2491
4039
|
}
|
2492
4040
|
|
2493
|
-
mblock = mblock_empty(type);
|
4041
|
+
mblock = mblock_empty(type, flags);
|
2494
4042
|
Py_DECREF(type);
|
2495
4043
|
if (mblock == NULL) {
|
2496
4044
|
return NULL;
|
@@ -2508,14 +4056,15 @@ Xnd_ViewMoveNdt(const PyObject *v, ndt_t *t)
|
|
2508
4056
|
|
2509
4057
|
if (!Xnd_Check(v)) {
|
2510
4058
|
PyErr_SetString(PyExc_TypeError, "expected xnd object");
|
2511
|
-
|
4059
|
+
ndt_decref(t);
|
2512
4060
|
return NULL;
|
2513
4061
|
}
|
2514
4062
|
|
2515
|
-
type =
|
4063
|
+
type = Ndt_FromType(t);
|
2516
4064
|
if (type == NULL) {
|
2517
4065
|
return NULL;
|
2518
4066
|
}
|
4067
|
+
ndt_decref(t);
|
2519
4068
|
|
2520
4069
|
view = pyxnd_alloc(Py_TYPE(src));
|
2521
4070
|
if (view == NULL) {
|
@@ -2571,7 +4120,7 @@ Xnd_FromXndMoveType(const PyObject *xnd, xnd_t *x)
|
|
2571
4120
|
if (!Xnd_Check(xnd)) {
|
2572
4121
|
PyErr_SetString(PyExc_TypeError,
|
2573
4122
|
"Xnd_FromXndMoveType() called on non-xnd object");
|
2574
|
-
|
4123
|
+
ndt_decref(x->type);
|
2575
4124
|
return NULL;
|
2576
4125
|
}
|
2577
4126
|
|
@@ -2700,7 +4249,7 @@ _test_view_new(PyObject *module UNUSED, PyObject *args UNUSED)
|
|
2700
4249
|
NDT_STATIC_CONTEXT(ctx);
|
2701
4250
|
xnd_view_t x = xnd_view_error;
|
2702
4251
|
double *d;
|
2703
|
-
ndt_t *t;
|
4252
|
+
const ndt_t *t;
|
2704
4253
|
char *ptr;
|
2705
4254
|
|
2706
4255
|
t = ndt_from_string("3 * float64", &ctx);
|
@@ -2710,7 +4259,7 @@ _test_view_new(PyObject *module UNUSED, PyObject *args UNUSED)
|
|
2710
4259
|
|
2711
4260
|
ptr = ndt_aligned_calloc(8, 3 * sizeof(double));
|
2712
4261
|
if (ptr == NULL) {
|
2713
|
-
|
4262
|
+
ndt_decref(t);
|
2714
4263
|
(void)ndt_memory_error(&ctx);
|
2715
4264
|
return seterr(&ctx);
|
2716
4265
|
}
|
@@ -2736,6 +4285,8 @@ _test_view_new(PyObject *module UNUSED, PyObject *args UNUSED)
|
|
2736
4285
|
|
2737
4286
|
static PyMethodDef _xnd_methods [] =
|
2738
4287
|
{
|
4288
|
+
{ "data_shapes", (PyCFunction)data_shapes, METH_O, NULL},
|
4289
|
+
{ "_typeof", (PyCFunction)xnd_typeof, METH_VARARGS|METH_KEYWORDS, NULL},
|
2739
4290
|
{ "_test_view_subscript", (PyCFunction)_test_view_subscript, METH_VARARGS|METH_KEYWORDS, NULL},
|
2740
4291
|
{ "_test_view_new", (PyCFunction)_test_view_new, METH_NOARGS, NULL},
|
2741
4292
|
{ NULL, NULL, 1, NULL }
|