gumath 0.2.0dev5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +61 -0
  3. data/Gemfile +5 -0
  4. data/History.md +0 -0
  5. data/README.md +5 -0
  6. data/Rakefile +105 -0
  7. data/ext/ruby_gumath/examples.c +126 -0
  8. data/ext/ruby_gumath/extconf.rb +97 -0
  9. data/ext/ruby_gumath/functions.c +106 -0
  10. data/ext/ruby_gumath/gufunc_object.c +79 -0
  11. data/ext/ruby_gumath/gufunc_object.h +55 -0
  12. data/ext/ruby_gumath/gumath/AUTHORS.txt +5 -0
  13. data/ext/ruby_gumath/gumath/INSTALL.txt +42 -0
  14. data/ext/ruby_gumath/gumath/LICENSE.txt +29 -0
  15. data/ext/ruby_gumath/gumath/MANIFEST.in +3 -0
  16. data/ext/ruby_gumath/gumath/Makefile.in +62 -0
  17. data/ext/ruby_gumath/gumath/README.rst +20 -0
  18. data/ext/ruby_gumath/gumath/config.guess +1530 -0
  19. data/ext/ruby_gumath/gumath/config.h.in +52 -0
  20. data/ext/ruby_gumath/gumath/config.sub +1782 -0
  21. data/ext/ruby_gumath/gumath/configure +5049 -0
  22. data/ext/ruby_gumath/gumath/configure.ac +167 -0
  23. data/ext/ruby_gumath/gumath/doc/_static/copybutton.js +66 -0
  24. data/ext/ruby_gumath/gumath/doc/conf.py +26 -0
  25. data/ext/ruby_gumath/gumath/doc/gumath/functions.rst +62 -0
  26. data/ext/ruby_gumath/gumath/doc/gumath/index.rst +26 -0
  27. data/ext/ruby_gumath/gumath/doc/index.rst +45 -0
  28. data/ext/ruby_gumath/gumath/doc/libgumath/data-structures.rst +130 -0
  29. data/ext/ruby_gumath/gumath/doc/libgumath/functions.rst +78 -0
  30. data/ext/ruby_gumath/gumath/doc/libgumath/index.rst +25 -0
  31. data/ext/ruby_gumath/gumath/doc/libgumath/kernels.rst +41 -0
  32. data/ext/ruby_gumath/gumath/doc/releases/index.rst +11 -0
  33. data/ext/ruby_gumath/gumath/install-sh +527 -0
  34. data/ext/ruby_gumath/gumath/libgumath/Makefile.in +170 -0
  35. data/ext/ruby_gumath/gumath/libgumath/Makefile.vc +160 -0
  36. data/ext/ruby_gumath/gumath/libgumath/apply.c +201 -0
  37. data/ext/ruby_gumath/gumath/libgumath/extending/bfloat16.c +130 -0
  38. data/ext/ruby_gumath/gumath/libgumath/extending/examples.c +176 -0
  39. data/ext/ruby_gumath/gumath/libgumath/extending/graph.c +393 -0
  40. data/ext/ruby_gumath/gumath/libgumath/extending/pdist.c +140 -0
  41. data/ext/ruby_gumath/gumath/libgumath/extending/quaternion.c +156 -0
  42. data/ext/ruby_gumath/gumath/libgumath/func.c +177 -0
  43. data/ext/ruby_gumath/gumath/libgumath/gumath.h +205 -0
  44. data/ext/ruby_gumath/gumath/libgumath/kernels/binary.c +547 -0
  45. data/ext/ruby_gumath/gumath/libgumath/kernels/unary.c +449 -0
  46. data/ext/ruby_gumath/gumath/libgumath/nploops.c +219 -0
  47. data/ext/ruby_gumath/gumath/libgumath/tbl.c +223 -0
  48. data/ext/ruby_gumath/gumath/libgumath/thread.c +175 -0
  49. data/ext/ruby_gumath/gumath/libgumath/xndloops.c +130 -0
  50. data/ext/ruby_gumath/gumath/python/extending.py +24 -0
  51. data/ext/ruby_gumath/gumath/python/gumath/__init__.py +74 -0
  52. data/ext/ruby_gumath/gumath/python/gumath/_gumath.c +577 -0
  53. data/ext/ruby_gumath/gumath/python/gumath/examples.c +93 -0
  54. data/ext/ruby_gumath/gumath/python/gumath/functions.c +77 -0
  55. data/ext/ruby_gumath/gumath/python/gumath/pygumath.h +95 -0
  56. data/ext/ruby_gumath/gumath/python/test_gumath.py +405 -0
  57. data/ext/ruby_gumath/gumath/setup.py +298 -0
  58. data/ext/ruby_gumath/gumath/vcbuild/INSTALL.txt +36 -0
  59. data/ext/ruby_gumath/gumath/vcbuild/vcbuild32.bat +21 -0
  60. data/ext/ruby_gumath/gumath/vcbuild/vcbuild64.bat +21 -0
  61. data/ext/ruby_gumath/gumath/vcbuild/vcclean.bat +10 -0
  62. data/ext/ruby_gumath/gumath/vcbuild/vcdistclean.bat +11 -0
  63. data/ext/ruby_gumath/include/gumath.h +205 -0
  64. data/ext/ruby_gumath/include/ruby_gumath.h +41 -0
  65. data/ext/ruby_gumath/lib/libgumath.a +0 -0
  66. data/ext/ruby_gumath/lib/libgumath.so +1 -0
  67. data/ext/ruby_gumath/lib/libgumath.so.0 +1 -0
  68. data/ext/ruby_gumath/lib/libgumath.so.0.2.0dev3 +0 -0
  69. data/ext/ruby_gumath/ruby_gumath.c +295 -0
  70. data/ext/ruby_gumath/ruby_gumath.h +41 -0
  71. data/ext/ruby_gumath/ruby_gumath_internal.h +45 -0
  72. data/ext/ruby_gumath/util.c +68 -0
  73. data/ext/ruby_gumath/util.h +48 -0
  74. data/gumath.gemspec +47 -0
  75. data/lib/gumath.rb +7 -0
  76. data/lib/gumath/version.rb +5 -0
  77. data/lib/ruby_gumath.so +0 -0
  78. metadata +206 -0
@@ -0,0 +1,223 @@
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 <stdio.h>
35
+ #include <limits.h>
36
+ #include <stddef.h>
37
+ #include "gumath.h"
38
+
39
+
40
+ /*****************************************************************************/
41
+ /* Charmap */
42
+ /*****************************************************************************/
43
+
44
+ #define ALPHABET_LEN 64
45
+
46
+ static int code[UCHAR_MAX+1];
47
+ static unsigned char alpha[ALPHABET_LEN+1] =
48
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
49
+
50
+ static void
51
+ init_charmap(void)
52
+ {
53
+ int i;
54
+
55
+ for (i = 0; i < UCHAR_MAX+1; i++) {
56
+ code[i] = UCHAR_MAX;
57
+ }
58
+
59
+ for (i = 0; i < ALPHABET_LEN; i++) {
60
+ code[alpha[i]] = i;
61
+ }
62
+ }
63
+
64
+
65
+ /*****************************************************************************/
66
+ /* Function tables */
67
+ /*****************************************************************************/
68
+
69
+ /* Function table */
70
+ struct _gm_tbl {
71
+ gm_func_t *value;
72
+ gm_tbl_t *next[];
73
+ };
74
+
75
+ gm_tbl_t *
76
+ gm_tbl_new(ndt_context_t *ctx)
77
+ {
78
+ gm_tbl_t *t;
79
+ int i;
80
+
81
+ t = ndt_alloc_size(offsetof(gm_tbl_t, next) + ALPHABET_LEN * (sizeof t));
82
+ if (t == NULL) {
83
+ return ndt_memory_error(ctx);
84
+ }
85
+
86
+ t->value = NULL;
87
+
88
+ for (i = 0; i < ALPHABET_LEN; i++) {
89
+ t->next[i] = NULL;
90
+ }
91
+
92
+ return t;
93
+ }
94
+
95
+ void
96
+ gm_tbl_del(gm_tbl_t *t)
97
+ {
98
+ int i;
99
+
100
+ if (t == NULL) {
101
+ return;
102
+ }
103
+
104
+ gm_func_del(t->value);
105
+
106
+ for (i = 0; i < ALPHABET_LEN; i++) {
107
+ gm_tbl_del(t->next[i]);
108
+ }
109
+
110
+ ndt_free(t);
111
+ }
112
+
113
+ int
114
+ gm_tbl_add(gm_tbl_t *tbl, const char *key, gm_func_t *value, ndt_context_t *ctx)
115
+ {
116
+ gm_tbl_t *t = tbl;
117
+ const unsigned char *cp;
118
+ int i;
119
+
120
+ for (cp = (const unsigned char *)key; *cp != '\0'; cp++) {
121
+ i = code[*cp];
122
+ if (i == UCHAR_MAX) {
123
+ ndt_err_format(ctx, NDT_ValueError,
124
+ "invalid character in function name: '%c'", *cp);
125
+ gm_func_del(value);
126
+ return -1;
127
+ }
128
+
129
+ if (t->next[i] == NULL) {
130
+ gm_tbl_t *u = gm_tbl_new(ctx);
131
+ if (u == NULL) {
132
+ gm_func_del(value);
133
+ return -1;
134
+ }
135
+ t->next[i] = u;
136
+ t = u;
137
+ }
138
+ else {
139
+ t = t->next[i];
140
+ }
141
+ }
142
+
143
+ if (t->value) {
144
+ ndt_err_format(ctx, NDT_ValueError, "duplicate function name '%s'", key);
145
+ gm_func_del(value);
146
+ return -1;
147
+ }
148
+
149
+ t->value = value;
150
+ return 0;
151
+ }
152
+
153
+ gm_func_t *
154
+ gm_tbl_find(const gm_tbl_t *tbl, const char *key, ndt_context_t *ctx)
155
+ {
156
+ const gm_tbl_t *t = tbl;
157
+ const unsigned char *cp;
158
+ int i;
159
+
160
+ for (cp = (const unsigned char *)key; *cp != '\0'; cp++) {
161
+ i = code[*cp];
162
+ if (i == UCHAR_MAX) {
163
+ ndt_err_format(ctx, NDT_ValueError,
164
+ "invalid character in function name: '%c'", *cp);
165
+ return NULL;
166
+ }
167
+
168
+ if (t->next[i] == NULL) {
169
+ ndt_err_format(ctx, NDT_ValueError,
170
+ "cannot find function '%s'", key);
171
+ return NULL;
172
+ }
173
+ t = t->next[i];
174
+ }
175
+
176
+ if (t->value == NULL) {
177
+ ndt_err_format(ctx, NDT_RuntimeError,
178
+ "cannot find function '%s'", key);
179
+ return NULL;
180
+ }
181
+
182
+ return t->value;
183
+ }
184
+
185
+ int
186
+ gm_tbl_map(const gm_tbl_t *tbl, int (*f)(const gm_func_t *, void *), void *state)
187
+ {
188
+ const gm_tbl_t *t = tbl;
189
+ int i;
190
+
191
+ if (t->value) {
192
+ if (f(t->value, state) < 0) {
193
+ return -1;
194
+ }
195
+ }
196
+
197
+ for (i = 0; i < ALPHABET_LEN; i++) {
198
+ if (t->next[i] && gm_tbl_map(t->next[i], f, state) < 0) {
199
+ return -1;
200
+ }
201
+ }
202
+
203
+ return 0;
204
+ }
205
+
206
+
207
+ /*****************************************************************************/
208
+ /* Initialize global values */
209
+ /*****************************************************************************/
210
+
211
+ void
212
+ gm_init(void)
213
+ {
214
+ static bool initialized = false;
215
+
216
+ if (!initialized) {
217
+ init_charmap();
218
+ }
219
+ else {
220
+ fprintf(stderr, "gm_init: warning: ignoring attempt to initialize "
221
+ "libgumath a second time\n");
222
+ }
223
+ }
@@ -0,0 +1,175 @@
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 <stdlib.h>
35
+ #include <stdint.h>
36
+ #include <string.h>
37
+ #include <inttypes.h>
38
+ #include "ndtypes.h"
39
+ #include "xnd.h"
40
+ #include "gumath.h"
41
+ #include "config.h"
42
+
43
+
44
+ #ifdef HAVE_PTHREAD_H
45
+ #include <pthread.h>
46
+
47
+ struct thread_info {
48
+ pthread_t tid;
49
+ int tnum;
50
+ int nrows;
51
+ int ncols;
52
+ const gm_kernel_t *kernel;
53
+ xnd_t **slices;
54
+ int outer_dims;
55
+ ndt_context_t ctx;
56
+ };
57
+
58
+ static void
59
+ init_static_context(ndt_context_t *ctx)
60
+ {
61
+ static const ndt_context_t c = {
62
+ .flags=0,
63
+ .err=NDT_Success,
64
+ .msg=ConstMsg,
65
+ .ConstMsg="Success" };
66
+
67
+ *ctx = c;
68
+ }
69
+
70
+ static void
71
+ clear_all_slices(xnd_t *slices[], int *nslices, int stop)
72
+ {
73
+ for (int i = 0; i < stop; i++) {
74
+ for (int k = 0; k < nslices[i]; k++) {
75
+ ndt_del((ndt_t *)slices[i][k].type);
76
+ }
77
+ ndt_free(slices[i]);
78
+ }
79
+ }
80
+
81
+ static void *
82
+ apply_thread(void *arg)
83
+ {
84
+ struct thread_info *tinfo = arg;
85
+ ALLOCA(xnd_t, stack, tinfo->nrows);
86
+
87
+ for (int i = 0; i < tinfo->nrows; i++) {
88
+ stack[i] = tinfo->slices[i][tinfo->tnum];
89
+ }
90
+
91
+ gm_apply(tinfo->kernel, stack, tinfo->outer_dims, &tinfo->ctx);
92
+ return NULL;
93
+ }
94
+
95
+ int
96
+ gm_apply_thread(const gm_kernel_t *kernel, xnd_t stack[], int outer_dims,
97
+ uint32_t flags, const int64_t nthreads, ndt_context_t *ctx)
98
+ {
99
+ const int nrows = (int)kernel->set->sig->Function.nargs;
100
+ ALLOCA(xnd_t *, slices, nrows);
101
+ ALLOCA(int, nslices, nrows);
102
+ struct thread_info *tinfo;
103
+ int ncols, tnum;
104
+
105
+ if (nthreads <= 1 || nrows == 0 || outer_dims == 0 ||
106
+ !(flags & NDT_STRIDED)) {
107
+ return gm_apply(kernel, stack, outer_dims, ctx);
108
+ }
109
+
110
+ for (int i = 0; i < nrows; i++) {
111
+ int64_t ncols = nthreads;
112
+ slices[i] = xnd_split(&stack[i], &ncols, outer_dims, ctx);
113
+ if (ndt_err_occurred(ctx)) {
114
+ clear_all_slices(slices, nslices, i);
115
+ return -1;
116
+ }
117
+ nslices[i] = ncols;
118
+ }
119
+
120
+ ncols = nslices[0];
121
+ for (int i = 1; i < nrows; i++) {
122
+ if (nslices[i] != ncols) {
123
+ clear_all_slices(slices, nslices, nrows);
124
+ ndt_err_format(ctx, NDT_RuntimeError,
125
+ "equal subdivision in threaded apply loop failed");
126
+ return -1;
127
+ }
128
+ }
129
+
130
+ tinfo = ndt_calloc(nthreads, sizeof *tinfo);
131
+ if (tinfo == NULL) {
132
+ clear_all_slices(slices, nslices, nrows);
133
+ (void)ndt_memory_error(ctx);
134
+ return -1;
135
+ }
136
+
137
+ for (tnum = 0; tnum < ncols; tnum++) {
138
+ tinfo[tnum].tnum = tnum;
139
+ tinfo[tnum].kernel = kernel;
140
+ tinfo[tnum].nrows = nrows;
141
+ tinfo[tnum].ncols = ncols;
142
+ tinfo[tnum].slices = slices;
143
+ tinfo[tnum].outer_dims = outer_dims;
144
+ init_static_context(&tinfo[tnum].ctx);
145
+
146
+ int ret = pthread_create(&tinfo[tnum].tid, NULL, &apply_thread,
147
+ &tinfo[tnum]);
148
+ if (ret != 0) {
149
+ clear_all_slices(slices, nslices, nrows);
150
+ ndt_err_format(ctx, NDT_RuntimeError, "could not create thread");
151
+ return -1;
152
+ }
153
+ }
154
+
155
+ int ret = 0;
156
+ for (tnum = 0; tnum < ncols; tnum++) {
157
+ ret |= pthread_join(tinfo[tnum].tid, NULL);
158
+ if (ndt_err_occurred(&tinfo[tnum].ctx)) {
159
+ if (!ndt_err_occurred(ctx)) {
160
+ ndt_err_format(ctx, tinfo[tnum].ctx.err,
161
+ ndt_context_msg(&tinfo[tnum].ctx));
162
+ }
163
+ ndt_err_clear(&tinfo[tnum].ctx);
164
+ }
165
+ }
166
+
167
+ if (ret != 0 && !ndt_err_occurred(ctx)) {
168
+ ndt_err_format(ctx, NDT_RuntimeError, "error in thread");
169
+ }
170
+
171
+ clear_all_slices(slices, nslices, nrows);
172
+
173
+ return ndt_err_occurred(ctx) ? -1 : 0;
174
+ }
175
+ #endif
@@ -0,0 +1,130 @@
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 <stdlib.h>
35
+ #include <stdint.h>
36
+ #include <string.h>
37
+ #include <inttypes.h>
38
+ #include "ndtypes.h"
39
+ #include "xnd.h"
40
+ #include "gumath.h"
41
+
42
+
43
+ int
44
+ gm_xnd_map(const gm_xnd_kernel_t f, xnd_t stack[], const int nargs,
45
+ const int outer_dims, ndt_context_t *ctx)
46
+ {
47
+ ALLOCA(xnd_t, next, nargs);
48
+ const ndt_t *t;
49
+
50
+ if (outer_dims == 0 || nargs == 0) {
51
+ return f(stack, ctx);
52
+ }
53
+
54
+ t = stack[0].type;
55
+
56
+ switch (t->tag) {
57
+ case FixedDim: {
58
+ const int64_t shape = t->FixedDim.shape;
59
+
60
+ for (int k = 1; k < nargs; k++) {
61
+ const ndt_t *u = stack[k].type;
62
+
63
+ if (u->tag != FixedDim || u->FixedDim.shape != shape) {
64
+ ndt_err_format(ctx, NDT_RuntimeError,
65
+ "type or shape mismatch in outer dimensions");
66
+ return -1;
67
+ }
68
+ }
69
+
70
+ for (int64_t i = 0; i < shape; i++) {
71
+ for (int k = 0; k < nargs; k++) {
72
+ next[k] = xnd_fixed_dim_next(&stack[k], i);
73
+ }
74
+
75
+ if (gm_xnd_map(f, next, nargs, outer_dims-1, ctx) < 0) {
76
+ return -1;
77
+ }
78
+ }
79
+
80
+ return 0;
81
+ }
82
+
83
+ case VarDim: {
84
+ ALLOCA(int64_t, start, nargs);
85
+ ALLOCA(int64_t, step, nargs);
86
+ const int64_t shape = ndt_var_indices(&start[0], &step[0], t,
87
+ stack[0].index, ctx);
88
+ if (shape < 0) {
89
+ return -1;
90
+ }
91
+
92
+ for (int k = 1; k < nargs; k++) {
93
+ const ndt_t *u = stack[k].type;
94
+
95
+ if (u->tag != VarDim) {
96
+ ndt_err_format(ctx, NDT_RuntimeError,
97
+ "type mismatch in outer dimensions");
98
+ return -1;
99
+ }
100
+
101
+ int64_t n = ndt_var_indices(&start[k], &step[k], u, stack[k].index, ctx);
102
+ if (n < 0) {
103
+ return -1;
104
+ }
105
+
106
+ if (n != shape) {
107
+ ndt_err_format(ctx, NDT_RuntimeError,
108
+ "shape mismatch in outer dimensions");
109
+ return -1;
110
+ }
111
+ }
112
+
113
+ for (int64_t i = 0; i < shape; i++) {
114
+ for (int k = 0; k < nargs; k++) {
115
+ next[k] = xnd_var_dim_next(&stack[k], start[k], step[k], i);
116
+ }
117
+
118
+ if (gm_xnd_map(f, next, nargs, outer_dims-1, ctx) < 0) {
119
+ return -1;
120
+ }
121
+ }
122
+
123
+ return 0;
124
+ }
125
+
126
+ default:
127
+ ndt_err_format(ctx, NDT_NotImplementedError, "unsupported type");
128
+ return -1;
129
+ }
130
+ }