ndtypes 0.2.0dev4

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 (139) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +50 -0
  3. data/Gemfile +2 -0
  4. data/History.md +0 -0
  5. data/README.md +19 -0
  6. data/Rakefile +125 -0
  7. data/ext/ruby_ndtypes/extconf.rb +55 -0
  8. data/ext/ruby_ndtypes/gc_guard.c +36 -0
  9. data/ext/ruby_ndtypes/gc_guard.h +12 -0
  10. data/ext/ruby_ndtypes/ndtypes/AUTHORS.txt +5 -0
  11. data/ext/ruby_ndtypes/ndtypes/INSTALL.txt +101 -0
  12. data/ext/ruby_ndtypes/ndtypes/LICENSE.txt +29 -0
  13. data/ext/ruby_ndtypes/ndtypes/MANIFEST.in +3 -0
  14. data/ext/ruby_ndtypes/ndtypes/Makefile.in +87 -0
  15. data/ext/ruby_ndtypes/ndtypes/README.rst +47 -0
  16. data/ext/ruby_ndtypes/ndtypes/config.guess +1530 -0
  17. data/ext/ruby_ndtypes/ndtypes/config.h.in +67 -0
  18. data/ext/ruby_ndtypes/ndtypes/config.sub +1782 -0
  19. data/ext/ruby_ndtypes/ndtypes/configure +5260 -0
  20. data/ext/ruby_ndtypes/ndtypes/configure.ac +161 -0
  21. data/ext/ruby_ndtypes/ndtypes/doc/Makefile +14 -0
  22. data/ext/ruby_ndtypes/ndtypes/doc/_static/copybutton.js +66 -0
  23. data/ext/ruby_ndtypes/ndtypes/doc/conf.py +26 -0
  24. data/ext/ruby_ndtypes/ndtypes/doc/grammar/grammar.rst +27 -0
  25. data/ext/ruby_ndtypes/ndtypes/doc/index.rst +56 -0
  26. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/context.rst +131 -0
  27. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/encodings.rst +68 -0
  28. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/fields-values.rst +175 -0
  29. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/functions.rst +72 -0
  30. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/index.rst +43 -0
  31. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/init.rst +48 -0
  32. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/io.rst +100 -0
  33. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/memory.rst +124 -0
  34. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/predicates.rst +110 -0
  35. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/typedef.rst +31 -0
  36. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/types.rst +594 -0
  37. data/ext/ruby_ndtypes/ndtypes/doc/libndtypes/util.rst +166 -0
  38. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/buffer-protocol.rst +27 -0
  39. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/index.rst +21 -0
  40. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/pattern-matching.rst +330 -0
  41. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/quickstart.rst +144 -0
  42. data/ext/ruby_ndtypes/ndtypes/doc/ndtypes/types.rst +544 -0
  43. data/ext/ruby_ndtypes/ndtypes/doc/releases/index.rst +35 -0
  44. data/ext/ruby_ndtypes/ndtypes/install-sh +527 -0
  45. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.in +271 -0
  46. data/ext/ruby_ndtypes/ndtypes/libndtypes/Makefile.vc +269 -0
  47. data/ext/ruby_ndtypes/ndtypes/libndtypes/alloc.c +230 -0
  48. data/ext/ruby_ndtypes/ndtypes/libndtypes/attr.c +268 -0
  49. data/ext/ruby_ndtypes/ndtypes/libndtypes/attr.h +109 -0
  50. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/Makefile.in +73 -0
  51. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/Makefile.vc +70 -0
  52. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/README.txt +16 -0
  53. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.c +2179 -0
  54. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.h +134 -0
  55. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bpgrammar.y +428 -0
  56. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.c +2543 -0
  57. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.h +735 -0
  58. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/bplexer.l +176 -0
  59. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/export.c +543 -0
  60. data/ext/ruby_ndtypes/ndtypes/libndtypes/compat/import.c +110 -0
  61. data/ext/ruby_ndtypes/ndtypes/libndtypes/context.c +228 -0
  62. data/ext/ruby_ndtypes/ndtypes/libndtypes/copy.c +634 -0
  63. data/ext/ruby_ndtypes/ndtypes/libndtypes/encodings.c +116 -0
  64. data/ext/ruby_ndtypes/ndtypes/libndtypes/equal.c +288 -0
  65. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.c +3067 -0
  66. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.h +180 -0
  67. data/ext/ruby_ndtypes/ndtypes/libndtypes/grammar.y +417 -0
  68. data/ext/ruby_ndtypes/ndtypes/libndtypes/io.c +1658 -0
  69. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.c +2773 -0
  70. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.h +734 -0
  71. data/ext/ruby_ndtypes/ndtypes/libndtypes/lexer.l +222 -0
  72. data/ext/ruby_ndtypes/ndtypes/libndtypes/match.c +1132 -0
  73. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.c +2323 -0
  74. data/ext/ruby_ndtypes/ndtypes/libndtypes/ndtypes.h.in +893 -0
  75. data/ext/ruby_ndtypes/ndtypes/libndtypes/overflow.h +161 -0
  76. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.c +473 -0
  77. data/ext/ruby_ndtypes/ndtypes/libndtypes/parsefuncs.h +92 -0
  78. data/ext/ruby_ndtypes/ndtypes/libndtypes/parser.c +246 -0
  79. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.c +269 -0
  80. data/ext/ruby_ndtypes/ndtypes/libndtypes/seq.h +197 -0
  81. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/Makefile.in +48 -0
  82. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/Makefile.vc +46 -0
  83. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/deserialize.c +1007 -0
  84. data/ext/ruby_ndtypes/ndtypes/libndtypes/serialize/serialize.c +442 -0
  85. data/ext/ruby_ndtypes/ndtypes/libndtypes/slice.h +42 -0
  86. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.c +238 -0
  87. data/ext/ruby_ndtypes/ndtypes/libndtypes/substitute.h +50 -0
  88. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.c +371 -0
  89. data/ext/ruby_ndtypes/ndtypes/libndtypes/symtable.h +100 -0
  90. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.in +55 -0
  91. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/Makefile.vc +45 -0
  92. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/alloc_fail.c +82 -0
  93. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/alloc_fail.h +49 -0
  94. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/runtest.c +1657 -0
  95. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test.h +85 -0
  96. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_array.c +115 -0
  97. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_buffer.c +137 -0
  98. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_indent.c +201 -0
  99. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_match.c +2397 -0
  100. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_numba.c +57 -0
  101. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse.c +349 -0
  102. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_error.c +27839 -0
  103. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_parse_roundtrip.c +350 -0
  104. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_record.c +231 -0
  105. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_typecheck.c +375 -0
  106. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/test_typedef.c +65 -0
  107. data/ext/ruby_ndtypes/ndtypes/libndtypes/tests/valgrind.supp +30 -0
  108. data/ext/ruby_ndtypes/ndtypes/libndtypes/tools/bench.c +79 -0
  109. data/ext/ruby_ndtypes/ndtypes/libndtypes/tools/indent.c +94 -0
  110. data/ext/ruby_ndtypes/ndtypes/libndtypes/tools/print_ast.c +96 -0
  111. data/ext/ruby_ndtypes/ndtypes/libndtypes/util.c +474 -0
  112. data/ext/ruby_ndtypes/ndtypes/libndtypes/values.c +228 -0
  113. data/ext/ruby_ndtypes/ndtypes/python/bench.py +49 -0
  114. data/ext/ruby_ndtypes/ndtypes/python/ndt_randtype.py +409 -0
  115. data/ext/ruby_ndtypes/ndtypes/python/ndt_support.py +14 -0
  116. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/__init__.py +70 -0
  117. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/_ndtypes.c +1332 -0
  118. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/docstrings.h +319 -0
  119. data/ext/ruby_ndtypes/ndtypes/python/ndtypes/pyndtypes.h +154 -0
  120. data/ext/ruby_ndtypes/ndtypes/python/test_ndtypes.py +1977 -0
  121. data/ext/ruby_ndtypes/ndtypes/setup.py +288 -0
  122. data/ext/ruby_ndtypes/ndtypes/vcbuild/INSTALL.txt +41 -0
  123. data/ext/ruby_ndtypes/ndtypes/vcbuild/runtest32.bat +15 -0
  124. data/ext/ruby_ndtypes/ndtypes/vcbuild/runtest64.bat +13 -0
  125. data/ext/ruby_ndtypes/ndtypes/vcbuild/vcbuild32.bat +38 -0
  126. data/ext/ruby_ndtypes/ndtypes/vcbuild/vcbuild64.bat +38 -0
  127. data/ext/ruby_ndtypes/ndtypes/vcbuild/vcclean.bat +13 -0
  128. data/ext/ruby_ndtypes/ndtypes/vcbuild/vcdistclean.bat +14 -0
  129. data/ext/ruby_ndtypes/ruby_ndtypes.c +1003 -0
  130. data/ext/ruby_ndtypes/ruby_ndtypes.h +37 -0
  131. data/ext/ruby_ndtypes/ruby_ndtypes_internal.h +28 -0
  132. data/lib/ndtypes.rb +45 -0
  133. data/lib/ndtypes/errors.rb +2 -0
  134. data/lib/ndtypes/version.rb +6 -0
  135. data/ndtypes.gemspec +47 -0
  136. data/spec/gc_table_spec.rb +10 -0
  137. data/spec/ndtypes_spec.rb +289 -0
  138. data/spec/spec_helper.rb +241 -0
  139. metadata +242 -0
@@ -0,0 +1,14 @@
1
+ import sys
2
+ import unittest
3
+
4
+ def skip_if(condition, reason):
5
+ if condition:
6
+ raise unittest.SkipTest(reason)
7
+
8
+ HAVE_PYTHON_36 = sys.version_info >= (3, 6, 0)
9
+ HAVE_32_BIT_LINUX = sys.maxsize == 2**31-1 and sys.platform == 'linux'
10
+
11
+ requires_py36 = unittest.skipUnless(
12
+ sys.version_info > (3, 6),
13
+ "test requires Python 3.6 or greater")
14
+
@@ -0,0 +1,70 @@
1
+ #
2
+ # BSD 3-Clause License
3
+ #
4
+ # Copyright (c) 2017-2018, plures
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are met:
9
+ #
10
+ # 1. Redistributions of source code must retain the above copyright notice,
11
+ # this list of conditions and the following disclaimer.
12
+ #
13
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the documentation
15
+ # and/or other materials provided with the distribution.
16
+ #
17
+ # 3. Neither the name of the copyright holder nor the names of its
18
+ # contributors may be used to endorse or promote products derived from
19
+ # this software without specific prior written permission.
20
+ #
21
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ #
26
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ """
35
+ A module for typing memory blocks using a close variant of the datashape type
36
+ language.
37
+
38
+ The underlying library -- libndtypes -- implements the type part of a compiler
39
+ frontend. It can describe C types needed for array computing and additionally
40
+ includes symbolic types for dynamic type checking.
41
+
42
+ libndtypes has the concept of abstract and concrete types. Concrete types
43
+ contain the exact data layout and all sizes that are required to access
44
+ subtypes or individual elements in memory.
45
+
46
+ Abstract types are for type checking and include functions, symbolic dimensions
47
+ and type variables. Module support is planned at a later stage.
48
+
49
+ Concrete types with rich layout information make it possible to write
50
+ relatively small container libraries that can traverse memory without
51
+ type erasure.
52
+
53
+ The xnd module uses ndtypes to implement a general container for mapping most
54
+ Python types relevant for scientific computing directly to memory.
55
+ """
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
+ from ._ndtypes import *
@@ -0,0 +1,1332 @@
1
+ /*
2
+ * BSD 3-Clause License
3
+ *
4
+ * Copyright (c) 2017-2018, plures
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ *
17
+ * 3. Neither the name of the copyright holder nor the names of its
18
+ * contributors may be used to endorse or promote products derived from
19
+ * this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+
34
+ #include <Python.h>
35
+ #include <stdlib.h>
36
+ #include "ndtypes.h"
37
+ #include "docstrings.h"
38
+
39
+ #define NDTYPES_MODULE
40
+ #include "pyndtypes.h"
41
+
42
+
43
+ #ifdef _MSC_VER
44
+ #ifndef UNUSED
45
+ #define UNUSED
46
+ #endif
47
+ #else
48
+ #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
49
+ #define UNUSED __attribute__((unused))
50
+ #else
51
+ #define UNUSED
52
+ #endif
53
+ #endif
54
+
55
+
56
+ /****************************************************************************/
57
+ /* Resource Buffer Object */
58
+ /****************************************************************************/
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);
67
+
68
+ typedef struct {
69
+ PyObject_HEAD
70
+ ndt_meta_t *m;
71
+ } ResourceBufferObject;
72
+
73
+ static PyTypeObject ResourceBuffer_Type;
74
+
75
+ static PyObject *
76
+ rbuf_alloc(void)
77
+ {
78
+ NDT_STATIC_CONTEXT(ctx);
79
+ ResourceBufferObject *self;
80
+
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);
90
+ }
91
+
92
+ PyObject_GC_Track(self);
93
+ return (PyObject *)self;
94
+ }
95
+
96
+ static int
97
+ rbuf_traverse(ResourceBufferObject *self UNUSED, visitproc visit UNUSED,
98
+ void *arg UNUSED)
99
+ {
100
+ return 0;
101
+ }
102
+
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
+ }
111
+
112
+ static int
113
+ rbuf_init_from_offset_list(ResourceBufferObject *rbuf, PyObject *list)
114
+ {
115
+ ndt_meta_t * const m = rbuf->m;
116
+ PyObject *lst;
117
+
118
+ if (!PyList_Check(list)) {
119
+ PyErr_SetString(PyExc_TypeError, "expected a list of offset lists");
120
+ return -1;
121
+ }
122
+
123
+ const int64_t n = PyList_GET_SIZE(list);
124
+ if (n < 1 || n > NDT_MAX_DIM) {
125
+ PyErr_Format(PyExc_ValueError,
126
+ "number of offset lists must be in [1, %d]", NDT_MAX_DIM);
127
+ return -1;
128
+ }
129
+
130
+ m->ndims = 0;
131
+ for (int64_t i = n-1; i >= 0; i--) {
132
+ lst = PyList_GET_ITEM(list, i);
133
+ if (!PyList_Check(lst)) {
134
+ PyErr_SetString(PyExc_TypeError,
135
+ "expected a list of offset lists");
136
+ return -1;
137
+ }
138
+
139
+ const int64_t noffsets = PyList_GET_SIZE(lst);
140
+ if (noffsets < 2 || noffsets > INT32_MAX) {
141
+ PyErr_SetString(PyExc_ValueError,
142
+ "length of a single offset list must be in [2, INT32_MAX]");
143
+ return -1;
144
+ }
145
+
146
+ int32_t * const offsets = ndt_alloc(noffsets, sizeof(int32_t));
147
+ if (offsets == NULL) {
148
+ PyErr_NoMemory();
149
+ return -1;
150
+ }
151
+
152
+ for (int32_t k = 0; k < noffsets; k++) {
153
+ long long x = PyLong_AsLongLong(PyList_GET_ITEM(lst, k));
154
+ if (x == -1 && PyErr_Occurred()) {
155
+ ndt_free(offsets);
156
+ return -1;
157
+ }
158
+
159
+ if (x < 0 || x > INT32_MAX) {
160
+ ndt_free(offsets);
161
+ PyErr_SetString(PyExc_ValueError,
162
+ "offset must be in [0, INT32_MAX]");
163
+ return -1;
164
+ }
165
+
166
+ offsets[k] = (int32_t)x;
167
+ }
168
+
169
+ m->noffsets[m->ndims] = (int32_t)noffsets;
170
+ m->offsets[m->ndims] = offsets;
171
+ m->ndims++;
172
+ }
173
+
174
+ return 0;
175
+ }
176
+
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
+
263
+ /****************************************************************************/
264
+ /* ndt object */
265
+ /****************************************************************************/
266
+
267
+ static PyTypeObject Ndt_Type;
268
+
269
+ static PyObject *
270
+ ndtype_alloc(PyTypeObject *type)
271
+ {
272
+ NdtObject *self;
273
+
274
+ self = (NdtObject *)type->tp_alloc(type, 0);
275
+ if (self == NULL) {
276
+ return NULL;
277
+ }
278
+
279
+ RBUF(self) = NULL;
280
+ NDT(self) = NULL;
281
+
282
+ return (PyObject *)self;
283
+ }
284
+
285
+ static int
286
+ ndtype_traverse(NdtObject *self, visitproc visit, void *arg)
287
+ {
288
+ Py_VISIT(self->rbuf);
289
+ return 0;
290
+ }
291
+
292
+ static void
293
+ ndtype_dealloc(NdtObject *self)
294
+ {
295
+ PyObject_GC_UnTrack(self);
296
+ ndt_del(NDT(self));
297
+ Py_CLEAR(self->rbuf);
298
+ Py_TYPE(self)->tp_free(self);
299
+ }
300
+
301
+ static PyObject *
302
+ ndtype_from_object(PyTypeObject *tp, PyObject *type)
303
+ {
304
+ NDT_STATIC_CONTEXT(ctx);
305
+ PyObject *self;
306
+ const char *cp;
307
+
308
+ if (Ndt_Check(type)) {
309
+ Py_INCREF(type);
310
+ return type;
311
+ }
312
+
313
+ cp = PyUnicode_AsUTF8(type);
314
+ if (cp == NULL) {
315
+ return NULL;
316
+ }
317
+
318
+ self = ndtype_alloc(tp);
319
+ if (self == NULL) {
320
+ return NULL;
321
+ }
322
+
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);
330
+ if (NDT(self) == NULL) {
331
+ Py_DECREF(self);
332
+ return seterr(&ctx);
333
+ }
334
+
335
+ return self;
336
+ }
337
+
338
+ static PyObject *
339
+ ndtype_from_format(PyTypeObject *tp, PyObject *format)
340
+ {
341
+ NDT_STATIC_CONTEXT(ctx);
342
+ PyObject *self;
343
+ const char *cp;
344
+
345
+ cp = PyUnicode_AsUTF8(format);
346
+ if (cp == NULL) {
347
+ return NULL;
348
+ }
349
+
350
+ self = ndtype_alloc(tp);
351
+ if (self == NULL) {
352
+ return NULL;
353
+ }
354
+
355
+ NDT(self) = ndt_from_bpformat(cp, &ctx);
356
+ if (NDT(self) == NULL) {
357
+ Py_DECREF(self);
358
+ return seterr(&ctx);
359
+ }
360
+
361
+ return self;
362
+ }
363
+
364
+ static PyObject *
365
+ ndtype_to_format(PyObject *self, PyObject *args UNUSED)
366
+ {
367
+ NDT_STATIC_CONTEXT(ctx);
368
+ PyObject *ret;
369
+ char *cp;
370
+
371
+ cp = ndt_to_bpformat(NDT(self), &ctx);
372
+ if (cp == NULL) {
373
+ return seterr(&ctx);
374
+ }
375
+
376
+ ret = PyUnicode_FromString(cp);
377
+ ndt_free(cp);
378
+
379
+ return ret;
380
+ }
381
+
382
+ static PyObject *
383
+ ndtype_from_offsets_and_dtype(PyTypeObject *tp, PyObject *offsets, PyObject *dtype)
384
+ {
385
+ NDT_STATIC_CONTEXT(ctx);
386
+ PyObject *self;
387
+ const char *cp;
388
+
389
+ cp = PyUnicode_AsUTF8(dtype);
390
+ if (cp == NULL) {
391
+ return NULL;
392
+ }
393
+
394
+ self = ndtype_alloc(tp);
395
+ if (self == NULL) {
396
+ return NULL;
397
+ }
398
+
399
+ RBUF(self) = rbuf_from_offset_lists(offsets);
400
+ if (RBUF(self) == NULL) {
401
+ Py_DECREF(self);
402
+ return NULL;
403
+ }
404
+
405
+ NDT(self) = ndt_from_metadata_and_dtype(RBUF_NDT_META(self), cp, &ctx);
406
+
407
+ if (NDT(self) == NULL) {
408
+ Py_DECREF(self);
409
+ return seterr(&ctx);
410
+ }
411
+
412
+ return self;
413
+ }
414
+
415
+ static PyObject *
416
+ ndtype_deserialize(PyTypeObject *tp, PyObject *bytes)
417
+ {
418
+ NDT_STATIC_CONTEXT(ctx);
419
+ PyObject *self;
420
+
421
+ if (!PyBytes_Check(bytes)) {
422
+ PyErr_SetString(PyExc_TypeError, "expected bytes object");
423
+ return NULL;
424
+ }
425
+
426
+ self = ndtype_alloc(tp);
427
+ if (self == NULL) {
428
+ return NULL;
429
+ }
430
+
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),
438
+ PyBytes_GET_SIZE(bytes), &ctx);
439
+ if (NDT(self) == NULL) {
440
+ Py_DECREF(self);
441
+ return seterr(&ctx);
442
+ }
443
+
444
+ return self;
445
+ }
446
+
447
+ static PyObject *
448
+ ndtype_new(PyTypeObject *tp, PyObject *args, PyObject *kwds)
449
+ {
450
+ static char *kwlist[] = {"type", "offsets", NULL};
451
+ PyObject *offsets = Py_None;
452
+ PyObject *type;
453
+
454
+ if (!PyArg_ParseTupleAndKeywords(
455
+ args, kwds, "O|O", kwlist, &type, &offsets)) {
456
+ return NULL;
457
+ }
458
+
459
+ if (offsets == Py_None) {
460
+ return ndtype_from_object(tp, type);
461
+ }
462
+
463
+ return ndtype_from_offsets_and_dtype(tp, offsets, type);
464
+ }
465
+
466
+ static PyObject *
467
+ ndtype_str(PyObject *self)
468
+ {
469
+ NDT_STATIC_CONTEXT(ctx);
470
+ PyObject *res;
471
+ char *cp;
472
+
473
+ cp = ndt_as_string(NDT(self), &ctx);
474
+ if (cp == NULL) {
475
+ return seterr(&ctx);
476
+ }
477
+
478
+ res = PyUnicode_FromString(cp);
479
+ ndt_free(cp);
480
+ return res;
481
+ }
482
+
483
+ static PyObject *
484
+ ndtype_repr(PyObject *self)
485
+ {
486
+ NDT_STATIC_CONTEXT(ctx);
487
+ PyObject *res;
488
+ char *cp;
489
+
490
+ cp = ndt_as_string(NDT(self), &ctx);
491
+ if (cp == NULL) {
492
+ return seterr(&ctx);
493
+ }
494
+
495
+ res = PyUnicode_FromFormat("ndt(\"%s\")", cp);
496
+ ndt_free(cp);
497
+ return res;
498
+ }
499
+
500
+ static PyObject *
501
+ ndtype_pformat(PyObject *self, PyObject *args UNUSED)
502
+ {
503
+ NDT_STATIC_CONTEXT(ctx);
504
+ PyObject *res;
505
+ char *cp;
506
+
507
+ cp = ndt_indent(NDT(self), &ctx);
508
+ if (cp == NULL) {
509
+ return seterr(&ctx);
510
+ }
511
+
512
+ res = PyUnicode_FromString(cp);
513
+ ndt_free(cp);
514
+ return res;
515
+ }
516
+
517
+ static PyObject *
518
+ ndtype_pprint(PyObject *self, PyObject *args UNUSED)
519
+ {
520
+ NDT_STATIC_CONTEXT(ctx);
521
+ char *cp;
522
+
523
+ cp = ndt_indent(NDT(self), &ctx);
524
+ if (cp == NULL) {
525
+ return seterr(&ctx);
526
+ }
527
+
528
+ printf("%s\n", cp);
529
+ fflush(stdout);
530
+
531
+ ndt_free(cp);
532
+ Py_RETURN_NONE;
533
+ }
534
+
535
+ static PyObject *
536
+ ndtype_ast_repr(PyObject *self, PyObject *args UNUSED)
537
+ {
538
+ NDT_STATIC_CONTEXT(ctx);
539
+ PyObject *res;
540
+ char *cp;
541
+
542
+ cp = ndt_ast_repr(NDT(self), &ctx);
543
+ if (cp == NULL) {
544
+ return seterr(&ctx);
545
+ }
546
+
547
+ res = PyUnicode_FromString(cp);
548
+ ndt_free(cp);
549
+ return res;
550
+ }
551
+
552
+ static PyObject *
553
+ ndtype_copy(PyObject *self, PyObject *args UNUSED)
554
+ {
555
+ Py_INCREF(self);
556
+ return self;
557
+ }
558
+
559
+ static PyObject *
560
+ ndtype_serialize(PyObject *self, PyObject *args UNUSED)
561
+ {
562
+ NDT_STATIC_CONTEXT(ctx);
563
+ PyObject *res;
564
+ char *bytes;
565
+ int64_t size;
566
+
567
+ size = ndt_serialize(&bytes, NDT(self), &ctx);
568
+ if (size < 0) {
569
+ return seterr(&ctx);
570
+ }
571
+
572
+ res = PyBytes_FromStringAndSize(bytes, (Py_ssize_t)size);
573
+ ndt_free(bytes);
574
+ return res;
575
+ }
576
+
577
+
578
+ /******************************************************************************/
579
+ /* Ndt methods */
580
+ /******************************************************************************/
581
+
582
+ #define Ndtype_BoolFunc(NDTFUNC) \
583
+ static PyObject * \
584
+ ndtype_##NDTFUNC(PyObject *self, PyObject *args UNUSED) \
585
+ { \
586
+ if (NDTFUNC(NDT(self))) { \
587
+ Py_RETURN_TRUE; \
588
+ } \
589
+ Py_RETURN_FALSE; \
590
+ }
591
+
592
+ Ndtype_BoolFunc(ndt_is_abstract)
593
+ Ndtype_BoolFunc(ndt_is_concrete)
594
+
595
+ Ndtype_BoolFunc(ndt_is_optional)
596
+ Ndtype_BoolFunc(ndt_is_scalar)
597
+ Ndtype_BoolFunc(ndt_is_signed)
598
+ Ndtype_BoolFunc(ndt_is_unsigned)
599
+ Ndtype_BoolFunc(ndt_is_float)
600
+ Ndtype_BoolFunc(ndt_is_complex)
601
+
602
+ Ndtype_BoolFunc(ndt_is_c_contiguous)
603
+ Ndtype_BoolFunc(ndt_is_f_contiguous)
604
+
605
+
606
+ static PyObject *
607
+ ndtype_richcompare(PyObject *self, PyObject *other, int op)
608
+ {
609
+ int r = 0;
610
+
611
+ assert(Ndt_Check(self));
612
+
613
+ if (Ndt_Check(other)) {
614
+ r = ndt_equal(NDT(self), NDT(other));
615
+ }
616
+
617
+ switch (op) {
618
+ case Py_EQ:
619
+ return PyBool_FromLong(r);
620
+ case Py_NE:
621
+ return PyBool_FromLong(!r);
622
+ default:
623
+ Py_RETURN_NOTIMPLEMENTED;
624
+ }
625
+ }
626
+
627
+ static Py_hash_t
628
+ ndtype_hash(PyObject *self)
629
+ {
630
+ NDT_STATIC_CONTEXT(ctx);
631
+ Py_hash_t res;
632
+
633
+ res = ndt_hash(NDT(self), &ctx);
634
+ if (res == -1) {
635
+ (void)seterr(&ctx);
636
+ }
637
+
638
+ return res;
639
+ }
640
+
641
+ static PyObject *
642
+ ndtype_match(PyObject *self, PyObject *other)
643
+ {
644
+ NDT_STATIC_CONTEXT(ctx);
645
+ int res;
646
+
647
+ if (!Ndt_Check(other)) {
648
+ PyErr_SetString(PyExc_TypeError, "argument must be 'ndt'");
649
+ return NULL;
650
+ }
651
+
652
+ res = ndt_match(NDT(self), NDT(other), &ctx);
653
+ if (res == -1) {
654
+ return seterr(&ctx);
655
+ }
656
+
657
+ return PyBool_FromLong(res);
658
+ }
659
+
660
+ static PyObject *
661
+ ndtype_apply(PyObject *self, PyObject *args)
662
+ {
663
+ 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;
671
+
672
+ if (!PyTuple_Check(args) && !PyList_Check(args)) {
673
+ PyErr_SetString(PyExc_TypeError, "arguments must be a tuple or a list");
674
+ return NULL;
675
+ }
676
+
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);
681
+ return NULL;
682
+ }
683
+
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;
689
+ }
690
+ in[i] = CONST_NDT(tmp);
691
+ }
692
+
693
+ spec = ndt_apply_spec_empty;
694
+ if (ndt_typecheck(&spec, sig, in, (int)nin, NULL, NULL, &ctx) < 0) {
695
+ return seterr(&ctx);
696
+ }
697
+
698
+ flags = PyUnicode_FromString(ndt_apply_flags_as_string(&spec));
699
+ if (flags == NULL) {
700
+ return NULL;
701
+ }
702
+
703
+ out = PyList_New(spec.nout);
704
+ if (out == NULL) {
705
+ ndt_apply_spec_clear(&spec);
706
+ goto finish;
707
+ }
708
+
709
+ for (i=spec.nout-1; i >= 0; i--) {
710
+ PyObject *x = ndtype_alloc(&Ndt_Type);
711
+ if (x == NULL) {
712
+ ndt_apply_spec_clear(&spec);
713
+ goto finish;
714
+ }
715
+ NDT(x) = spec.out[i];
716
+ spec.out[i] = NULL; spec.nout--;
717
+ PyList_SET_ITEM(out, i, x);
718
+ }
719
+
720
+ broadcast = PyList_New(spec.nbroadcast);
721
+ if (broadcast == NULL) {
722
+ ndt_apply_spec_clear(&spec);
723
+ goto finish;
724
+ }
725
+
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);
735
+ }
736
+
737
+ outer_dims = PyLong_FromLong(spec.outer_dims);
738
+ if (outer_dims == NULL) {
739
+ goto finish;
740
+ }
741
+
742
+ res = PyObject_CallFunctionObjArgs((PyObject *)ApplySpec, flags, self,
743
+ args, broadcast, out, outer_dims, NULL);
744
+
745
+ finish:
746
+ Py_XDECREF(flags);
747
+ Py_XDECREF(out);
748
+ Py_XDECREF(broadcast);
749
+ Py_XDECREF(outer_dims);
750
+ return res;
751
+ }
752
+
753
+ static PyObject *
754
+ tuple_from_int64(int64_t x[NDT_MAX_DIM], int ndim)
755
+ {
756
+ PyObject *tuple;
757
+ int i;
758
+
759
+ tuple = PyTuple_New(ndim);
760
+ if (tuple == NULL) {
761
+ return NULL;
762
+ }
763
+
764
+ for (i = 0; i < ndim; i++) {
765
+ PyObject *v = PyLong_FromLongLong(x[i]);
766
+ if (v == NULL) {
767
+ Py_DECREF(tuple);
768
+ return NULL;
769
+ }
770
+ PyTuple_SET_ITEM(tuple, i, v);
771
+ }
772
+
773
+ return tuple;
774
+ }
775
+
776
+ static PyObject *
777
+ ndtype_ndim(PyObject *self, PyObject *args UNUSED)
778
+ {
779
+ const ndt_t *t = NDT(self);
780
+
781
+ if (ndt_is_abstract(t)) {
782
+ PyErr_SetString(PyExc_TypeError,
783
+ "abstract type has no ndim");
784
+ return NULL;
785
+ }
786
+
787
+ return PyLong_FromLong(t->ndim);
788
+ }
789
+
790
+ static PyObject *
791
+ ndtype_datasize(PyObject *self, PyObject *args UNUSED)
792
+ {
793
+ const ndt_t *t = NDT(self);
794
+
795
+ if (ndt_is_abstract(t)) {
796
+ PyErr_SetString(PyExc_TypeError,
797
+ "abstract type has no datasize");
798
+ return NULL;
799
+ }
800
+
801
+ return PyLong_FromLongLong(t->datasize);
802
+ }
803
+
804
+ static PyObject *
805
+ ndtype_itemsize(PyObject *self, PyObject *args UNUSED)
806
+ {
807
+ const ndt_t *t = NDT(self);
808
+ int64_t size;
809
+
810
+ if (ndt_is_abstract(t)) {
811
+ PyErr_SetString(PyExc_TypeError,
812
+ "abstract type has no itemsize");
813
+ return NULL;
814
+ }
815
+
816
+ switch (t->tag) {
817
+ case FixedDim:
818
+ size = t->Concrete.FixedDim.itemsize;
819
+ break;
820
+ case VarDim:
821
+ size = t->Concrete.VarDim.itemsize;
822
+ break;
823
+ default:
824
+ size = t->datasize;
825
+ break;
826
+ }
827
+
828
+ return PyLong_FromLongLong(size);
829
+ }
830
+
831
+ static PyObject *
832
+ ndtype_shape(PyObject *self, PyObject *args UNUSED)
833
+ {
834
+ NDT_STATIC_CONTEXT(ctx);
835
+ ndt_ndarray_t x;
836
+
837
+ if (ndt_as_ndarray(&x, NDT(self), &ctx) < 0) {
838
+ return seterr(&ctx);
839
+ }
840
+
841
+ return tuple_from_int64(x.shape, x.ndim);
842
+ }
843
+
844
+ static PyObject *
845
+ ndtype_strides(PyObject *self, PyObject *args UNUSED)
846
+ {
847
+ NDT_STATIC_CONTEXT(ctx);
848
+ ndt_ndarray_t x;
849
+
850
+ if (ndt_as_ndarray(&x, NDT(self), &ctx) < 0) {
851
+ return seterr(&ctx);
852
+ }
853
+
854
+ return tuple_from_int64(x.strides, x.ndim);
855
+ }
856
+
857
+ static PyObject *
858
+ ndtype_hidden_dtype(PyObject *self, PyObject *args UNUSED)
859
+ {
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);
873
+ }
874
+
875
+ static PyObject *
876
+ ndtype_align(PyObject *self, PyObject *args UNUSED)
877
+ {
878
+ if (ndt_is_abstract(NDT(self))) {
879
+ PyErr_SetString(PyExc_TypeError,
880
+ "abstract type has no alignment");
881
+ return NULL;
882
+ }
883
+
884
+ return PyLong_FromLong(NDT(self)->align);
885
+ }
886
+
887
+ static PyObject *
888
+ ndtype_reduce(PyObject *self, PyObject *args UNUSED)
889
+ {
890
+ PyObject *bytes;
891
+ PyObject *res;
892
+
893
+ bytes = ndtype_serialize(self, NULL);
894
+ if (bytes == NULL) {
895
+ return NULL;
896
+ }
897
+
898
+ res = Py_BuildValue("O(O)", Deserialize, bytes);
899
+ Py_DECREF(bytes);
900
+
901
+ return res;
902
+ }
903
+
904
+ static PyObject *
905
+ ndtype_to_nbformat(PyObject *self, PyObject *args UNUSED)
906
+ {
907
+ NDT_STATIC_CONTEXT(ctx);
908
+ PyObject *sig;
909
+ PyObject *core;
910
+ PyObject *ret;
911
+ char *s;
912
+ char *c;
913
+
914
+ if (ndt_to_nbformat(&s, &c, NDT(self), &ctx) < 0) {
915
+ return seterr(&ctx);
916
+ }
917
+
918
+ sig = PyUnicode_FromString(s);
919
+ ndt_free(s);
920
+ if (s == NULL) {
921
+ ndt_free(c);
922
+ return NULL;
923
+ }
924
+
925
+ core = PyUnicode_FromString(c);
926
+ ndt_free(c);
927
+ if (s == NULL) {
928
+ Py_DECREF(sig);
929
+ return NULL;
930
+ }
931
+
932
+ ret = PyTuple_New(2);
933
+ if (ret == NULL) {
934
+ Py_DECREF(sig);
935
+ Py_DECREF(core);
936
+ return NULL;
937
+ }
938
+
939
+ PyTuple_SET_ITEM(ret, 0, sig);
940
+ PyTuple_SET_ITEM(ret, 1, core);
941
+
942
+ return ret;
943
+ }
944
+
945
+
946
+ static PyGetSetDef ndtype_getsets [] =
947
+ {
948
+ { "align", (getter)ndtype_align, NULL, doc_align, NULL},
949
+ { "datasize", (getter)ndtype_datasize, NULL, doc_datasize, NULL},
950
+ { "itemsize", (getter)ndtype_itemsize, NULL, doc_itemsize, NULL},
951
+ { "ndim", (getter)ndtype_ndim, NULL, doc_ndim, NULL},
952
+ { "shape", (getter)ndtype_shape, NULL, doc_shape, NULL},
953
+ { "strides", (getter)ndtype_strides, NULL, doc_strides, NULL},
954
+ { "hidden_dtype", (getter)ndtype_hidden_dtype, NULL, doc_strides, NULL},
955
+ {NULL}
956
+ };
957
+
958
+ static PyMethodDef ndtype_methods [] =
959
+ {
960
+ /* Boolean functions */
961
+ { "isoptional", (PyCFunction)ndtype_ndt_is_optional, METH_NOARGS, doc_isoptional },
962
+ { "isabstract", (PyCFunction)ndtype_ndt_is_abstract, METH_NOARGS, doc_isabstract },
963
+ { "isconcrete", (PyCFunction)ndtype_ndt_is_concrete, METH_NOARGS, doc_isconcrete },
964
+ { "isscalar", (PyCFunction)ndtype_ndt_is_scalar, METH_NOARGS, doc_isscalar },
965
+ { "issigned", (PyCFunction)ndtype_ndt_is_signed, METH_NOARGS, doc_issigned },
966
+ { "isunsigned", (PyCFunction)ndtype_ndt_is_unsigned, METH_NOARGS, doc_isunsigned },
967
+ { "isfloat", (PyCFunction)ndtype_ndt_is_float, METH_NOARGS, doc_isfloat },
968
+ { "iscomplex", (PyCFunction)ndtype_ndt_is_complex, METH_NOARGS, doc_iscomplex },
969
+
970
+ /* Boolean functions on array types */
971
+ { "is_c_contiguous", (PyCFunction)ndtype_ndt_is_c_contiguous, METH_NOARGS, doc_is_c_contiguous },
972
+ { "is_f_contiguous", (PyCFunction)ndtype_ndt_is_f_contiguous, METH_NOARGS, doc_is_f_contiguous },
973
+
974
+ /* Binary functions */
975
+ { "match", (PyCFunction)ndtype_match, METH_O, doc_match },
976
+ { "apply", (PyCFunction)ndtype_apply, METH_O, "method likely to change" },
977
+
978
+ /* Other functions */
979
+ { "to_format", (PyCFunction)ndtype_to_format, METH_NOARGS, NULL },
980
+ { "to_nbformat", (PyCFunction)ndtype_to_nbformat, METH_NOARGS, NULL },
981
+ { "pformat", (PyCFunction)ndtype_pformat, METH_NOARGS, doc_pformat },
982
+ { "pprint", (PyCFunction)ndtype_pprint, METH_NOARGS, doc_pprint },
983
+ { "ast_repr", (PyCFunction)ndtype_ast_repr, METH_NOARGS, doc_ast_repr },
984
+ { "serialize", (PyCFunction)ndtype_serialize, METH_NOARGS, doc_serialize },
985
+
986
+ /* Class methods */
987
+ { "from_format", (PyCFunction)ndtype_from_format, METH_O|METH_CLASS, doc_from_format },
988
+ { "deserialize", (PyCFunction)ndtype_deserialize, METH_O|METH_CLASS, doc_deserialize },
989
+
990
+ /* Special methods */
991
+ { "__copy__", ndtype_copy, METH_NOARGS, NULL },
992
+ { "__deepcopy__", ndtype_copy, METH_O, NULL },
993
+ { "__reduce__", ndtype_reduce, METH_NOARGS, NULL },
994
+
995
+ { NULL, NULL, 1 }
996
+ };
997
+
998
+ static PyTypeObject Ndt_Type =
999
+ {
1000
+ PyVarObject_HEAD_INIT(NULL, 0)
1001
+ .tp_name = "ndtypes.ndt",
1002
+ .tp_basicsize = sizeof(NdtObject),
1003
+ .tp_dealloc = (destructor) ndtype_dealloc,
1004
+ .tp_repr = (reprfunc) ndtype_repr,
1005
+ .tp_hash = ndtype_hash,
1006
+ .tp_str = (reprfunc) ndtype_str,
1007
+ .tp_getattro = (getattrofunc) PyObject_GenericGetAttr,
1008
+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1009
+ .tp_traverse = (traverseproc)ndtype_traverse,
1010
+ .tp_richcompare = ndtype_richcompare,
1011
+ .tp_methods = ndtype_methods,
1012
+ .tp_getset = ndtype_getsets,
1013
+ .tp_alloc = PyType_GenericAlloc,
1014
+ .tp_new = ndtype_new,
1015
+ .tp_free = PyObject_GC_Del
1016
+ };
1017
+
1018
+
1019
+ /****************************************************************************/
1020
+ /* C-API */
1021
+ /****************************************************************************/
1022
+
1023
+ static void **ndtypes_api[NDTYPES_MAX_API];
1024
+
1025
+ static int
1026
+ Ndt_CheckExact(const PyObject *v)
1027
+ {
1028
+ return Py_TYPE(v) == &Ndt_Type;
1029
+ }
1030
+
1031
+ static int
1032
+ Ndt_Check(const PyObject *v)
1033
+ {
1034
+ return PyObject_TypeCheck(v, &Ndt_Type);
1035
+ }
1036
+
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
+ static PyObject *
1045
+ Ndt_SetError(ndt_context_t *ctx)
1046
+ {
1047
+ return seterr(ctx);
1048
+ }
1049
+
1050
+ 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)
1102
+ {
1103
+ PyObject *self;
1104
+
1105
+ self = ndtype_alloc(&Ndt_Type);
1106
+ if (self == NULL) {
1107
+ ndt_del(type);
1108
+ return NULL;
1109
+ }
1110
+
1111
+ NDT(self) = type;
1112
+ return self;
1113
+ }
1114
+
1115
+ static PyObject *
1116
+ Ndt_FromObject(PyObject *obj)
1117
+ {
1118
+ return ndtype_from_object(&Ndt_Type, obj);
1119
+ }
1120
+
1121
+ static PyObject *
1122
+ init_api(void)
1123
+ {
1124
+ ndtypes_api[Ndt_CheckExact_INDEX] = (void *)Ndt_CheckExact;
1125
+ ndtypes_api[Ndt_Check_INDEX] = (void *)Ndt_Check;
1126
+ ndtypes_api[CONST_NDT_INDEX] = (void *)CONST_NDT;
1127
+ 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
+ ndtypes_api[Ndt_FromType_INDEX] = (void *)Ndt_FromType;
1131
+ ndtypes_api[Ndt_FromObject_INDEX] = (void *)Ndt_FromObject;
1132
+
1133
+ return PyCapsule_New(ndtypes_api, "ndtypes._ndtypes._API", NULL);
1134
+ }
1135
+
1136
+
1137
+ /****************************************************************************/
1138
+ /* Module */
1139
+ /****************************************************************************/
1140
+
1141
+ static PyObject *
1142
+ ndtype_typedef(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1143
+ {
1144
+ static char *kwlist[] = {"name", "type", NULL};
1145
+ NDT_STATIC_CONTEXT(ctx);
1146
+ PyObject *name, *type;
1147
+ const char *cname, *ctype;
1148
+ ndt_t *t;
1149
+
1150
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &name, &type)) {
1151
+ return NULL;
1152
+ }
1153
+
1154
+ cname = PyUnicode_AsUTF8(name);
1155
+ if (cname == NULL) {
1156
+ return NULL;
1157
+ }
1158
+
1159
+ ctype = PyUnicode_AsUTF8(type);
1160
+ if (ctype == NULL) {
1161
+ return NULL;
1162
+ }
1163
+
1164
+ t = ndt_from_string(ctype, &ctx);
1165
+ if (t == NULL) {
1166
+ return seterr(&ctx);
1167
+ }
1168
+
1169
+ if (ndt_typedef(cname, t, NULL, &ctx) < 0) {
1170
+ return seterr(&ctx);
1171
+ }
1172
+
1173
+ Py_RETURN_NONE;
1174
+ }
1175
+
1176
+ static PyObject *
1177
+ ndtype_instantiate(PyObject *mod UNUSED, PyObject *args, PyObject *kwds)
1178
+ {
1179
+ static char *kwlist[] = {"name", "type", NULL};
1180
+ NDT_STATIC_CONTEXT(ctx);
1181
+ PyObject *name, *type;
1182
+ const char *cname;
1183
+ char *cp;
1184
+ ndt_t *t, *tp;
1185
+
1186
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &name, &type)) {
1187
+ return NULL;
1188
+ }
1189
+
1190
+ cname = PyUnicode_AsUTF8(name);
1191
+ if (cname == NULL) {
1192
+ return NULL;
1193
+ }
1194
+
1195
+ if (!Ndt_Check(type)) {
1196
+ PyErr_SetString(PyExc_TypeError, "type argument must be ndt");
1197
+ return NULL;
1198
+ }
1199
+
1200
+ cp = ndt_strdup(cname, &ctx);
1201
+ if (cp == NULL) {
1202
+ return seterr(&ctx);
1203
+ }
1204
+
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);
1212
+ if (t == NULL) {
1213
+ return seterr(&ctx);
1214
+ }
1215
+
1216
+ return Ndt_MoveSubtree(type, t);
1217
+ }
1218
+
1219
+ static PyMethodDef _ndtypes_methods [] =
1220
+ {
1221
+ { "typedef", (PyCFunction)ndtype_typedef, METH_VARARGS|METH_KEYWORDS, NULL},
1222
+ { "instantiate", (PyCFunction)ndtype_instantiate, METH_VARARGS|METH_KEYWORDS, NULL},
1223
+ { NULL, NULL, 1, NULL }
1224
+ };
1225
+
1226
+
1227
+ static struct PyModuleDef ndtypes_module = {
1228
+ PyModuleDef_HEAD_INIT, /* m_base */
1229
+ "_ndtypes", /* m_name */
1230
+ doc_module, /* m_doc */
1231
+ -1, /* m_size */
1232
+ _ndtypes_methods, /* m_methods */
1233
+ NULL, /* m_slots */
1234
+ NULL, /* m_traverse */
1235
+ NULL, /* m_clear */
1236
+ NULL /* m_free */
1237
+ };
1238
+
1239
+
1240
+ PyMODINIT_FUNC
1241
+ PyInit__ndtypes(void)
1242
+ {
1243
+ NDT_STATIC_CONTEXT(ctx);
1244
+ PyObject *m = NULL;
1245
+ PyObject *collections = NULL;
1246
+ PyObject *obj = NULL;
1247
+ static PyObject *capsule = NULL;
1248
+ static int initialized = 0;
1249
+
1250
+ if (!initialized) {
1251
+ capsule = init_api();
1252
+ if (capsule == NULL) {
1253
+ return NULL;
1254
+ }
1255
+ if (ndt_init(&ctx) < 0) {
1256
+ return seterr(&ctx);
1257
+ }
1258
+ initialized = 1;
1259
+ }
1260
+
1261
+ if (PyType_Ready(&ResourceBuffer_Type) < 0) {
1262
+ goto error;
1263
+ }
1264
+
1265
+ Ndt_Type.tp_base = &PyBaseObject_Type;
1266
+ if (PyType_Ready(&Ndt_Type) < 0) {
1267
+ goto error;
1268
+ }
1269
+
1270
+ /* ApplySpec */
1271
+ collections = PyImport_ImportModule("collections");
1272
+ if (collections == NULL) {
1273
+ goto error;
1274
+ }
1275
+
1276
+ ApplySpec = (PyTypeObject *)PyObject_CallMethod(collections,
1277
+ "namedtuple", "(ss)", "ApplySpec",
1278
+ "flags sig in_types in_broadcast out_types outer_dims");
1279
+ if (ApplySpec == NULL) {
1280
+ goto error;
1281
+ }
1282
+
1283
+ obj = PyUnicode_FromString("ndtypes");
1284
+ if (obj == NULL) {
1285
+ goto error;
1286
+ }
1287
+
1288
+ if (PyDict_SetItemString(ApplySpec->tp_dict, "__module__", obj) < 0) {
1289
+ goto error;
1290
+ }
1291
+ Py_CLEAR(obj);
1292
+
1293
+
1294
+ m = PyModule_Create(&ndtypes_module);
1295
+ if (m == NULL) {
1296
+ goto error;
1297
+ }
1298
+
1299
+ Deserialize = PyObject_GetAttrString((PyObject *)&Ndt_Type, "deserialize");
1300
+ if (Deserialize == NULL) {
1301
+ goto error;
1302
+ }
1303
+
1304
+ Py_INCREF(&Ndt_Type);
1305
+ if (PyModule_AddObject(m, "ndt", (PyObject *)&Ndt_Type) < 0) {
1306
+ goto error;
1307
+ }
1308
+
1309
+ Py_INCREF(ApplySpec);
1310
+ if (PyModule_AddObject(m, "ApplySpec", (PyObject *)ApplySpec) < 0) {
1311
+ goto error;
1312
+ }
1313
+
1314
+ if (PyModule_AddIntConstant(m, "MAX_DIM", NDT_MAX_DIM) < 0) {
1315
+ goto error;
1316
+ }
1317
+
1318
+ Py_INCREF(capsule);
1319
+ if (PyModule_AddObject(m, "_API", capsule) < 0) {
1320
+ goto error;
1321
+ }
1322
+
1323
+
1324
+ return m;
1325
+
1326
+
1327
+ error:
1328
+ Py_CLEAR(m);
1329
+ return NULL;
1330
+ }
1331
+
1332
+