ndtypes 0.2.0dev5 → 0.2.0dev6

Sign up to get free protection for your applications and to get access to all the features.
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