ndtypes 0.2.0dev4

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