ndtypes 0.2.0dev5 → 0.2.0dev6

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.
Files changed (130) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +12 -0
  3. data/Rakefile +8 -0
  4. data/ext/ruby_ndtypes/GPATH +0 -0
  5. data/ext/ruby_ndtypes/GRTAGS +0 -0
  6. data/ext/ruby_ndtypes/GTAGS +0 -0
  7. data/ext/ruby_ndtypes/extconf.rb +1 -1
  8. data/ext/ruby_ndtypes/include/ndtypes.h +231 -122
  9. data/ext/ruby_ndtypes/include/ruby_ndtypes.h +1 -1
  10. data/ext/ruby_ndtypes/lib/libndtypes.a +0 -0
  11. data/ext/ruby_ndtypes/lib/libndtypes.so.0.2.0dev3 +0 -0
  12. data/ext/ruby_ndtypes/ndtypes/Makefile +87 -0
  13. data/ext/ruby_ndtypes/ndtypes/config.h +68 -0
  14. data/ext/ruby_ndtypes/ndtypes/config.log +477 -0
  15. data/ext/ruby_ndtypes/ndtypes/config.status +1027 -0
  16. data/ext/ruby_ndtypes/ndtypes/doc/_static/style.css +7 -0
  17. data/ext/ruby_ndtypes/ndtypes/doc/_templates/layout.html +2 -0
  18. data/ext/ruby_ndtypes/ndtypes/doc/conf.py +40 -4
  19. data/ext/ruby_ndtypes/ndtypes/doc/images/xndlogo.png +0 -0
  20. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/types.rst +1 -1
  21. data/ext/ruby_ndtypes/ndtypes/doc/requirements.txt +2 -0
  22. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile +287 -0
  23. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.in +20 -4
  24. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.vc +22 -3
  25. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.c +1 -1
  26. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.o +0 -0
  27. data/ext/ruby_ndtypes/ndtypes/libndtypes/attr.o +0 -0
  28. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/Makefile +73 -0
  29. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.c +246 -229
  30. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.h +15 -11
  31. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.o +0 -0
  32. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.y +38 -28
  33. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.c +91 -91
  34. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.h +1 -1
  35. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.l +4 -3
  36. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.o +0 -0
  37. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.c +8 -7
  38. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.o +0 -0
  39. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.c +2 -2
  40. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.o +0 -0
  41. data/ext/ruby_ndtypes/ndtypes/libndtypes/context.o +0 -0
  42. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.c +263 -182
  43. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.o +0 -0
  44. data/ext/ruby_ndtypes/ndtypes/libndtypes/encodings.o +0 -0
  45. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.c +67 -7
  46. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.o +0 -0
  47. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.c +1112 -1000
  48. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.h +69 -58
  49. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.o +0 -0
  50. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.y +150 -99
  51. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.c +185 -15
  52. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.o +0 -0
  53. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.c +301 -276
  54. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.h +1 -1
  55. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.l +9 -4
  56. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.o +0 -0
  57. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.a +0 -0
  58. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so +1 -0
  59. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0 +1 -0
  60. data/ext/ruby_ndtypes/ndtypes/libndtypes/libndtypes.so.0.2.0dev3 +0 -0
  61. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.c +729 -228
  62. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.o +0 -0
  63. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.c +768 -403
  64. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h +1002 -0
  65. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h.in +231 -122
  66. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.o +0 -0
  67. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.c +176 -84
  68. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.h +26 -14
  69. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.o +0 -0
  70. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.c +57 -35
  71. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.o +0 -0
  72. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.c +420 -0
  73. data/ext/ruby_ndtypes/ndtypes/libndtypes/primitive.o +0 -0
  74. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.c +8 -8
  75. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.h +1 -1
  76. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.o +0 -0
  77. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/Makefile +48 -0
  78. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.c +200 -116
  79. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.o +0 -0
  80. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.c +46 -4
  81. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.o +0 -0
  82. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.c +58 -27
  83. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.h +1 -1
  84. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.o +0 -0
  85. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.c +3 -5
  86. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.h +12 -4
  87. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.o +0 -0
  88. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile +55 -0
  89. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.in +8 -8
  90. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.vc +5 -5
  91. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/runtest.c +274 -172
  92. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test.h +24 -4
  93. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_array.c +2 -2
  94. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_buffer.c +14 -14
  95. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_match.c +32 -30
  96. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse.c +37 -0
  97. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_error.c +36 -0
  98. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_roundtrip.c +16 -0
  99. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_record.c +5 -5
  100. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_typecheck.c +706 -253
  101. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_unify.c +132 -0
  102. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.c +703 -0
  103. data/ext/ruby_ndtypes/ndtypes/libndtypes/unify.o +0 -0
  104. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.c +335 -127
  105. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.o +0 -0
  106. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.c +2 -2
  107. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.o +0 -0
  108. data/ext/ruby_ndtypes/ndtypes/python/ndt_randtype.py +88 -71
  109. data/ext/ruby_ndtypes/ndtypes/python/ndt_support.py +0 -1
  110. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/__init__.py +10 -13
  111. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/_ndtypes.c +395 -314
  112. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.a +0 -0
  113. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so +1 -0
  114. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0 +1 -0
  115. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/libndtypes.so.0.2.0dev3 +0 -0
  116. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/ndtypes.h +1002 -0
  117. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/pyndtypes.h +15 -33
  118. data/ext/ruby_ndtypes/ndtypes/python/test_ndtypes.py +340 -132
  119. data/ext/ruby_ndtypes/ndtypes/setup.py +11 -2
  120. data/ext/ruby_ndtypes/ruby_ndtypes.c +364 -241
  121. data/ext/ruby_ndtypes/ruby_ndtypes.h +1 -1
  122. data/ext/ruby_ndtypes/ruby_ndtypes_internal.h +0 -1
  123. data/lib/ndtypes.rb +11 -0
  124. data/lib/ndtypes/version.rb +2 -2
  125. data/lib/ruby_ndtypes.so +0 -0
  126. data/ndtypes.gemspec +3 -0
  127. data/spec/ndtypes_spec.rb +6 -0
  128. metadata +98 -4
  129. data/ext/ruby_ndtypes/gc_guard.c +0 -36
  130. data/ext/ruby_ndtypes/gc_guard.h +0 -12
@@ -56,7 +56,7 @@ ndt_value_del(ndt_value_t *mem)
56
56
  }
57
57
 
58
58
  void
59
- ndt_value_array_del(ndt_value_t *mem, int64_t ntypes)
59
+ ndt_value_array_del(const ndt_value_t *mem, int64_t ntypes)
60
60
  {
61
61
  int64_t i;
62
62
 
@@ -70,7 +70,7 @@ ndt_value_array_del(ndt_value_t *mem, int64_t ntypes)
70
70
  }
71
71
  }
72
72
 
73
- ndt_free(mem);
73
+ ndt_free((void *)mem);
74
74
  }
75
75
 
76
76
  /* Value sequences */
@@ -335,75 +335,92 @@ def genindices(factor):
335
335
  yield (factor * i, factor * j, factor * k)
336
336
 
337
337
  BROADCAST_TEST_CASES = [
338
- ApplySpec(
339
- flags = 'C|Fortran|Strided|Xnd',
340
- sig = ndt("uint8 -> float64"),
341
- in_types = [ndt("uint8")],
342
- out_types = [ndt("float64")],
343
- in_broadcast = [],
344
- outer_dims = 0),
345
-
346
- ApplySpec(
347
- flags = 'Elemwise1D|C|Fortran|Strided|Xnd',
348
- sig = ndt("... * uint8 -> ... * float64"),
349
- in_types = [ndt("2 * uint8")],
350
- out_types = [ndt("2 * float64")],
351
- in_broadcast = [ndt("2 * uint8")],
352
- outer_dims = 1),
353
-
354
- ApplySpec(
355
- flags = 'C|Fortran|Strided|Xnd',
356
- sig = ndt("F[... * uint8] -> F[... * float64]"),
357
- in_types = [ndt("!2 * 3 * uint8")],
358
- out_types = [ndt("!2 * 3 * float64")],
359
- in_broadcast = [ndt("!2 * 3 * uint8")],
360
- outer_dims = 2),
361
-
362
- ApplySpec(
363
- flags = 'C|Fortran|Strided|Xnd',
364
- sig = ndt("... * uint8 -> ... * float64"),
365
- in_types = [ndt("fixed(shape=2, step=10) * uint8")],
366
- out_types = [ndt("2 * float64")],
367
- in_broadcast = [ndt("fixed(shape=2, step=10) * uint8")],
368
- outer_dims = 1),
369
-
370
- ApplySpec(
371
- flags = 'Strided|Xnd',
372
- sig = ndt("... * N * uint8 -> ... * N * float64"),
373
- in_types = [ndt("fixed(shape=2, step=10) * uint8")],
374
- out_types = [ndt("2 * float64")],
375
- in_broadcast = [ndt("fixed(shape=2, step=10) * uint8")],
376
- outer_dims = 0),
377
-
378
- ApplySpec(
379
- flags = 'C|Fortran|Strided|Xnd',
380
- sig = ndt("... * N * uint8 -> ... * N * float64"),
381
- in_types = [ndt("2 * 3 * uint8")],
382
- out_types = [ndt("2 * 3 * float64")],
383
- in_broadcast = [ndt("2 * 3 * uint8")],
384
- outer_dims = 1),
385
-
386
- ApplySpec(
387
- flags = 'C|Strided|Xnd',
388
- sig = ndt("... * N * M * uint8 -> ... * N * M * float64"),
389
- in_types = [ndt("2 * 3 * uint8")],
390
- out_types = [ndt("2 * 3 * float64")],
391
- in_broadcast = [ndt("2 * 3 * uint8")],
392
- outer_dims = 0),
393
-
394
- ApplySpec(
395
- flags = 'Xnd',
396
- sig = ndt("N * D * float64 -> P * float64"),
397
- in_types = [ndt("2 * 10 * float64")],
398
- out_types = [ndt("P * float64")],
399
- in_broadcast = [],
400
- outer_dims = 0),
401
-
402
- ApplySpec(
403
- flags = 'C|Fortran|Xnd',
404
- sig = ndt("var... * float64 -> var... * float64"),
405
- in_types = [ndt("var(offsets=[0,2]) * var(offsets=[0,4,11]) * float64")],
406
- out_types = [ndt("var(offsets=[0,2]) * var(offsets=[0,4,11]) * float64")],
407
- in_broadcast = [],
408
- outer_dims = 2)
338
+ dict(sig=ndt("uint8 -> float64"),
339
+ args=[ndt("uint8")],
340
+ out=None,
341
+ spec= ApplySpec(
342
+ flags = 'C|Fortran|Strided|Xnd',
343
+ outer_dims = 0,
344
+ nin = 1,
345
+ nout = 1,
346
+ nargs = 2,
347
+ types = [ndt("uint8"), ndt("float64")])),
348
+
349
+ dict(sig=ndt("... * uint8 -> ... * float64"),
350
+ args=[ndt("2 * uint8")],
351
+ out=None,
352
+ spec=ApplySpec(
353
+ flags = 'OptZ|OptC|OptS|C|Fortran|Strided|Xnd',
354
+ outer_dims = 1,
355
+ nin = 1,
356
+ nout = 1,
357
+ nargs = 2,
358
+ types = [ndt("2 * uint8"), ndt("2 * float64")])),
359
+
360
+ dict(sig=ndt("F[... * uint8] -> F[... * float64]"),
361
+ args=[ndt("!2 * 3 * uint8")],
362
+ out=None,
363
+ spec=ApplySpec(
364
+ flags = 'OptS|C|Fortran|Strided|Xnd',
365
+ outer_dims = 2,
366
+ nin = 1,
367
+ nout = 1,
368
+ nargs = 2,
369
+ types = [ndt("!2 * 3 * uint8"), ndt("!2 * 3 * float64")])),
370
+
371
+ dict(sig=ndt("... * uint8 -> ... * float64"),
372
+ args=[ndt("fixed(shape=2, step=10) * uint8")],
373
+ out=None,
374
+ spec=ApplySpec(
375
+ flags = 'OptS|C|Fortran|Strided|Xnd',
376
+ outer_dims = 1,
377
+ nin = 1,
378
+ nout = 1,
379
+ nargs = 2,
380
+ types = [ndt("fixed(shape=2, step=10) * uint8"), ndt("2 * float64")])),
381
+
382
+ dict(sig=ndt("... * N * uint8 -> ... * N * float64"),
383
+ args=[ndt("fixed(shape=2, step=10) * uint8")],
384
+ out=None,
385
+ spec=ApplySpec(
386
+ flags = 'Strided|Xnd',
387
+ outer_dims = 0,
388
+ nin = 1,
389
+ nout = 1,
390
+ nargs = 2,
391
+ types = [ndt("fixed(shape=2, step=10) * uint8"), ndt("2 * float64")])),
392
+
393
+ dict(sig=ndt("... * N * uint8 -> ... * N * float64"),
394
+ args=[ndt("2 * 3 * uint8")],
395
+ out=None,
396
+ spec=ApplySpec(
397
+ flags = 'OptZ|OptC|OptS|C|Fortran|Strided|Xnd' ,
398
+ outer_dims = 1,
399
+ nin = 1,
400
+ nout = 1,
401
+ nargs = 2,
402
+ types = [ndt("2 * 3 * uint8"), ndt("2 * 3 * float64")])),
403
+
404
+ dict(sig=ndt("... * N * M * uint8 -> ... * N * M * float64"),
405
+ args=[ndt("2 * 3 * uint8")],
406
+ out=None,
407
+ spec=ApplySpec(
408
+ flags = 'C|Strided|Xnd',
409
+ outer_dims = 0,
410
+ nin = 1,
411
+ nout = 1,
412
+ nargs = 2,
413
+ types = [ndt("2 * 3 * uint8"), ndt("2 * 3 * float64")])),
414
+
415
+ dict(sig=ndt("var... * float64 -> var... * float64"),
416
+ args=[ndt("var(offsets=[0,2]) * var(offsets=[0,4,11]) * float64")],
417
+ out=None,
418
+ spec=ApplySpec(
419
+ flags = 'Xnd',
420
+ outer_dims = 2,
421
+ nin = 1,
422
+ nout = 1,
423
+ nargs = 2,
424
+ types = [ndt("var(offsets=[0,2]) * var(offsets=[0,4,11]) * float64"),
425
+ ndt("var(offsets=[0,2]) * var(offsets=[0,4,11]) * float64")])),
409
426
  ]
@@ -5,7 +5,6 @@ def skip_if(condition, reason):
5
5
  if condition:
6
6
  raise unittest.SkipTest(reason)
7
7
 
8
- HAVE_PYTHON_36 = sys.version_info >= (3, 6, 0)
9
8
  HAVE_32_BIT_LINUX = sys.maxsize == 2**31-1 and sys.platform == 'linux'
10
9
 
11
10
  requires_py36 = unittest.skipUnless(
@@ -54,17 +54,14 @@ The xnd module uses ndtypes to implement a general container for mapping most
54
54
  Python types relevant for scientific computing directly to memory.
55
55
  """
56
56
 
57
- def _pretty_repr(self):
58
- return """\
59
- ApplySpec(
60
- flags=%r,
61
- sig=%r,
62
- in_types=%r,
63
- in_broadcast=%r,
64
- out_types=%r,
65
- outer_dims=%r
66
- )""" % (self.flags, self.sig, self.in_types, self.in_broadcast, self.out_types, self.outer_dims)
67
-
68
- from . import _ndtypes
69
- _ndtypes.ApplySpec.__repr__ = _pretty_repr
70
57
  from ._ndtypes import *
58
+ from ._ndtypes import _ApplySpec
59
+ from . import _ndtypes
60
+
61
+ class ApplySpec(_ApplySpec):
62
+
63
+ def __repr__(self):
64
+ return "\
65
+ ApplySpec(flags=%r,\n outer_dims=%r\n nin=%r,\n nout=%r,\n nargs=%r,\n types=%r)\
66
+ " % (self.flags, self.outer_dims, self.nin, self.nout, self.nargs, self.types)
67
+
@@ -54,65 +54,70 @@
54
54
 
55
55
 
56
56
  /****************************************************************************/
57
- /* Resource Buffer Object */
57
+ /* Cached objects */
58
58
  /****************************************************************************/
59
59
 
60
- /* This object handles resources like offsets that are shared by several
61
- ndt objects. It is never exposed to the Python level.
62
-
63
- At a later stage, the object will need to communicate with Arrow
64
- or other formats to store external resources. */
65
-
66
- static PyObject *seterr(ndt_context_t *ctx);
60
+ static PyObject *Deserialize = NULL;
61
+ static PyTypeObject *_ApplySpec = NULL;
67
62
 
68
- typedef struct {
69
- PyObject_HEAD
70
- ndt_meta_t *m;
71
- } ResourceBufferObject;
72
63
 
73
- static PyTypeObject ResourceBuffer_Type;
64
+ /****************************************************************************/
65
+ /* Error handling */
66
+ /****************************************************************************/
74
67
 
75
68
  static PyObject *
76
- rbuf_alloc(void)
69
+ seterr(ndt_context_t *ctx)
77
70
  {
78
- NDT_STATIC_CONTEXT(ctx);
79
- ResourceBufferObject *self;
71
+ PyObject *exc = PyExc_RuntimeError;
80
72
 
81
- self = (ResourceBufferObject *)
82
- PyObject_GC_New(ResourceBufferObject, &ResourceBuffer_Type);
83
- if (self == NULL) {
84
- return NULL;
85
- }
86
-
87
- self->m = ndt_meta_new(&ctx);
88
- if (self->m == NULL) {
89
- return seterr(&ctx);
73
+ switch (ctx->err) {
74
+ case NDT_Success: /* should never be set on error */
75
+ exc = PyExc_RuntimeError;
76
+ break;
77
+ case NDT_ValueError:
78
+ exc = PyExc_ValueError;
79
+ break;
80
+ case NDT_TypeError:
81
+ exc = PyExc_TypeError;
82
+ break;
83
+ case NDT_InvalidArgumentError:
84
+ exc = PyExc_ValueError;
85
+ break;
86
+ case NDT_NotImplementedError:
87
+ exc = PyExc_NotImplementedError;
88
+ break;
89
+ case NDT_IndexError:
90
+ exc = PyExc_IndexError;
91
+ break;
92
+ case NDT_LexError: case NDT_ParseError:
93
+ exc = PyExc_ValueError;
94
+ break;
95
+ case NDT_OSError:
96
+ exc = PyExc_OSError;
97
+ break;
98
+ case NDT_RuntimeError:
99
+ exc = PyExc_RuntimeError;
100
+ break;
101
+ case NDT_MemoryError:
102
+ exc = PyExc_MemoryError;
103
+ break;
90
104
  }
91
105
 
92
- PyObject_GC_Track(self);
93
- return (PyObject *)self;
94
- }
106
+ PyErr_SetString(exc, ndt_context_msg(ctx));
107
+ ndt_context_del(ctx);
95
108
 
96
- static int
97
- rbuf_traverse(ResourceBufferObject *self UNUSED, visitproc visit UNUSED,
98
- void *arg UNUSED)
99
- {
100
- return 0;
101
- }
109
+ return NULL;
110
+ };
102
111
 
103
- static void
104
- rbuf_dealloc(ResourceBufferObject *self)
105
- {
106
- ndt_meta_del(self->m);
107
- self->m = NULL;
108
- PyObject_GC_UnTrack(self);
109
- PyObject_GC_Del(self);
110
- }
112
+
113
+ /****************************************************************************/
114
+ /* Get offsets from a list */
115
+ /****************************************************************************/
111
116
 
112
117
  static int
113
- rbuf_init_from_offset_list(ResourceBufferObject *rbuf, PyObject *list)
118
+ offsets_from_list(ndt_meta_t *m, PyObject *list)
114
119
  {
115
- ndt_meta_t * const m = rbuf->m;
120
+ NDT_STATIC_CONTEXT(ctx);
116
121
  PyObject *lst;
117
122
 
118
123
  if (!PyList_Check(list)) {
@@ -166,99 +171,17 @@ rbuf_init_from_offset_list(ResourceBufferObject *rbuf, PyObject *list)
166
171
  offsets[k] = (int32_t)x;
167
172
  }
168
173
 
169
- m->noffsets[m->ndims] = (int32_t)noffsets;
170
- m->offsets[m->ndims] = offsets;
174
+ m->offsets[m->ndims] = ndt_offsets_from_ptr(offsets, (int32_t)noffsets, &ctx);
175
+ if (m->offsets[m->ndims] == NULL) {
176
+ (void)seterr(&ctx);
177
+ return -1;
178
+ }
171
179
  m->ndims++;
172
180
  }
173
181
 
174
182
  return 0;
175
183
  }
176
184
 
177
- static PyObject *
178
- rbuf_from_offset_lists(PyObject *list)
179
- {
180
- PyObject *rbuf;
181
-
182
- rbuf = rbuf_alloc();
183
- if (rbuf == NULL) {
184
- return NULL;
185
- }
186
-
187
- if (rbuf_init_from_offset_list((ResourceBufferObject *)rbuf, list) < 0) {
188
- Py_DECREF(rbuf);
189
- return NULL;
190
- }
191
-
192
- return rbuf;
193
- }
194
-
195
- static PyTypeObject ResourceBuffer_Type = {
196
- PyVarObject_HEAD_INIT(NULL, 0)
197
- .tp_name = "_ndtypes.resource",
198
- .tp_basicsize = sizeof(ResourceBufferObject),
199
- .tp_dealloc = (destructor)rbuf_dealloc,
200
- .tp_getattro = PyObject_GenericGetAttr,
201
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
202
- .tp_traverse = (traverseproc)rbuf_traverse
203
- };
204
-
205
-
206
- /****************************************************************************/
207
- /* Cached objects */
208
- /****************************************************************************/
209
-
210
- static PyObject *Deserialize = NULL;
211
- static PyTypeObject *ApplySpec = NULL;
212
-
213
-
214
- /****************************************************************************/
215
- /* Error handling */
216
- /****************************************************************************/
217
-
218
- static PyObject *
219
- seterr(ndt_context_t *ctx)
220
- {
221
- PyObject *exc = PyExc_RuntimeError;
222
-
223
- switch (ctx->err) {
224
- case NDT_Success: /* should never be set on error */
225
- exc = PyExc_RuntimeError;
226
- break;
227
- case NDT_ValueError:
228
- exc = PyExc_ValueError;
229
- break;
230
- case NDT_TypeError:
231
- exc = PyExc_TypeError;
232
- break;
233
- case NDT_InvalidArgumentError:
234
- exc = PyExc_ValueError;
235
- break;
236
- case NDT_NotImplementedError:
237
- exc = PyExc_NotImplementedError;
238
- break;
239
- case NDT_IndexError:
240
- exc = PyExc_IndexError;
241
- break;
242
- case NDT_LexError: case NDT_ParseError:
243
- exc = PyExc_ValueError;
244
- break;
245
- case NDT_OSError:
246
- exc = PyExc_OSError;
247
- break;
248
- case NDT_RuntimeError:
249
- exc = PyExc_RuntimeError;
250
- break;
251
- case NDT_MemoryError:
252
- exc = PyExc_MemoryError;
253
- break;
254
- }
255
-
256
- PyErr_SetString(exc, ndt_context_msg(ctx));
257
- ndt_context_del(ctx);
258
-
259
- return NULL;
260
- };
261
-
262
185
 
263
186
  /****************************************************************************/
264
187
  /* ndt object */
@@ -275,29 +198,40 @@ ndtype_alloc(PyTypeObject *type)
275
198
  if (self == NULL) {
276
199
  return NULL;
277
200
  }
278
-
279
- RBUF(self) = NULL;
201
+ self->hash = -1;
280
202
  NDT(self) = NULL;
281
203
 
282
204
  return (PyObject *)self;
283
205
  }
284
206
 
285
- static int
286
- ndtype_traverse(NdtObject *self, visitproc visit, void *arg)
287
- {
288
- Py_VISIT(self->rbuf);
289
- return 0;
290
- }
291
-
292
207
  static void
293
208
  ndtype_dealloc(NdtObject *self)
294
209
  {
295
- PyObject_GC_UnTrack(self);
296
- ndt_del(NDT(self));
297
- Py_CLEAR(self->rbuf);
210
+ ndt_decref(NDT(self));
298
211
  Py_TYPE(self)->tp_free(self);
299
212
  }
300
213
 
214
+ static const ndt_t *
215
+ from_string(PyObject *v)
216
+ {
217
+ NDT_STATIC_CONTEXT(ctx);
218
+ const char *cp;
219
+ const ndt_t *t;
220
+
221
+ cp = PyUnicode_AsUTF8(v);
222
+ if (cp == NULL) {
223
+ return NULL;
224
+ }
225
+
226
+ t = ndt_from_string(cp, &ctx);
227
+ if (t == NULL) {
228
+ (void)seterr(&ctx);
229
+ return NULL;
230
+ }
231
+
232
+ return t;
233
+ }
234
+
301
235
  static PyObject *
302
236
  ndtype_from_object(PyTypeObject *tp, PyObject *type)
303
237
  {
@@ -320,13 +254,7 @@ ndtype_from_object(PyTypeObject *tp, PyObject *type)
320
254
  return NULL;
321
255
  }
322
256
 
323
- RBUF(self) = rbuf_alloc();
324
- if (RBUF(self) == NULL) {
325
- Py_DECREF(self);
326
- return NULL;
327
- }
328
-
329
- NDT(self) = ndt_from_string_fill_meta(RBUF_NDT_META(self), cp, &ctx);
257
+ NDT(self) = ndt_from_string(cp, &ctx);
330
258
  if (NDT(self) == NULL) {
331
259
  Py_DECREF(self);
332
260
  return seterr(&ctx);
@@ -383,6 +311,7 @@ static PyObject *
383
311
  ndtype_from_offsets_and_dtype(PyTypeObject *tp, PyObject *offsets, PyObject *dtype)
384
312
  {
385
313
  NDT_STATIC_CONTEXT(ctx);
314
+ ndt_meta_t m = {.ndims = 0, .offsets = {NULL}};
386
315
  PyObject *self;
387
316
  const char *cp;
388
317
 
@@ -396,14 +325,43 @@ ndtype_from_offsets_and_dtype(PyTypeObject *tp, PyObject *offsets, PyObject *dty
396
325
  return NULL;
397
326
  }
398
327
 
399
- RBUF(self) = rbuf_from_offset_lists(offsets);
400
- if (RBUF(self) == NULL) {
328
+ if (offsets_from_list(&m, offsets) < 0) {
329
+ ndt_meta_clear(&m);
401
330
  Py_DECREF(self);
402
331
  return NULL;
403
332
  }
404
333
 
405
- NDT(self) = ndt_from_metadata_and_dtype(RBUF_NDT_META(self), cp, &ctx);
334
+ NDT(self) = ndt_from_metadata_and_dtype(&m, cp, &ctx);
335
+ ndt_meta_clear(&m);
336
+ if (NDT(self) == NULL) {
337
+ Py_DECREF(self);
338
+ return seterr(&ctx);
339
+ }
340
+
341
+ return self;
342
+ }
343
+
344
+ static PyObject *
345
+ ndtype_from_offsets_opt_and_dtype(PyTypeObject *tp, PyObject *offsets, bool *opt,
346
+ const ndt_t *dtype)
347
+ {
348
+ NDT_STATIC_CONTEXT(ctx);
349
+ ndt_meta_t m = {.ndims = 0, .offsets = {NULL}};
350
+ PyObject *self;
351
+
352
+ self = ndtype_alloc(tp);
353
+ if (self == NULL) {
354
+ return NULL;
355
+ }
406
356
 
357
+ if (offsets_from_list(&m, offsets) < 0) {
358
+ ndt_meta_clear(&m);
359
+ Py_DECREF(self);
360
+ return NULL;
361
+ }
362
+
363
+ NDT(self) = ndt_from_metadata_opt_and_dtype(&m, opt, dtype, &ctx);
364
+ ndt_meta_clear(&m);
407
365
  if (NDT(self) == NULL) {
408
366
  Py_DECREF(self);
409
367
  return seterr(&ctx);
@@ -428,13 +386,7 @@ ndtype_deserialize(PyTypeObject *tp, PyObject *bytes)
428
386
  return NULL;
429
387
  }
430
388
 
431
- RBUF(self) = rbuf_alloc();
432
- if (RBUF(self) == NULL) {
433
- Py_DECREF(self);
434
- return NULL;
435
- }
436
-
437
- NDT(self) = ndt_deserialize(RBUF_NDT_META(self), PyBytes_AS_STRING(bytes),
389
+ NDT(self) = ndt_deserialize(PyBytes_AS_STRING(bytes),
438
390
  PyBytes_GET_SIZE(bytes), &ctx);
439
391
  if (NDT(self) == NULL) {
440
392
  Py_DECREF(self);
@@ -601,6 +553,7 @@ Ndtype_BoolFunc(ndt_is_complex)
601
553
 
602
554
  Ndtype_BoolFunc(ndt_is_c_contiguous)
603
555
  Ndtype_BoolFunc(ndt_is_f_contiguous)
556
+ Ndtype_BoolFunc(ndt_is_var_contiguous)
604
557
 
605
558
 
606
559
  static PyObject *
@@ -628,13 +581,62 @@ static Py_hash_t
628
581
  ndtype_hash(PyObject *self)
629
582
  {
630
583
  NDT_STATIC_CONTEXT(ctx);
631
- Py_hash_t res;
584
+ NdtObject *s = (NdtObject *)self;
632
585
 
633
- res = ndt_hash(NDT(self), &ctx);
634
- if (res == -1) {
635
- (void)seterr(&ctx);
586
+ if (s->hash == -1) {
587
+ s->hash = ndt_hash(NDT(self), &ctx);
588
+ if (s->hash == -1) {
589
+ (void)seterr(&ctx);
590
+ }
591
+ }
592
+
593
+ return s->hash;
594
+ }
595
+
596
+ static PyObject *
597
+ ndtype_at(PyObject *self, PyObject *args, PyObject *kwds)
598
+ {
599
+ static char *kwlist[] = {"n", "dtype", NULL};
600
+ NDT_STATIC_CONTEXT(ctx);
601
+ PyObject *dtype = Py_None;
602
+ int n = 0;
603
+ PyObject *res;
604
+ const ndt_t *t;
605
+ const ndt_t *dt;
606
+
607
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "i|O", kwlist, &n, &dtype)) {
608
+ return NULL;
609
+ }
610
+
611
+ if (dtype == Py_None) {
612
+ dt = NULL;
613
+ }
614
+ else if (Ndt_Check(dtype)) {
615
+ dt = NDT(dtype);
616
+ ndt_incref(dt);
617
+ }
618
+ else if (PyUnicode_Check(dtype)) {
619
+ dt = from_string(dtype);
620
+ if (dt == NULL) {
621
+ return NULL;
622
+ }
623
+ }
624
+ else {
625
+ PyErr_SetString(PyExc_TypeError,
626
+ "dtype argument must be 'ndt' or 'str'");
627
+ return NULL;
628
+ }
629
+
630
+ t = ndt_copy_contiguous_at(NDT(self), n, dt, &ctx);
631
+ if (dt != NULL) {
632
+ ndt_decref(dt);
633
+ }
634
+ if (t == NULL) {
635
+ return seterr(&ctx);
636
636
  }
637
637
 
638
+ res = Ndt_FromType(t);
639
+ ndt_decref(t);
638
640
  return res;
639
641
  }
640
642
 
@@ -658,40 +660,178 @@ ndtype_match(PyObject *self, PyObject *other)
658
660
  }
659
661
 
660
662
  static PyObject *
661
- ndtype_apply(PyObject *self, PyObject *args)
663
+ ndtype_unify(PyObject *self, PyObject *other)
662
664
  {
663
665
  NDT_STATIC_CONTEXT(ctx);
664
- ndt_t *sig = NDT(self);
665
- const ndt_t *in[NDT_MAX_ARGS];
666
- ndt_apply_spec_t spec;
667
- PyObject *flags = NULL, *out = NULL, *broadcast = NULL, *outer_dims = NULL;
668
- PyObject *res = NULL;
669
- Py_ssize_t nin;
670
- Py_ssize_t i;
666
+ PyObject *u;
667
+ const ndt_t *t;
671
668
 
672
- if (!PyTuple_Check(args) && !PyList_Check(args)) {
673
- PyErr_SetString(PyExc_TypeError, "arguments must be a tuple or a list");
669
+ if (!Ndt_Check(other)) {
670
+ PyErr_SetString(PyExc_TypeError, "argument must be 'ndt'");
674
671
  return NULL;
675
672
  }
676
673
 
677
- nin = PySequence_Fast_GET_SIZE(args);
678
- if (nin > NDT_MAX_ARGS) {
679
- PyErr_Format(PyExc_ValueError,
680
- "maximum number of arguments is %d", NDT_MAX_ARGS);
674
+ t = ndt_unify(NDT(self), NDT(other), &ctx);
675
+ if (t == NULL) {
676
+ return seterr(&ctx);
677
+ }
678
+
679
+ u = Ndt_FromType(t);
680
+ ndt_decref(t);
681
+ return u;
682
+ }
683
+
684
+ static PyObject *
685
+ get_item_with_error(PyObject *d, const char *key)
686
+ {
687
+ PyObject *s, *v;
688
+
689
+ s = PyUnicode_FromString(key);
690
+ if (s == NULL) {
681
691
  return NULL;
682
692
  }
683
693
 
684
- for (i = 0; i < nin; i++) {
685
- PyObject *tmp = PySequence_Fast_GET_ITEM(args, i);
686
- if (!Ndt_Check(tmp)) {
687
- PyErr_Format(PyExc_TypeError, "argument types must be ndt");
688
- return NULL;
694
+ v = PyDict_GetItemWithError(d, s);
695
+ Py_DECREF(s);
696
+ return v;
697
+ }
698
+
699
+ static int
700
+ parse_args(const ndt_t *types[NDT_MAX_ARGS], int *py_nin, int *py_nout, int *py_nargs,
701
+ PyObject *args, PyObject *kwargs)
702
+ {
703
+ Py_ssize_t nin;
704
+ Py_ssize_t nout;
705
+
706
+ if (!args || !PyTuple_Check(args)) {
707
+ const char *tuple = args ? Py_TYPE(args)->tp_name : "NULL";
708
+ PyErr_Format(PyExc_SystemError,
709
+ "internal error: expected tuple, got '%.200s'",
710
+ tuple);
711
+ return -1;
712
+ }
713
+
714
+ if (kwargs && !PyDict_Check(kwargs)) {
715
+ PyErr_Format(PyExc_SystemError,
716
+ "internal error: expected dict, got '%.200s'",
717
+ Py_TYPE(kwargs)->tp_name);
718
+ return -1;
719
+ }
720
+
721
+ nin = PyTuple_GET_SIZE(args);
722
+ if (nin > NDT_MAX_ARGS) {
723
+ PyErr_Format(PyExc_TypeError,
724
+ "maximum number of arguments is %d, got %n", NDT_MAX_ARGS, nin);
725
+ return -1;
726
+ }
727
+
728
+ for (Py_ssize_t i = 0; i < nin; i++) {
729
+ PyObject *v = PyTuple_GET_ITEM(args, i);
730
+ if (!Ndt_Check(v)) {
731
+ PyErr_Format(PyExc_TypeError,
732
+ "expected ndt argument, got '%.200s'", Py_TYPE(v)->tp_name);
733
+ return -1;
689
734
  }
690
- in[i] = CONST_NDT(tmp);
735
+
736
+ types[i] = NDT(v);
691
737
  }
692
738
 
693
- spec = ndt_apply_spec_empty;
694
- if (ndt_typecheck(&spec, sig, in, (int)nin, NULL, NULL, &ctx) < 0) {
739
+ if (kwargs == NULL || PyDict_Size(kwargs) == 0) {
740
+ nout = 0;
741
+ }
742
+ else if (PyDict_Size(kwargs) == 1) {
743
+ PyObject *out = get_item_with_error(kwargs, "out");
744
+ if (out == NULL) {
745
+ if (PyErr_Occurred()) {
746
+ return -1;
747
+ }
748
+ PyErr_SetString(PyExc_TypeError,
749
+ "the only supported keyword argument is 'out'");
750
+ return -1;
751
+ }
752
+
753
+ if (out == Py_None) {
754
+ nout = 0;
755
+ }
756
+ else if (Ndt_Check(out)) {
757
+ nout = 1;
758
+ if (nin+nout > NDT_MAX_ARGS) {
759
+ PyErr_Format(PyExc_TypeError,
760
+ "maximum number of arguments is %d, got %n", NDT_MAX_ARGS, nin+nout);
761
+ return -1;
762
+ }
763
+
764
+ types[nin] = NDT(out);
765
+ }
766
+ else if (PyTuple_Check(out)) {
767
+ nout = PyTuple_GET_SIZE(out);
768
+ if (nout > NDT_MAX_ARGS || nin+nout > NDT_MAX_ARGS) {
769
+ PyErr_Format(PyExc_TypeError,
770
+ "maximum number of arguments is %d, got %n", NDT_MAX_ARGS, nin+nout);
771
+ return -1;
772
+ }
773
+
774
+ for (Py_ssize_t i = 0; i < nout; i++) {
775
+ PyObject *v = PyTuple_GET_ITEM(out, i);
776
+ if (!Ndt_Check(v)) {
777
+ PyErr_Format(PyExc_TypeError,
778
+ "expected ndt argument, got '%.200s'", Py_TYPE(v)->tp_name);
779
+ return -1;
780
+ }
781
+
782
+ types[nin+i] = NDT(v);
783
+ }
784
+ }
785
+ else {
786
+ PyErr_Format(PyExc_TypeError,
787
+ "'out' argument must be ndt or a tuple of ndt, got '%.200s'",
788
+ Py_TYPE(out)->tp_name);
789
+ return -1;
790
+ }
791
+ }
792
+ else {
793
+ PyErr_SetString(PyExc_TypeError,
794
+ "the only supported keyword argument is 'out'");
795
+ return -1;
796
+ }
797
+
798
+ for (int i = 0; i < nin+nout; i++) {
799
+ ndt_incref(types[i]);
800
+ }
801
+
802
+ *py_nin = (int)nin;
803
+ *py_nout = (int)nout;
804
+ *py_nargs = (int)nin+(int)nout;
805
+
806
+ return 0;
807
+ }
808
+
809
+ static PyObject *
810
+ ndtype_apply(PyObject *self, PyObject *args, PyObject *kwargs)
811
+ {
812
+ NDT_STATIC_CONTEXT(ctx);
813
+ const ndt_t *sig = NDT(self);
814
+ const ndt_t *types[NDT_MAX_ARGS] = {NULL};
815
+ const int64_t li[NDT_MAX_ARGS] = {0};
816
+ ndt_apply_spec_t spec = ndt_apply_spec_empty;
817
+ int py_nin, py_nout, py_nargs;
818
+ PyObject *res = NULL;
819
+ PyObject *flags = NULL;
820
+ PyObject *outer_dims = NULL;
821
+ PyObject *nin = NULL;
822
+ PyObject *nout = NULL;
823
+ PyObject *nargs = NULL;
824
+ PyObject *lst = NULL;
825
+ int ret;
826
+
827
+ if (parse_args(types, &py_nin, &py_nout, &py_nargs, args, kwargs) < 0) {
828
+ return NULL;
829
+ }
830
+
831
+ ret = ndt_typecheck(&spec, sig, types, li, py_nin, py_nout, false,
832
+ NULL, NULL, &ctx);
833
+ ndt_type_array_clear(types, py_nargs);
834
+ if (ret < 0) {
695
835
  return seterr(&ctx);
696
836
  }
697
837
 
@@ -700,53 +840,52 @@ ndtype_apply(PyObject *self, PyObject *args)
700
840
  return NULL;
701
841
  }
702
842
 
703
- out = PyList_New(spec.nout);
704
- if (out == NULL) {
843
+ lst = PyList_New(spec.nargs);
844
+ if (lst == NULL) {
705
845
  ndt_apply_spec_clear(&spec);
706
846
  goto finish;
707
847
  }
708
848
 
709
- for (i=spec.nout-1; i >= 0; i--) {
849
+ for (int i = 0; i < spec.nargs; i++) {
710
850
  PyObject *x = ndtype_alloc(&Ndt_Type);
711
851
  if (x == NULL) {
712
852
  ndt_apply_spec_clear(&spec);
713
853
  goto finish;
714
854
  }
715
- NDT(x) = spec.out[i];
716
- spec.out[i] = NULL; spec.nout--;
717
- PyList_SET_ITEM(out, i, x);
855
+ NDT(x) = spec.types[i];
856
+ PyList_SET_ITEM(lst, i, x);
718
857
  }
719
858
 
720
- broadcast = PyList_New(spec.nbroadcast);
721
- if (broadcast == NULL) {
722
- ndt_apply_spec_clear(&spec);
859
+ outer_dims = PyLong_FromLong(spec.outer_dims);
860
+ if (outer_dims == NULL) {
723
861
  goto finish;
724
862
  }
725
863
 
726
- for (i=spec.nbroadcast-1; i >= 0; i--) {
727
- PyObject *x = ndtype_alloc(&Ndt_Type);
728
- if (x == NULL) {
729
- ndt_apply_spec_clear(&spec);
730
- goto finish;
731
- }
732
- NDT(x) = spec.broadcast[i];
733
- spec.broadcast[i] = NULL; spec.nbroadcast--;
734
- PyList_SET_ITEM(broadcast, i, x);
864
+ nin = PyLong_FromLong(spec.nin);
865
+ if (nin == NULL) {
866
+ goto finish;
735
867
  }
736
868
 
737
- outer_dims = PyLong_FromLong(spec.outer_dims);
738
- if (outer_dims == NULL) {
869
+ nout = PyLong_FromLong(spec.nout);
870
+ if (nout == NULL) {
871
+ goto finish;
872
+ }
873
+
874
+ nargs = PyLong_FromLong(spec.nargs);
875
+ if (nargs == NULL) {
739
876
  goto finish;
740
877
  }
741
878
 
742
- res = PyObject_CallFunctionObjArgs((PyObject *)ApplySpec, flags, self,
743
- args, broadcast, out, outer_dims, NULL);
879
+ res = PyObject_CallFunctionObjArgs((PyObject *)_ApplySpec, flags,
880
+ outer_dims, nin, nout, nargs, lst, NULL);
744
881
 
745
882
  finish:
746
883
  Py_XDECREF(flags);
747
- Py_XDECREF(out);
748
- Py_XDECREF(broadcast);
749
884
  Py_XDECREF(outer_dims);
885
+ Py_XDECREF(nin);
886
+ Py_XDECREF(nout);
887
+ Py_XDECREF(nargs);
888
+ Py_XDECREF(lst);
750
889
  return res;
751
890
  }
752
891
 
@@ -777,6 +916,7 @@ static PyObject *
777
916
  ndtype_ndim(PyObject *self, PyObject *args UNUSED)
778
917
  {
779
918
  const ndt_t *t = NDT(self);
919
+ int ldim;
780
920
 
781
921
  if (ndt_is_abstract(t)) {
782
922
  PyErr_SetString(PyExc_TypeError,
@@ -784,7 +924,8 @@ ndtype_ndim(PyObject *self, PyObject *args UNUSED)
784
924
  return NULL;
785
925
  }
786
926
 
787
- return PyLong_FromLong(t->ndim);
927
+ ldim = ndt_logical_ndim(t);
928
+ return PyLong_FromLong(ldim);
788
929
  }
789
930
 
790
931
  static PyObject *
@@ -857,19 +998,8 @@ ndtype_strides(PyObject *self, PyObject *args UNUSED)
857
998
  static PyObject *
858
999
  ndtype_hidden_dtype(PyObject *self, PyObject *args UNUSED)
859
1000
  {
860
- NDT_STATIC_CONTEXT(ctx);
861
- const ndt_t *t = NDT(self);
862
- const ndt_t *dtype;
863
- ndt_t *u;
864
-
865
- dtype = ndt_hidden_dtype(t);
866
-
867
- u = ndt_copy(dtype, &ctx);
868
- if (u == NULL) {
869
- return seterr(&ctx);
870
- }
871
-
872
- return Ndt_FromType(u);
1001
+ const ndt_t *dtype = ndt_hidden_dtype(NDT(self));
1002
+ return Ndt_FromType(dtype);
873
1003
  }
874
1004
 
875
1005
  static PyObject *
@@ -970,10 +1100,13 @@ static PyMethodDef ndtype_methods [] =
970
1100
  /* Boolean functions on array types */
971
1101
  { "is_c_contiguous", (PyCFunction)ndtype_ndt_is_c_contiguous, METH_NOARGS, doc_is_c_contiguous },
972
1102
  { "is_f_contiguous", (PyCFunction)ndtype_ndt_is_f_contiguous, METH_NOARGS, doc_is_f_contiguous },
1103
+ { "is_var_contiguous", (PyCFunction)dtype_ndt_is_var_contiguous, METH_NOARGS, NULL },
973
1104
 
974
1105
  /* Binary functions */
1106
+ { "at", (PyCFunction)ndtype_at, METH_VARARGS|METH_KEYWORDS, NULL },
975
1107
  { "match", (PyCFunction)ndtype_match, METH_O, doc_match },
976
- { "apply", (PyCFunction)ndtype_apply, METH_O, "method likely to change" },
1108
+ { "unify", (PyCFunction)ndtype_unify, METH_O, NULL },
1109
+ { "apply", (PyCFunction)ndtype_apply, METH_VARARGS|METH_KEYWORDS, "method likely to change" },
977
1110
 
978
1111
  /* Other functions */
979
1112
  { "to_format", (PyCFunction)ndtype_to_format, METH_NOARGS, NULL },
@@ -1005,14 +1138,12 @@ static PyTypeObject Ndt_Type =
1005
1138
  .tp_hash = ndtype_hash,
1006
1139
  .tp_str = (reprfunc) ndtype_str,
1007
1140
  .tp_getattro = (getattrofunc) PyObject_GenericGetAttr,
1008
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1009
- .tp_traverse = (traverseproc)ndtype_traverse,
1141
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1010
1142
  .tp_richcompare = ndtype_richcompare,
1011
1143
  .tp_methods = ndtype_methods,
1012
1144
  .tp_getset = ndtype_getsets,
1013
- .tp_alloc = PyType_GenericAlloc,
1014
1145
  .tp_new = ndtype_new,
1015
- .tp_free = PyObject_GC_Del
1146
+ .tp_free = PyObject_Del
1016
1147
  };
1017
1148
 
1018
1149
 
@@ -1034,13 +1165,6 @@ Ndt_Check(const PyObject *v)
1034
1165
  return PyObject_TypeCheck(v, &Ndt_Type);
1035
1166
  }
1036
1167
 
1037
- static const ndt_t *
1038
- CONST_NDT(const PyObject *v)
1039
- {
1040
- assert(Ndt_Check(v));
1041
- return ((NdtObject *)v)->ndt;
1042
- }
1043
-
1044
1168
  static PyObject *
1045
1169
  Ndt_SetError(ndt_context_t *ctx)
1046
1170
  {
@@ -1048,67 +1172,18 @@ Ndt_SetError(ndt_context_t *ctx)
1048
1172
  }
1049
1173
 
1050
1174
  static PyObject *
1051
- Ndt_CopySubtree(const PyObject *src, const ndt_t *t)
1052
- {
1053
- NDT_STATIC_CONTEXT(ctx);
1054
- PyObject *dest;
1055
-
1056
- if (!Ndt_Check(src)) {
1057
- PyErr_SetString(PyExc_TypeError, "expected ndt object");
1058
- return NULL;
1059
- }
1060
-
1061
- dest = ndtype_alloc(Py_TYPE(src));
1062
- if (dest == NULL) {
1063
- return NULL;
1064
- }
1065
-
1066
- NDT(dest) = ndt_copy(t, &ctx);
1067
- if (NDT(dest) == NULL) {
1068
- return seterr(&ctx);
1069
- }
1070
-
1071
- RBUF(dest) = RBUF(src);
1072
- Py_XINCREF(RBUF(dest));
1073
-
1074
- return dest;
1075
- }
1076
-
1077
- static PyObject *
1078
- Ndt_MoveSubtree(const PyObject *src, ndt_t *t)
1079
- {
1080
- PyObject *dest;
1081
-
1082
- if (!Ndt_Check(src)) {
1083
- PyErr_SetString(PyExc_TypeError, "expected ndt object");
1084
- return NULL;
1085
- }
1086
-
1087
- dest = ndtype_alloc(Py_TYPE(src));
1088
- if (dest == NULL) {
1089
- ndt_del(t);
1090
- return NULL;
1091
- }
1092
-
1093
- NDT(dest) = t;
1094
- RBUF(dest) = RBUF(src);
1095
- Py_XINCREF(RBUF(dest));
1096
-
1097
- return dest;
1098
- }
1099
-
1100
- static PyObject *
1101
- Ndt_FromType(ndt_t *type)
1175
+ Ndt_FromType(const ndt_t *t)
1102
1176
  {
1103
1177
  PyObject *self;
1104
1178
 
1105
1179
  self = ndtype_alloc(&Ndt_Type);
1106
1180
  if (self == NULL) {
1107
- ndt_del(type);
1108
1181
  return NULL;
1109
1182
  }
1110
1183
 
1111
- NDT(self) = type;
1184
+ ndt_incref(t);
1185
+ NDT(self) = t;
1186
+
1112
1187
  return self;
1113
1188
  }
1114
1189
 
@@ -1118,17 +1193,22 @@ Ndt_FromObject(PyObject *obj)
1118
1193
  return ndtype_from_object(&Ndt_Type, obj);
1119
1194
  }
1120
1195
 
1196
+ static PyObject *
1197
+ Ndt_FromOffsetsAndDtype(PyObject *offsets, bool *opt, const ndt_t *dtype)
1198
+ {
1199
+ return ndtype_from_offsets_opt_and_dtype(&Ndt_Type, offsets, opt, dtype);
1200
+ }
1201
+
1202
+
1121
1203
  static PyObject *
1122
1204
  init_api(void)
1123
1205
  {
1124
1206
  ndtypes_api[Ndt_CheckExact_INDEX] = (void *)Ndt_CheckExact;
1125
1207
  ndtypes_api[Ndt_Check_INDEX] = (void *)Ndt_Check;
1126
- ndtypes_api[CONST_NDT_INDEX] = (void *)CONST_NDT;
1127
1208
  ndtypes_api[Ndt_SetError_INDEX] = (void *)Ndt_SetError;
1128
- ndtypes_api[Ndt_CopySubtree_INDEX] = (void *)Ndt_CopySubtree;
1129
- ndtypes_api[Ndt_MoveSubtree_INDEX] = (void *)Ndt_MoveSubtree;
1130
1209
  ndtypes_api[Ndt_FromType_INDEX] = (void *)Ndt_FromType;
1131
1210
  ndtypes_api[Ndt_FromObject_INDEX] = (void *)Ndt_FromObject;
1211
+ ndtypes_api[Ndt_FromOffsetsAndDtype_INDEX] = (void *)Ndt_FromOffsetsAndDtype;
1132
1212
 
1133
1213
  return PyCapsule_New(ndtypes_api, "ndtypes._ndtypes._API", NULL);
1134
1214
  }
@@ -1145,7 +1225,8 @@ ndtype_typedef(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1145
1225
  NDT_STATIC_CONTEXT(ctx);
1146
1226
  PyObject *name, *type;
1147
1227
  const char *cname, *ctype;
1148
- ndt_t *t;
1228
+ const ndt_t *t;
1229
+ int ret;
1149
1230
 
1150
1231
  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &name, &type)) {
1151
1232
  return NULL;
@@ -1166,7 +1247,9 @@ ndtype_typedef(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1166
1247
  return seterr(&ctx);
1167
1248
  }
1168
1249
 
1169
- if (ndt_typedef(cname, t, NULL, &ctx) < 0) {
1250
+ ret = ndt_typedef(cname, t, NULL, &ctx);
1251
+ ndt_decref(t);
1252
+ if (ret < 0) {
1170
1253
  return seterr(&ctx);
1171
1254
  }
1172
1255
 
@@ -1179,9 +1262,10 @@ ndtype_instantiate(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1179
1262
  static char *kwlist[] = {"name", "type", NULL};
1180
1263
  NDT_STATIC_CONTEXT(ctx);
1181
1264
  PyObject *name, *type;
1265
+ PyObject *ret;
1266
+ const ndt_t *t;
1182
1267
  const char *cname;
1183
1268
  char *cp;
1184
- ndt_t *t, *tp;
1185
1269
 
1186
1270
  if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &name, &type)) {
1187
1271
  return NULL;
@@ -1202,18 +1286,14 @@ ndtype_instantiate(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1202
1286
  return seterr(&ctx);
1203
1287
  }
1204
1288
 
1205
- tp = ndt_copy(NDT(type), &ctx);
1206
- if (tp == NULL) {
1207
- ndt_free(cp);
1208
- return seterr(&ctx);
1209
- }
1210
-
1211
- t = ndt_nominal(cp, tp, &ctx);
1289
+ t = ndt_nominal(cp, NDT(type), false, &ctx);
1212
1290
  if (t == NULL) {
1213
1291
  return seterr(&ctx);
1214
1292
  }
1215
1293
 
1216
- return Ndt_MoveSubtree(type, t);
1294
+ ret = Ndt_FromType(t);
1295
+ ndt_decref(t);
1296
+ return ret;
1217
1297
  }
1218
1298
 
1219
1299
  static PyMethodDef _ndtypes_methods [] =
@@ -1248,6 +1328,11 @@ PyInit__ndtypes(void)
1248
1328
  static int initialized = 0;
1249
1329
 
1250
1330
  if (!initialized) {
1331
+ ndt_mallocfunc = PyMem_Malloc;
1332
+ ndt_reallocfunc = PyMem_Realloc;
1333
+ ndt_callocfunc = PyMem_Calloc;
1334
+ ndt_freefunc = PyMem_Free;
1335
+
1251
1336
  capsule = init_api();
1252
1337
  if (capsule == NULL) {
1253
1338
  return NULL;
@@ -1258,25 +1343,21 @@ PyInit__ndtypes(void)
1258
1343
  initialized = 1;
1259
1344
  }
1260
1345
 
1261
- if (PyType_Ready(&ResourceBuffer_Type) < 0) {
1262
- goto error;
1263
- }
1264
-
1265
1346
  Ndt_Type.tp_base = &PyBaseObject_Type;
1266
1347
  if (PyType_Ready(&Ndt_Type) < 0) {
1267
1348
  goto error;
1268
1349
  }
1269
1350
 
1270
- /* ApplySpec */
1351
+ /* _ApplySpec */
1271
1352
  collections = PyImport_ImportModule("collections");
1272
1353
  if (collections == NULL) {
1273
1354
  goto error;
1274
1355
  }
1275
1356
 
1276
- ApplySpec = (PyTypeObject *)PyObject_CallMethod(collections,
1357
+ _ApplySpec = (PyTypeObject *)PyObject_CallMethod(collections,
1277
1358
  "namedtuple", "(ss)", "ApplySpec",
1278
- "flags sig in_types in_broadcast out_types outer_dims");
1279
- if (ApplySpec == NULL) {
1359
+ "flags outer_dims nin nout nargs types");
1360
+ if (_ApplySpec == NULL) {
1280
1361
  goto error;
1281
1362
  }
1282
1363
 
@@ -1285,7 +1366,7 @@ PyInit__ndtypes(void)
1285
1366
  goto error;
1286
1367
  }
1287
1368
 
1288
- if (PyDict_SetItemString(ApplySpec->tp_dict, "__module__", obj) < 0) {
1369
+ if (PyDict_SetItemString(_ApplySpec->tp_dict, "__module__", obj) < 0) {
1289
1370
  goto error;
1290
1371
  }
1291
1372
  Py_CLEAR(obj);
@@ -1306,8 +1387,8 @@ PyInit__ndtypes(void)
1306
1387
  goto error;
1307
1388
  }
1308
1389
 
1309
- Py_INCREF(ApplySpec);
1310
- if (PyModule_AddObject(m, "ApplySpec", (PyObject *)ApplySpec) < 0) {
1390
+ Py_INCREF(_ApplySpec);
1391
+ if (PyModule_AddObject(m, "_ApplySpec", (PyObject *)_ApplySpec) < 0) {
1311
1392
  goto error;
1312
1393
  }
1313
1394