xnd 0.2.0dev3

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +42 -0
  3. data/Gemfile +3 -0
  4. data/History.md +0 -0
  5. data/README.md +7 -0
  6. data/Rakefile +135 -0
  7. data/ext/ruby_xnd/extconf.rb +70 -0
  8. data/ext/ruby_xnd/float_pack_unpack.c +277 -0
  9. data/ext/ruby_xnd/float_pack_unpack.h +39 -0
  10. data/ext/ruby_xnd/gc_guard.c +36 -0
  11. data/ext/ruby_xnd/gc_guard.h +12 -0
  12. data/ext/ruby_xnd/include/xnd.h +449 -0
  13. data/ext/ruby_xnd/lib/libxnd.a +0 -0
  14. data/ext/ruby_xnd/lib/libxnd.so +1 -0
  15. data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
  16. data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
  17. data/ext/ruby_xnd/memory_block_object.c +32 -0
  18. data/ext/ruby_xnd/memory_block_object.h +33 -0
  19. data/ext/ruby_xnd/ruby_xnd.c +1953 -0
  20. data/ext/ruby_xnd/ruby_xnd.h +61 -0
  21. data/ext/ruby_xnd/ruby_xnd_internal.h +85 -0
  22. data/ext/ruby_xnd/util.h +170 -0
  23. data/ext/ruby_xnd/xnd/AUTHORS.txt +5 -0
  24. data/ext/ruby_xnd/xnd/INSTALL.txt +134 -0
  25. data/ext/ruby_xnd/xnd/LICENSE.txt +29 -0
  26. data/ext/ruby_xnd/xnd/MANIFEST.in +3 -0
  27. data/ext/ruby_xnd/xnd/Makefile.in +80 -0
  28. data/ext/ruby_xnd/xnd/README.rst +44 -0
  29. data/ext/ruby_xnd/xnd/config.guess +1530 -0
  30. data/ext/ruby_xnd/xnd/config.h.in +22 -0
  31. data/ext/ruby_xnd/xnd/config.sub +1782 -0
  32. data/ext/ruby_xnd/xnd/configure +4867 -0
  33. data/ext/ruby_xnd/xnd/configure.ac +164 -0
  34. data/ext/ruby_xnd/xnd/doc/Makefile +14 -0
  35. data/ext/ruby_xnd/xnd/doc/_static/copybutton.js +66 -0
  36. data/ext/ruby_xnd/xnd/doc/conf.py +26 -0
  37. data/ext/ruby_xnd/xnd/doc/index.rst +44 -0
  38. data/ext/ruby_xnd/xnd/doc/libxnd/data-structures.rst +186 -0
  39. data/ext/ruby_xnd/xnd/doc/libxnd/functions.rst +148 -0
  40. data/ext/ruby_xnd/xnd/doc/libxnd/index.rst +25 -0
  41. data/ext/ruby_xnd/xnd/doc/releases/index.rst +34 -0
  42. data/ext/ruby_xnd/xnd/doc/xnd/align-pack.rst +96 -0
  43. data/ext/ruby_xnd/xnd/doc/xnd/buffer-protocol.rst +42 -0
  44. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +30 -0
  45. data/ext/ruby_xnd/xnd/doc/xnd/quickstart.rst +62 -0
  46. data/ext/ruby_xnd/xnd/doc/xnd/types.rst +674 -0
  47. data/ext/ruby_xnd/xnd/install-sh +527 -0
  48. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +102 -0
  49. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +112 -0
  50. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +345 -0
  51. data/ext/ruby_xnd/xnd/libxnd/contrib.h +313 -0
  52. data/ext/ruby_xnd/xnd/libxnd/copy.c +944 -0
  53. data/ext/ruby_xnd/xnd/libxnd/equal.c +1216 -0
  54. data/ext/ruby_xnd/xnd/libxnd/inline.h +154 -0
  55. data/ext/ruby_xnd/xnd/libxnd/overflow.h +147 -0
  56. data/ext/ruby_xnd/xnd/libxnd/split.c +286 -0
  57. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.in +39 -0
  58. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.vc +44 -0
  59. data/ext/ruby_xnd/xnd/libxnd/tests/README.txt +2 -0
  60. data/ext/ruby_xnd/xnd/libxnd/tests/runtest.c +101 -0
  61. data/ext/ruby_xnd/xnd/libxnd/tests/test.h +48 -0
  62. data/ext/ruby_xnd/xnd/libxnd/tests/test_fixed.c +108 -0
  63. data/ext/ruby_xnd/xnd/libxnd/xnd.c +1304 -0
  64. data/ext/ruby_xnd/xnd/libxnd/xnd.h +449 -0
  65. data/ext/ruby_xnd/xnd/python/test_xnd.py +3144 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +290 -0
  67. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +2822 -0
  68. data/ext/ruby_xnd/xnd/python/xnd/contrib/pretty.py +850 -0
  69. data/ext/ruby_xnd/xnd/python/xnd/docstrings.h +129 -0
  70. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +200 -0
  71. data/ext/ruby_xnd/xnd/python/xnd/util.h +182 -0
  72. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +1121 -0
  73. data/ext/ruby_xnd/xnd/python/xnd_support.py +106 -0
  74. data/ext/ruby_xnd/xnd/setup.py +303 -0
  75. data/ext/ruby_xnd/xnd/vcbuild/INSTALL.txt +42 -0
  76. data/ext/ruby_xnd/xnd/vcbuild/runtest32.bat +16 -0
  77. data/ext/ruby_xnd/xnd/vcbuild/runtest64.bat +14 -0
  78. data/ext/ruby_xnd/xnd/vcbuild/vcbuild32.bat +29 -0
  79. data/ext/ruby_xnd/xnd/vcbuild/vcbuild64.bat +29 -0
  80. data/ext/ruby_xnd/xnd/vcbuild/vcclean.bat +13 -0
  81. data/ext/ruby_xnd/xnd/vcbuild/vcdistclean.bat +14 -0
  82. data/lib/ruby_xnd.so +0 -0
  83. data/lib/xnd.rb +306 -0
  84. data/lib/xnd/monkeys.rb +29 -0
  85. data/lib/xnd/version.rb +6 -0
  86. data/spec/debug_spec.rb +9 -0
  87. data/spec/gc_guard_spec.rb +10 -0
  88. data/spec/leakcheck.rb +9 -0
  89. data/spec/spec_helper.rb +877 -0
  90. data/spec/type_inference_spec.rb +81 -0
  91. data/spec/xnd_spec.rb +2921 -0
  92. data/xnd.gemspec +47 -0
  93. metadata +215 -0
@@ -0,0 +1,39 @@
1
+
2
+ SRCDIR = ..
3
+
4
+ CC = @CC@
5
+ LIBSTATIC = @LIBSTATIC@
6
+ LIBSHARED = @LIBSHARED@
7
+
8
+ INCLUDES = @CONFIGURE_INCLUDES_TEST@
9
+ LIBS = @CONFIGURE_LIBS_TEST@
10
+
11
+ CONFIGURE_CFLAGS = @CONFIGURE_CFLAGS@
12
+ XND_CFLAGS = $(strip $(CONFIGURE_CFLAGS) $(CFLAGS))
13
+
14
+
15
+ default: runtest runtest_shared
16
+
17
+
18
+ runtest:\
19
+ Makefile runtest.c test_fixed.c test.h $(SRCDIR)/xnd.h $(SRCDIR)/$(LIBSTATIC)
20
+ $(CC) -I$(SRCDIR) -I$(INCLUDES) $(XND_CFLAGS) \
21
+ -o runtest runtest.c test_fixed.c $(SRCDIR)/libxnd.a \
22
+ $(LIBS)/libndtypes.a
23
+
24
+ runtest_shared:\
25
+ Makefile runtest.c test_fixed.c test.h $(SRCDIR)/xnd.h $(SRCDIR)/$(LIBSHARED)
26
+ $(CC) -I$(SRCDIR) -I$(INCLUDES) -L$(SRCDIR) -L$(LIBS) \
27
+ $(XND_CFLAGS) -o runtest_shared runtest.c test_fixed.c -lxnd -lndtypes
28
+
29
+
30
+ FORCE:
31
+
32
+ clean: FORCE
33
+ rm -f *.o *.gch *.gcda *.gcno *.gcov *.dyn *.dpi *.lock
34
+ rm -f runtest runtest_shared
35
+
36
+ distclean: clean
37
+ rm -rf Makefile
38
+
39
+
@@ -0,0 +1,44 @@
1
+
2
+ SRCDIR = ..
3
+
4
+ LIBSTATIC = libxnd-0.2.0dev3.lib
5
+ LIBSHARED = libxnd-0.2.0dev3.dll.lib
6
+ LIBNDTYPESSTATIC = libndtypes-0.2.0dev3.lib
7
+ LIBNDTYPESIMPORT = libndtypes-0.2.0dev3.dll.lib
8
+
9
+ !ifndef LIBNDTYPESINCLUDE
10
+ LIBNDTYPESINCLUDE = ..\..\ndtypes\libndtypes
11
+ !endif
12
+
13
+ !ifndef LIBNDTYPESDIR
14
+ LIBNDTYPESDIR = ..\..\ndtypes\libndtypes
15
+ !endif
16
+
17
+
18
+ CC = cl.exe
19
+ CFLAGS = /nologo /MT /Ox /GS /EHsc
20
+ CFLAGS_SHARED = /nologo /DXND_IMPORT /MD /Ox /GS /EHsc
21
+
22
+ default: runtest runtest_shared
23
+
24
+
25
+ runtest:\
26
+ Makefile runtest.c test_fixed.c test.h $(SRCDIR)\xnd.h $(SRCDIR)\$(LIBSTATIC)
27
+ $(CC) "-I$(SRCDIR)" "-I$(LIBNDTYPESINCLUDE)" $(CFLAGS) /Feruntest runtest.c \
28
+ test_fixed.c $(SRCDIR)\$(LIBSTATIC) /link "/LIBPATH:$(LIBNDTYPESDIR)" $(LIBNDTYPESSTATIC)
29
+
30
+ runtest_shared:\
31
+ Makefile runtest.c test_fixed.c test.h $(SRCDIR)\xnd.h $(SRCDIR)\$(LIBSHARED)
32
+ $(CC) "-I$(SRCDIR)" "-I$(LIBNDTYPESINCLUDE)" $(CFLAGS_SHARED) /Feruntest_shared \
33
+ runtest.c test_fixed.c $(SRCDIR)\$(LIBSHARED) /link "/LIBPATH:$(LIBNDTYPESDIR)" $(LIBNDTYPESIMPORT)
34
+
35
+
36
+ FORCE:
37
+
38
+ clean: FORCE
39
+ del /q /f *.exe *.obj *.lib *.dll *.exp *.manifest 2>NUL
40
+
41
+ distclean: clean
42
+ del /q /f Makefile 2>NUL
43
+
44
+
@@ -0,0 +1,2 @@
1
+
2
+ The library is tested extensively through the unit tests of the Python bindings.
@@ -0,0 +1,101 @@
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 <stdlib.h>
36
+ #include <string.h>
37
+ #include <assert.h>
38
+ #include "ndtypes.h"
39
+ #include "test.h"
40
+
41
+
42
+ static int
43
+ init_tests(void)
44
+ {
45
+ ndt_context_t *ctx;
46
+
47
+ ctx = ndt_context_new();
48
+ if (ctx == NULL) {
49
+ fprintf(stderr, "error: out of memory");
50
+ return -1;
51
+ }
52
+
53
+ if (ndt_init(ctx) < 0) {
54
+ ndt_err_fprint(stderr, ctx);
55
+ ndt_context_del(ctx);
56
+ return -1;
57
+ }
58
+
59
+ if (xnd_init_float(ctx) < 0) {
60
+ ndt_err_fprint(stderr, ctx);
61
+ ndt_context_del(ctx);
62
+ return -1;
63
+ }
64
+
65
+ ndt_context_del(ctx);
66
+ return 0;
67
+ }
68
+
69
+ static int (*tests[])(void) = {
70
+ test_fixed,
71
+ NULL
72
+ };
73
+
74
+ int
75
+ main(void)
76
+ {
77
+ int (**f)(void);
78
+ int success = 0;
79
+ int fail = 0;
80
+
81
+ if (init_tests() < 0) {
82
+ return 1;
83
+ }
84
+
85
+ for (f = tests; *f != NULL; f++) {
86
+ if ((*f)() < 0)
87
+ fail++;
88
+ else
89
+ success++;
90
+ }
91
+
92
+ if (fail) {
93
+ fprintf(stderr, "\nFAIL (failures=%d)\n", fail);
94
+ }
95
+ else {
96
+ fprintf(stderr, "\n%d tests OK.\n", success);
97
+ }
98
+
99
+ ndt_finalize();
100
+ return fail ? 1 : 0;
101
+ }
@@ -0,0 +1,48 @@
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
+ #ifndef TEST_H
35
+ #define TEST_H
36
+
37
+
38
+ #include "ndtypes.h"
39
+ #include "xnd.h"
40
+
41
+
42
+ #define ARRAY_SIZE(a) ((int)(sizeof(a)/sizeof(a[0])))
43
+
44
+
45
+ int test_fixed(void);
46
+
47
+
48
+ #endif /* TEST_H */
@@ -0,0 +1,108 @@
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 <assert.h>
37
+ #include "ndtypes.h"
38
+ #include "test.h"
39
+
40
+
41
+ int
42
+ test_fixed(void)
43
+ {
44
+ ndt_context_t *ctx;
45
+ xnd_master_t *x;
46
+ xnd_t view;
47
+ uint16_t *ptr;
48
+ int ret = 0;
49
+ int i, j, k, l;
50
+ int64_t indices[3];
51
+
52
+ /* a1 = [[[0, 1], [2, 3]], [[4, 5], [6, 7]], [[8, 9], [10, 11]]] */
53
+ const char *s = "3 * 2 * 2 * uint16";
54
+ uint16_t data[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
55
+
56
+
57
+ ctx = ndt_context_new();
58
+ if (ctx == NULL) {
59
+ fprintf(stderr, "out of memory\n");
60
+ return 1;
61
+ }
62
+
63
+
64
+ /***** Type with fixed dimensions *****/
65
+ x = xnd_empty_from_string(s, XND_OWN_ALL, ctx);
66
+ if (x == NULL) {
67
+ goto error;
68
+ }
69
+
70
+ ptr = (uint16_t *)x->master.ptr;
71
+ for (i = 0; i < ARRAY_SIZE(data); i++) {
72
+ ptr[i] = data[i];
73
+ }
74
+
75
+ for (i = 0; i < 3; i++) {
76
+ for (j = 0; j < 2; j++) {
77
+ for (k = 0; k < 2; k++) {
78
+ indices[0] = i; indices[1] = j; indices[2] = k;
79
+ l = i * 4 + j * 2 + k;
80
+ view = xnd_subtree_index(&x->master, indices, 3, ctx);
81
+ if (view.ptr == NULL) {
82
+ goto error;
83
+ }
84
+ assert(view.type->tag == Uint16);
85
+ if (*(uint16_t *)(view.ptr) != data[l]) {
86
+ ndt_err_format(ctx, NDT_RuntimeError, "unexpected value");
87
+ goto error;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+
94
+ fprintf(stderr, "test_fixed (1 test case)\n");
95
+
96
+
97
+ out:
98
+ xnd_del(x);
99
+ ndt_context_del(ctx);
100
+ return ret;
101
+
102
+ error:
103
+ ret = -1;
104
+ ndt_err_fprint(stderr, ctx);
105
+ goto out;
106
+ }
107
+
108
+
@@ -0,0 +1,1304 @@
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 <inttypes.h>
37
+ #include <string.h>
38
+ #include <assert.h>
39
+ #include "ndtypes.h"
40
+ #include "xnd.h"
41
+ #include "inline.h"
42
+ #include "contrib.h"
43
+
44
+
45
+ static int xnd_init(xnd_t * const x, const uint32_t flags, ndt_context_t *ctx);
46
+ static void xnd_clear(xnd_t * const x, const uint32_t flags);
47
+
48
+
49
+ /*****************************************************************************/
50
+ /* Error handling */
51
+ /*****************************************************************************/
52
+
53
+ /* error return value */
54
+ const xnd_t xnd_error = {
55
+ .bitmap = {.data=NULL, .size=0, .next=NULL},
56
+ .index = 0,
57
+ .type = NULL,
58
+ .ptr = NULL
59
+ };
60
+
61
+ int
62
+ xnd_err_occurred(const xnd_t *x)
63
+ {
64
+ return x->ptr == NULL;
65
+ }
66
+
67
+
68
+ /*****************************************************************************/
69
+ /* Create and initialize a new master buffer */
70
+ /*****************************************************************************/
71
+
72
+ static bool
73
+ requires_init(const ndt_t * const t)
74
+ {
75
+ const ndt_t *dtype = ndt_dtype(t);
76
+
77
+ switch (dtype->tag) {
78
+ case Categorical:
79
+ case Bool:
80
+ case Int8: case Int16: case Int32: case Int64:
81
+ case Uint8: case Uint16: case Uint32: case Uint64:
82
+ case Float16: case Float32: case Float64:
83
+ case Complex32: case Complex64: case Complex128:
84
+ case FixedString: case FixedBytes:
85
+ case String: case Bytes:
86
+ return false;
87
+ default:
88
+ return true;
89
+ }
90
+ }
91
+
92
+ /* Create and initialize memory with type 't'. */
93
+ static char *
94
+ xnd_new(const ndt_t * const t, const uint32_t flags, ndt_context_t *ctx)
95
+ {
96
+ xnd_t x;
97
+
98
+ if (ndt_is_abstract(t)) {
99
+ ndt_err_format(ctx, NDT_ValueError,
100
+ "cannot create xnd container from abstract type");
101
+ return NULL;
102
+ }
103
+
104
+ x.index = 0;
105
+ x.type = t;
106
+
107
+ x.ptr = ndt_aligned_calloc(t->align, t->datasize);
108
+ if (x.ptr == NULL) {
109
+ ndt_memory_error(ctx);
110
+ return NULL;
111
+ }
112
+
113
+ if (requires_init(t) && xnd_init(&x, flags, ctx) < 0) {
114
+ ndt_aligned_free(x.ptr);
115
+ return NULL;
116
+ }
117
+
118
+ return x.ptr;
119
+ }
120
+
121
+ /*
122
+ * Initialize typed memory. If the XND_OWN_POINTERS flag is set, allocate
123
+ * memory for all ref subtypes and initialize that memory. Otherwise, set
124
+ * refs to NULL.
125
+ *
126
+ * Ref subtypes include any type of the form "Ref(t)".
127
+ *
128
+ * Never allocated are (sizes are not known):
129
+ * - "string" type (pointer to NUL-terminated UTF8 string)
130
+ * - data of the "bytes" type: {size: size_t, data: uint8_t *bytes}
131
+ *
132
+ * At all times the data pointers must be NULL or pointers to valid memory.
133
+ */
134
+ static int
135
+ xnd_init(xnd_t * const x, const uint32_t flags, ndt_context_t *ctx)
136
+ {
137
+ const ndt_t * const t = x->type;
138
+
139
+ if (ndt_is_abstract(t)) {
140
+ ndt_err_format(ctx, NDT_ValueError,
141
+ "cannot initialize concrete memory from abstract type");
142
+ return -1;
143
+ }
144
+
145
+ switch (t->tag) {
146
+ case FixedDim: {
147
+ int64_t i;
148
+
149
+ for (i = 0; i < t->FixedDim.shape; i++) {
150
+ xnd_t next = _fixed_dim_next(x, i);
151
+ if (xnd_init(&next, flags, ctx) < 0) {
152
+ return -1;
153
+ }
154
+ }
155
+
156
+ return 0;
157
+ }
158
+
159
+ case VarDim: {
160
+ int64_t start, step, shape;
161
+ int64_t i;
162
+
163
+ shape = ndt_var_indices(&start, &step, t, x->index, ctx);
164
+ if (shape < 0) {
165
+ return -1;
166
+ }
167
+
168
+ for (i = 0; i < shape; i++) {
169
+ xnd_t next = _var_dim_next(x, start, step, i);
170
+ if (xnd_init(&next, flags, ctx) < 0) {
171
+ return -1;
172
+ }
173
+ }
174
+
175
+ return 0;
176
+ }
177
+
178
+ case Tuple: {
179
+ for (int64_t i = 0; i < t->Tuple.shape; i++) {
180
+ xnd_t next = _tuple_next(x, i);
181
+ if (xnd_init(&next, flags, ctx) < 0) {
182
+ xnd_clear(&next, flags);
183
+ return -1;
184
+ }
185
+ }
186
+
187
+ return 0;
188
+ }
189
+
190
+ case Record: {
191
+ for (int64_t i = 0; i < t->Record.shape; i++) {
192
+ xnd_t next = _record_next(x, i);
193
+ if (xnd_init(&next, flags, ctx) < 0) {
194
+ xnd_clear(&next, flags);
195
+ return -1;
196
+ }
197
+ }
198
+
199
+ return 0;
200
+ }
201
+
202
+ /*
203
+ * Ref represents a pointer to an explicit type. If XND_OWN_POINTERS
204
+ * is set, allocate memory for that type and set the pointer.
205
+ */
206
+ case Ref: {
207
+ if (flags & XND_OWN_POINTERS) {
208
+ const ndt_t *u = t->Ref.type;
209
+ void *ref;
210
+
211
+ ref = ndt_aligned_calloc(u->align, u->datasize);
212
+ if (ref == NULL) {
213
+ ndt_err_format(ctx, NDT_MemoryError, "out of memory");
214
+ return -1;
215
+ }
216
+ XND_POINTER_DATA(x->ptr) = ref;
217
+
218
+ xnd_t next = _ref_next(x);
219
+ if (xnd_init(&next, flags, ctx) < 0) {
220
+ xnd_clear(&next, flags);
221
+ return -1;
222
+ }
223
+ }
224
+
225
+ return 0;
226
+ }
227
+
228
+ /* Constr is a named explicit type. */
229
+ case Constr: {
230
+ xnd_t next = _constr_next(x);
231
+ if (xnd_init(&next, flags, ctx) < 0) {
232
+ xnd_clear(&next, flags);
233
+ return -1;
234
+ }
235
+
236
+ return 0;
237
+ }
238
+
239
+ /* Nominal is a globally unique typedef. */
240
+ case Nominal: {
241
+ xnd_t next = _nominal_next(x);
242
+ if (xnd_init(&next, flags, ctx) < 0) {
243
+ xnd_clear(&next, flags);
244
+ return -1;
245
+ }
246
+
247
+ return 0;
248
+ }
249
+
250
+ /* Categorical is already initialized by calloc(). */
251
+ case Categorical:
252
+ return 0;
253
+
254
+ case Char:
255
+ ndt_err_format(ctx, NDT_NotImplementedError, "char not implemented");
256
+ return -1;
257
+
258
+ /* Primitive types are already initialized by calloc(). */
259
+ case Bool:
260
+ case Int8: case Int16: case Int32: case Int64:
261
+ case Uint8: case Uint16: case Uint32: case Uint64:
262
+ case Float16: case Float32: case Float64:
263
+ case Complex32: case Complex64: case Complex128:
264
+ case FixedString: case FixedBytes:
265
+ case String: case Bytes:
266
+ return 0;
267
+
268
+ /* NOT REACHED: intercepted by ndt_is_abstract(). */
269
+ case Module: case Function:
270
+ case AnyKind: case SymbolicDim: case EllipsisDim: case Typevar:
271
+ case ScalarKind: case SignedKind: case UnsignedKind: case FloatKind:
272
+ case ComplexKind: case FixedStringKind: case FixedBytesKind:
273
+ ndt_err_format(ctx, NDT_RuntimeError, "unexpected abstract type");
274
+ return -1;
275
+ }
276
+
277
+ /* NOT REACHED: tags should be exhaustive */
278
+ ndt_err_format(ctx, NDT_RuntimeError, "invalid type tag");
279
+ return -1;
280
+ }
281
+
282
+ /*
283
+ * Create a type from a string and return a new master buffer for that type.
284
+ * Any combination of flags that include XND_OWN_TYPE can be passed.
285
+ */
286
+ xnd_master_t *
287
+ xnd_empty_from_string(const char *s, uint32_t flags, ndt_context_t *ctx)
288
+ {
289
+ xnd_bitmap_t b = {.data=NULL, .size=0, .next=NULL};
290
+ xnd_master_t *x;
291
+ ndt_t *t;
292
+ char *ptr;
293
+
294
+ if (!(flags & XND_OWN_TYPE)) {
295
+ ndt_err_format(ctx, NDT_InvalidArgumentError,
296
+ "xnd_empty_from_string: XND_OWN_TYPE must be set");
297
+ return NULL;
298
+ }
299
+
300
+ x = ndt_alloc(1, sizeof *x);
301
+ if (x == NULL) {
302
+ return ndt_memory_error(ctx);
303
+ }
304
+
305
+ t = ndt_from_string(s, ctx);
306
+ if (t == NULL) {
307
+ ndt_free(x);
308
+ return NULL;
309
+ }
310
+
311
+ if (!ndt_is_concrete(t)) {
312
+ ndt_err_format(ctx, NDT_ValueError, "type must be concrete");
313
+ ndt_del(t);
314
+ ndt_free(x);
315
+ return NULL;
316
+ }
317
+
318
+ if (xnd_bitmap_init(&b, t,ctx) < 0) {
319
+ ndt_del(t);
320
+ ndt_free(x);
321
+ return NULL;
322
+ }
323
+
324
+ ptr = xnd_new(t, flags, ctx);
325
+ if (ptr == NULL) {
326
+ xnd_bitmap_clear(&b);
327
+ ndt_del(t);
328
+ ndt_free(x);
329
+ return NULL;
330
+ }
331
+
332
+ x->flags = flags;
333
+ x->master.bitmap = b;
334
+ x->master.index = 0;
335
+ x->master.type = t;
336
+ x->master.ptr = ptr;
337
+
338
+ return x;
339
+ }
340
+
341
+ /*
342
+ * Return a new master buffer. Any combination of flags except for XND_OWN_TYPE
343
+ * can be passed. 't' must be kept valid as long as the master buffer is valid.
344
+ */
345
+ xnd_master_t *
346
+ xnd_empty_from_type(const ndt_t *t, uint32_t flags, ndt_context_t *ctx)
347
+ {
348
+ xnd_bitmap_t b = {.data=NULL, .size=0, .next=NULL};
349
+ xnd_master_t *x;
350
+ char *ptr;
351
+
352
+ if (flags & XND_OWN_TYPE) {
353
+ ndt_err_format(ctx, NDT_InvalidArgumentError,
354
+ "xnd_empty_from_type: XND_OWN_TYPE must not be set");
355
+ return NULL;
356
+ }
357
+
358
+ if (!ndt_is_concrete(t)) {
359
+ ndt_err_format(ctx, NDT_ValueError, "type must be concrete");
360
+ return NULL;
361
+ }
362
+
363
+ x = ndt_alloc(1, sizeof *x);
364
+ if (x == NULL) {
365
+ return ndt_memory_error(ctx);
366
+ }
367
+
368
+ if (xnd_bitmap_init(&b, t, ctx) < 0) {
369
+ ndt_free(x);
370
+ return NULL;
371
+ }
372
+
373
+ ptr = xnd_new(t, flags, ctx);
374
+ if (ptr == NULL) {
375
+ xnd_bitmap_clear(&b);
376
+ ndt_free(x);
377
+ return NULL;
378
+ }
379
+
380
+ x->flags = flags;
381
+ x->master.bitmap = b;
382
+ x->master.index = 0;
383
+ x->master.type = t;
384
+ x->master.ptr = ptr;
385
+
386
+ return x;
387
+ }
388
+
389
+ /*
390
+ * Create master buffer from an existing xnd_t. Ownership of bitmaps, type,
391
+ * ptr is transferred to the master buffer.
392
+ *
393
+ * 'flags' are the master buffer's flags after the transfer. The flags of
394
+ * 'src' are always assumed to be XND_OWN_ALL.
395
+ *
396
+ * This is a convenience function that should only be used if the xnd_t src
397
+ * owns everything and its internals have not been exposed to other views.
398
+ */
399
+ xnd_master_t *
400
+ xnd_from_xnd(xnd_t *src, uint32_t flags, ndt_context_t *ctx)
401
+ {
402
+ xnd_master_t *x;
403
+
404
+ x = ndt_alloc(1, sizeof *x);
405
+ if (x == NULL) {
406
+ xnd_clear(src, XND_OWN_ALL);
407
+ ndt_del((ndt_t *)src->type);
408
+ ndt_aligned_free(src->ptr);
409
+ xnd_bitmap_clear(&src->bitmap);
410
+ return ndt_memory_error(ctx);
411
+ }
412
+
413
+ x->flags = flags;
414
+ x->master = *src;
415
+
416
+ return x;
417
+ }
418
+
419
+
420
+ /*****************************************************************************/
421
+ /* Deallocate and clear a master buffer */
422
+ /*****************************************************************************/
423
+
424
+ static bool
425
+ requires_clear(const ndt_t * const t)
426
+ {
427
+ const ndt_t *dtype = ndt_dtype(t);
428
+
429
+ switch (dtype->tag) {
430
+ case Categorical:
431
+ case Bool:
432
+ case Int8: case Int16: case Int32: case Int64:
433
+ case Uint8: case Uint16: case Uint32: case Uint64:
434
+ case Float16: case Float32: case Float64:
435
+ case Complex32: case Complex64: case Complex128:
436
+ case FixedString: case FixedBytes:
437
+ return false;
438
+ default:
439
+ return true;
440
+ }
441
+ }
442
+
443
+ /* Clear an embedded pointer. */
444
+ static void
445
+ xnd_clear_ref(xnd_t *x, const uint32_t flags)
446
+ {
447
+ assert(x->type->tag == Ref);
448
+
449
+ if (flags & XND_OWN_POINTERS) {
450
+ ndt_aligned_free(XND_POINTER_DATA(x->ptr));
451
+ XND_POINTER_DATA(x->ptr) = NULL;
452
+ }
453
+ }
454
+
455
+ /* Strings must always be allocated by non-aligned allocators. */
456
+ static void
457
+ xnd_clear_string(xnd_t *x, const uint32_t flags)
458
+ {
459
+ assert(x->type->tag == String);
460
+
461
+ if (flags & XND_OWN_STRINGS) {
462
+ ndt_free(XND_POINTER_DATA(x->ptr));
463
+ XND_POINTER_DATA(x->ptr) = NULL;
464
+ }
465
+ }
466
+
467
+ /* Bytes must always be allocated by aligned allocators. */
468
+ static void
469
+ xnd_clear_bytes(xnd_t *x, const uint32_t flags)
470
+ {
471
+ assert(x->type->tag == Bytes);
472
+
473
+ if (flags & XND_OWN_BYTES) {
474
+ ndt_aligned_free(XND_BYTES_DATA(x->ptr));
475
+ XND_BYTES_DATA(x->ptr) = NULL;
476
+ }
477
+ }
478
+
479
+ /* Clear embedded pointers in the data according to flags. */
480
+ static void
481
+ xnd_clear(xnd_t * const x, const uint32_t flags)
482
+ {
483
+ NDT_STATIC_CONTEXT(ctx);
484
+ const ndt_t * const t = x->type;
485
+
486
+ assert(ndt_is_concrete(t));
487
+
488
+ switch (t->tag) {
489
+ case FixedDim: {
490
+ for (int64_t i = 0; i < t->FixedDim.shape; i++) {
491
+ xnd_t next = _fixed_dim_next(x, i);
492
+ xnd_clear(&next, flags);
493
+ }
494
+
495
+ return;
496
+ }
497
+
498
+ case VarDim: {
499
+ int64_t start, step, shape;
500
+ int64_t i;
501
+
502
+ shape = ndt_var_indices(&start, &step, t, x->index, &ctx);
503
+ if (shape < 0) {
504
+ /* This cannot happen: indices are checked in xnd_init() and
505
+ * should remain constant. */
506
+ ndt_context_del(&ctx);
507
+ fprintf(stderr, "xnd_clear: internal error: var indices changed\n");
508
+ return;
509
+ }
510
+
511
+ for (i = 0; i < shape; i++) {
512
+ xnd_t next = _var_dim_next(x, start, step, i);
513
+ xnd_clear(&next, flags);
514
+ }
515
+
516
+ return;
517
+ }
518
+
519
+ case Tuple: {
520
+ for (int64_t i = 0; i < t->Tuple.shape; i++) {
521
+ xnd_t next = _tuple_next(x, i);
522
+ xnd_clear(&next, flags);
523
+ }
524
+
525
+ return;
526
+ }
527
+
528
+ case Record: {
529
+ for (int64_t i = 0; i < t->Record.shape; i++) {
530
+ xnd_t next = _record_next(x, i);
531
+ xnd_clear(&next, flags);
532
+ }
533
+
534
+ return;
535
+ }
536
+
537
+ case Ref: {
538
+ if (flags & XND_OWN_POINTERS) {
539
+ xnd_t next = _ref_next(x);
540
+ xnd_clear(&next, flags);
541
+ xnd_clear_ref(x, flags);
542
+ }
543
+
544
+ return;
545
+ }
546
+
547
+ case Constr: {
548
+ xnd_t next = _constr_next(x);
549
+ xnd_clear(&next, flags);
550
+ return;
551
+ }
552
+
553
+ case Nominal: {
554
+ xnd_t next = _nominal_next(x);
555
+ xnd_clear(&next, flags);
556
+ return;
557
+ }
558
+
559
+ case Bool:
560
+ case Int8: case Int16: case Int32: case Int64:
561
+ case Uint8: case Uint16: case Uint32: case Uint64:
562
+ case Float16: case Float32: case Float64:
563
+ case Complex32: case Complex64: case Complex128:
564
+ case FixedString: case FixedBytes:
565
+ return;
566
+
567
+ case String:
568
+ xnd_clear_string(x, flags);
569
+ return;
570
+
571
+ case Bytes:
572
+ xnd_clear_bytes(x, flags);
573
+ return;
574
+
575
+ case Categorical:
576
+ /* Categorical values are just indices into the categories. */
577
+ return;
578
+
579
+ case Char:
580
+ /* Just a scalar. */
581
+ return;
582
+
583
+ /* NOT REACHED: intercepted by ndt_is_abstract(). */
584
+ case Module: case Function:
585
+ case AnyKind: case SymbolicDim: case EllipsisDim: case Typevar:
586
+ case ScalarKind: case SignedKind: case UnsignedKind: case FloatKind:
587
+ case ComplexKind: case FixedStringKind: case FixedBytesKind:
588
+ return;
589
+ }
590
+ }
591
+
592
+ /*
593
+ * Delete an xnd_t buffer according to 'flags'. Outside xnd_del(), this
594
+ * function should only be used if an xnd_t owns all its members.
595
+ */
596
+ void
597
+ xnd_del_buffer(xnd_t *x, uint32_t flags)
598
+ {
599
+ if (x != NULL) {
600
+ if (x->ptr != NULL && x->type != NULL) {
601
+ if ((flags&XND_OWN_DATA) && requires_clear(x->type)) {
602
+ xnd_clear(x, flags);
603
+ }
604
+
605
+ if (flags & XND_OWN_TYPE) {
606
+ ndt_del((ndt_t *)x->type);
607
+ }
608
+
609
+ if (flags & XND_OWN_DATA) {
610
+ ndt_aligned_free(x->ptr);
611
+ }
612
+ }
613
+
614
+ if (flags & XND_OWN_DATA) {
615
+ xnd_bitmap_clear(&x->bitmap);
616
+ }
617
+ }
618
+ }
619
+
620
+ /*
621
+ * Delete the master buffer. The type and embedded pointers are deallocated
622
+ * according to x->flags.
623
+ */
624
+ void
625
+ xnd_del(xnd_master_t *x)
626
+ {
627
+ if (x != NULL) {
628
+ xnd_del_buffer(&x->master, x->flags);
629
+ ndt_free(x);
630
+ }
631
+ }
632
+
633
+
634
+ /*****************************************************************************/
635
+ /* Subtrees (single elements are a special case) */
636
+ /*****************************************************************************/
637
+
638
+ static int64_t
639
+ get_index(const xnd_index_t *key, int64_t shape, ndt_context_t *ctx)
640
+ {
641
+ switch (key->tag) {
642
+ case Index: {
643
+ int64_t i = key->Index;
644
+ if (i < 0) {
645
+ i += shape;
646
+ }
647
+
648
+ if (i < 0 || i >= shape || i > XND_SSIZE_MAX) {
649
+ ndt_err_format(ctx, NDT_IndexError,
650
+ "index with value %" PRIi64 " out of bounds", key->Index);
651
+ return -1;
652
+ }
653
+
654
+ return i;
655
+ }
656
+
657
+ case FieldName:
658
+ ndt_err_format(ctx, NDT_ValueError,
659
+ "expected integer index, got field name: '%s'", key->FieldName);
660
+ return -1;
661
+
662
+ case Slice:
663
+ ndt_err_format(ctx, NDT_ValueError,
664
+ "expected integer index, got slice");
665
+ return -1;
666
+ }
667
+
668
+ /* NOT REACHED: tags should be exhaustive */
669
+ ndt_err_format(ctx, NDT_RuntimeError, "invalid index tag");
670
+ return -1;
671
+ }
672
+
673
+ static int64_t
674
+ get_index_record(const ndt_t *t, const xnd_index_t *key, ndt_context_t *ctx)
675
+ {
676
+ assert(t->tag == Record);
677
+
678
+ switch (key->tag) {
679
+ case FieldName: {
680
+ int64_t i;
681
+
682
+ for (i = 0; i < t->Record.shape; i++) {
683
+ if (strcmp(key->FieldName, t->Record.names[i]) == 0) {
684
+ return i;
685
+ }
686
+ }
687
+
688
+ ndt_err_format(ctx, NDT_ValueError,
689
+ "invalid field name '%s'", key->FieldName);
690
+ return -1;
691
+ }
692
+ case Index: case Slice:
693
+ return get_index(key, t->Record.shape, ctx);
694
+ }
695
+
696
+ /* NOT REACHED: tags should be exhaustive */
697
+ ndt_err_format(ctx, NDT_RuntimeError, "invalid index tag");
698
+ return -1;
699
+ }
700
+
701
+ static void
702
+ set_index_exception(bool indexable, ndt_context_t *ctx)
703
+ {
704
+ if (indexable) {
705
+ ndt_err_format(ctx, NDT_IndexError, "too many indices");
706
+ }
707
+ else {
708
+ ndt_err_format(ctx, NDT_TypeError, "type not indexable");
709
+ }
710
+ }
711
+
712
+ /* Return a typed subtree of a memory block */
713
+ xnd_t
714
+ xnd_subtree_index(const xnd_t *x, const int64_t *indices, int len, ndt_context_t *ctx)
715
+ {
716
+ const ndt_t * const t = x->type;
717
+
718
+ assert(ndt_is_concrete(t));
719
+
720
+ if (t->ndim > 0 && ndt_is_optional(t)) {
721
+ ndt_err_format(ctx, NDT_NotImplementedError,
722
+ "optional dimensions are not supported");
723
+ return xnd_error;
724
+ }
725
+
726
+ if (len == 0) {
727
+ return *x;
728
+ }
729
+
730
+ const int64_t i = indices[0];
731
+
732
+ switch (t->tag) {
733
+ case FixedDim: {
734
+ if (i < 0 || i >= t->FixedDim.shape) {
735
+ ndt_err_format(ctx, NDT_ValueError,
736
+ "fixed dim index out of bounds");
737
+ return xnd_error;
738
+ }
739
+
740
+ const xnd_t next = xnd_fixed_dim_next(x, i);
741
+ return xnd_subtree_index(&next, indices+1, len-1, ctx);
742
+ }
743
+
744
+ case VarDim: {
745
+ int64_t start, step, shape;
746
+
747
+ shape = ndt_var_indices(&start, &step, t, x->index, ctx);
748
+ if (shape < 0) {
749
+ return xnd_error;
750
+ }
751
+
752
+ if (i < 0 || i >= shape) {
753
+ ndt_err_format(ctx, NDT_ValueError, "var dim index out of bounds");
754
+ return xnd_error;
755
+ }
756
+
757
+ const xnd_t next = xnd_var_dim_next(x, start, step, i);
758
+ return xnd_subtree_index(&next, indices+1, len-1, ctx);
759
+ }
760
+
761
+ case Tuple: {
762
+ if (i < 0 || i >= t->Tuple.shape) {
763
+ ndt_err_format(ctx, NDT_ValueError, "tuple index out of bounds");
764
+ return xnd_error;
765
+ }
766
+
767
+ const xnd_t next = xnd_tuple_next(x, i, ctx);
768
+ if (next.ptr == NULL) {
769
+ return xnd_error;
770
+ }
771
+
772
+ return xnd_subtree_index(&next, indices+1, len-1, ctx);
773
+ }
774
+
775
+ case Record: {
776
+ if (i < 0 || i >= t->Record.shape) {
777
+ ndt_err_format(ctx, NDT_ValueError, "record index out of bounds");
778
+ return xnd_error;
779
+ }
780
+
781
+ const xnd_t next = xnd_record_next(x, i, ctx);
782
+ if (next.ptr == NULL) {
783
+ return xnd_error;
784
+ }
785
+
786
+ return xnd_subtree_index(&next, indices+1, len-1, ctx);
787
+ }
788
+
789
+ case Ref: {
790
+ const xnd_t next = xnd_ref_next(x, ctx);
791
+ if (next.ptr == NULL) {
792
+ return xnd_error;
793
+ }
794
+
795
+ return xnd_subtree_index(&next, indices, len, ctx);
796
+ }
797
+
798
+ case Constr: {
799
+ const xnd_t next = xnd_constr_next(x, ctx);
800
+ if (next.ptr == NULL) {
801
+ return xnd_error;
802
+ }
803
+
804
+ return xnd_subtree_index(&next, indices, len, ctx);
805
+ }
806
+
807
+ case Nominal: {
808
+ const xnd_t next = xnd_nominal_next(x, ctx);
809
+ if (next.ptr == NULL) {
810
+ return xnd_error;
811
+ }
812
+
813
+ return xnd_subtree_index(&next, indices, len, ctx);
814
+ }
815
+
816
+ default:
817
+ ndt_err_format(ctx, NDT_ValueError, "type not indexable");
818
+ return xnd_error;
819
+ }
820
+ }
821
+
822
+ /*
823
+ * Return a zero copy view of an xnd object. If a dtype is indexable,
824
+ * descend into the dtype.
825
+ */
826
+ static xnd_t
827
+ _xnd_subtree(const xnd_t *x, const xnd_index_t indices[], int len, bool indexable,
828
+ ndt_context_t *ctx)
829
+ {
830
+ const ndt_t *t = x->type;
831
+ const xnd_index_t *key;
832
+
833
+ assert(ndt_is_concrete(t));
834
+
835
+ if (t->ndim > 0 && ndt_is_optional(t)) {
836
+ ndt_err_format(ctx, NDT_NotImplementedError,
837
+ "optional dimensions are not supported");
838
+ return xnd_error;
839
+ }
840
+
841
+ if (len == 0) {
842
+ return *x;
843
+ }
844
+
845
+ key = &indices[0];
846
+
847
+ switch (t->tag) {
848
+ case FixedDim: {
849
+ int64_t i = get_index(key, t->FixedDim.shape, ctx);
850
+ if (i < 0) {
851
+ return xnd_error;
852
+ }
853
+
854
+ const xnd_t next = xnd_fixed_dim_next(x, i);
855
+ return _xnd_subtree(&next, indices+1, len-1, true, ctx);
856
+ }
857
+
858
+ case VarDim: {
859
+ int64_t start, step, shape;
860
+ int64_t i;
861
+
862
+ shape = ndt_var_indices(&start, &step, t, x->index, ctx);
863
+ if (shape < 0) {
864
+ return xnd_error;
865
+ }
866
+
867
+ i = get_index(key, shape, ctx);
868
+ if (i < 0) {
869
+ return xnd_error;
870
+ }
871
+
872
+ const xnd_t next = xnd_var_dim_next(x, start, step, i);
873
+ return _xnd_subtree(&next, indices+1, len-1, true, ctx);
874
+ }
875
+
876
+ case Tuple: {
877
+ const int64_t i = get_index(key, t->Tuple.shape, ctx);
878
+ if (i < 0) {
879
+ return xnd_error;
880
+ }
881
+
882
+ const xnd_t next = xnd_tuple_next(x, i, ctx);
883
+ if (next.ptr == NULL) {
884
+ return xnd_error;
885
+ }
886
+
887
+ return _xnd_subtree(&next, indices+1, len-1, true, ctx);
888
+ }
889
+
890
+ case Record: {
891
+ int64_t i = get_index_record(t, key, ctx);
892
+ if (i < 0) {
893
+ return xnd_error;
894
+ }
895
+
896
+ const xnd_t next = xnd_record_next(x, i, ctx);
897
+ if (next.ptr == NULL) {
898
+ return xnd_error;
899
+ }
900
+
901
+ return _xnd_subtree(&next, indices+1, len-1, true, ctx);
902
+ }
903
+
904
+ case Ref: {
905
+ const xnd_t next = xnd_ref_next(x, ctx);
906
+ if (next.ptr == NULL) {
907
+ return xnd_error;
908
+ }
909
+
910
+ return _xnd_subtree(&next, indices, len, false, ctx);
911
+ }
912
+
913
+ case Constr: {
914
+ const xnd_t next = xnd_constr_next(x, ctx);
915
+ if (next.ptr == NULL) {
916
+ return xnd_error;
917
+ }
918
+
919
+ return _xnd_subtree(&next, indices, len, false, ctx);
920
+ }
921
+
922
+ case Nominal: {
923
+ const xnd_t next = xnd_nominal_next(x, ctx);
924
+ if (next.ptr == NULL) {
925
+ return xnd_error;
926
+ }
927
+
928
+ return _xnd_subtree(&next, indices, len, false, ctx);
929
+ }
930
+
931
+ default:
932
+ set_index_exception(indexable, ctx);
933
+ return xnd_error;
934
+ }
935
+ }
936
+
937
+ /*
938
+ * Return a zero copy view of an xnd object. If a dtype is indexable,
939
+ * descend into the dtype.
940
+ */
941
+ xnd_t
942
+ xnd_subtree(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx)
943
+ {
944
+ return _xnd_subtree(x, indices, len, false, ctx);
945
+ }
946
+
947
+ static xnd_t xnd_index(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx);
948
+ static xnd_t xnd_slice(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx);
949
+
950
+ xnd_t
951
+ xnd_multikey(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx)
952
+ {
953
+ const ndt_t *t = x->type;
954
+ const xnd_index_t *key;
955
+
956
+ assert(len >= 0);
957
+ assert(ndt_is_concrete(t));
958
+ assert(x->ptr != NULL);
959
+
960
+ if (len > t->ndim) {
961
+ ndt_err_format(ctx, NDT_IndexError, "too many indices");
962
+ return xnd_error;
963
+ }
964
+
965
+ if (len == 0) {
966
+ xnd_t next = *x;
967
+ next.type = ndt_copy(t, ctx);
968
+ if (next.type == NULL) {
969
+ return xnd_error;
970
+ }
971
+
972
+ return next;
973
+ }
974
+
975
+ key = &indices[0];
976
+
977
+ switch (key->tag) {
978
+ case Index:
979
+ return xnd_index(x, indices, len, ctx);
980
+ case Slice:
981
+ return xnd_slice(x, indices, len, ctx);
982
+ case FieldName:
983
+ ndt_err_format(ctx, NDT_RuntimeError,
984
+ "xnd_multikey: internal error: key must be index or slice");
985
+ return xnd_error;
986
+ }
987
+
988
+ /* NOT REACHED: tags should be exhaustive */
989
+ ndt_err_format(ctx, NDT_RuntimeError, "invalid index tag");
990
+ return xnd_error;
991
+ }
992
+
993
+ /*
994
+ * Return a view with a copy of the type. Indexing into the dtype is
995
+ * not permitted.
996
+ */
997
+ static xnd_t
998
+ xnd_index(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx)
999
+ {
1000
+ const ndt_t *t = x->type;
1001
+ const xnd_index_t *key;
1002
+
1003
+ assert(len > 0);
1004
+ assert(ndt_is_concrete(t));
1005
+ assert(x->ptr != NULL);
1006
+
1007
+ key = &indices[0];
1008
+ assert(key->tag == Index);
1009
+
1010
+ switch (t->tag) {
1011
+ case FixedDim: {
1012
+ const int64_t i = get_index(key, t->FixedDim.shape, ctx);
1013
+ if (i < 0) {
1014
+ return xnd_error;
1015
+ }
1016
+
1017
+ const xnd_t next = xnd_fixed_dim_next(x, i);
1018
+ return xnd_multikey(&next, indices+1, len-1, ctx);
1019
+ }
1020
+
1021
+ case VarDim: {
1022
+ ndt_err_format(ctx, NDT_IndexError,
1023
+ "mixed indexing and slicing is not supported for var dimensions");
1024
+ return xnd_error;
1025
+ }
1026
+
1027
+ default:
1028
+ ndt_err_format(ctx, NDT_IndexError, "type is not indexable");
1029
+ return xnd_error;
1030
+ }
1031
+ }
1032
+
1033
+ static xnd_t
1034
+ xnd_slice(const xnd_t *x, const xnd_index_t indices[], int len, ndt_context_t *ctx)
1035
+ {
1036
+ const ndt_t *t = x->type;
1037
+ const xnd_index_t *key;
1038
+
1039
+ assert(len > 0);
1040
+ assert(ndt_is_concrete(t));
1041
+ assert(x->ptr != NULL);
1042
+
1043
+ key = &indices[0];
1044
+ assert(key->tag == Slice);
1045
+
1046
+ switch (t->tag) {
1047
+ case FixedDim: {
1048
+ int64_t start = key->Slice.start;
1049
+ int64_t stop = key->Slice.stop;
1050
+ int64_t step = key->Slice.step;
1051
+ int64_t shape;
1052
+
1053
+ shape = xnd_slice_adjust_indices(t->FixedDim.shape, &start, &stop, step);
1054
+
1055
+ const xnd_t next = xnd_fixed_dim_next(x, start);
1056
+ const xnd_t sliced = xnd_multikey(&next, indices+1, len-1, ctx);
1057
+ if (sliced.ptr == NULL) {
1058
+ return xnd_error;
1059
+ }
1060
+
1061
+ xnd_t ret = *x;
1062
+ ret.type = ndt_fixed_dim((ndt_t *)sliced.type, shape,
1063
+ t->Concrete.FixedDim.step * step,
1064
+ ctx);
1065
+ if (ret.type == NULL) {
1066
+ return xnd_error;
1067
+ }
1068
+ ret.index = sliced.index;
1069
+
1070
+ return ret;
1071
+ }
1072
+
1073
+ case VarDim: {
1074
+ int64_t start = key->Slice.start;
1075
+ int64_t stop = key->Slice.stop;
1076
+ int64_t step = key->Slice.step;
1077
+ ndt_slice_t *slices;
1078
+ int32_t nslices;
1079
+
1080
+ if (ndt_is_optional(t)) {
1081
+ ndt_err_format(ctx, NDT_NotImplementedError,
1082
+ "optional dimensions are temporarily disabled");
1083
+ return xnd_error;
1084
+ }
1085
+
1086
+ xnd_t next = *x;
1087
+ next.type = t->VarDim.type;
1088
+
1089
+ next = xnd_multikey(&next, indices+1, len-1, ctx);
1090
+ if (next.ptr == NULL) {
1091
+ return xnd_error;
1092
+ }
1093
+
1094
+ slices = ndt_var_add_slice(&nslices, t, start, stop, step, ctx);
1095
+ if (slices == NULL) {
1096
+ return xnd_error;
1097
+ }
1098
+
1099
+ xnd_t ret = *x;
1100
+ ret.type = ndt_var_dim((ndt_t *)next.type,
1101
+ ExternalOffsets,
1102
+ t->Concrete.VarDim.noffsets, t->Concrete.VarDim.offsets,
1103
+ nslices, slices,
1104
+ ctx);
1105
+ if (ret.type == NULL) {
1106
+ return xnd_error;
1107
+ }
1108
+
1109
+ ret.index = next.index;
1110
+
1111
+ return ret;
1112
+ }
1113
+
1114
+ case Tuple: {
1115
+ ndt_err_format(ctx, NDT_NotImplementedError,
1116
+ "slicing tuples is not supported");
1117
+ return xnd_error;
1118
+ }
1119
+
1120
+ case Record: {
1121
+ ndt_err_format(ctx, NDT_NotImplementedError,
1122
+ "slicing records is not supported");
1123
+ return xnd_error;
1124
+ }
1125
+
1126
+ default:
1127
+ ndt_err_format(ctx, NDT_IndexError, "type not sliceable");
1128
+ return xnd_error;
1129
+ }
1130
+ }
1131
+
1132
+ xnd_t
1133
+ xnd_subscript(const xnd_t *x, const xnd_index_t indices[], int len,
1134
+ ndt_context_t *ctx)
1135
+ {
1136
+ bool have_slice = false;
1137
+
1138
+ for (int i = 0; i < len; i++) {
1139
+ if (indices[i].tag == Slice) {
1140
+ have_slice = true;
1141
+ break;
1142
+ }
1143
+ }
1144
+
1145
+ if (have_slice) {
1146
+ return xnd_multikey(x, indices, len, ctx);
1147
+ }
1148
+ else {
1149
+ xnd_t res = xnd_subtree(x, indices, len, ctx);
1150
+ const ndt_t *t;
1151
+
1152
+ if (res.ptr == NULL) {
1153
+ return xnd_error;
1154
+ }
1155
+
1156
+ t = ndt_copy(res.type, ctx);
1157
+ if (t == NULL) {
1158
+ return xnd_error;
1159
+ }
1160
+
1161
+ res.type = t;
1162
+ return res;
1163
+ }
1164
+ }
1165
+
1166
+
1167
+ /*****************************************************************************/
1168
+ /* Unstable API */
1169
+ /*****************************************************************************/
1170
+
1171
+ /* error return value */
1172
+ const xnd_view_t xnd_view_error = {
1173
+ .flags = 0,
1174
+ .obj = NULL,
1175
+ .view = { .bitmap = {.data=NULL, .size=0, .next=NULL},
1176
+ .index = 0,
1177
+ .type = NULL,
1178
+ .ptr = NULL }
1179
+ };
1180
+
1181
+ int
1182
+ xnd_view_err_occurred(const xnd_view_t *x)
1183
+ {
1184
+ return x->view.ptr == NULL;
1185
+ }
1186
+
1187
+ void
1188
+ xnd_view_clear(xnd_view_t *x)
1189
+ {
1190
+ xnd_del_buffer(&x->view, x->flags);
1191
+ x->flags = 0;
1192
+ x->obj = NULL;
1193
+ }
1194
+
1195
+ xnd_view_t
1196
+ xnd_view_from_xnd(const void *obj, const xnd_t *x)
1197
+ {
1198
+ xnd_view_t res;
1199
+
1200
+ res.flags = 0;
1201
+ res.obj = obj;
1202
+ res.view = *x;
1203
+
1204
+ return res;
1205
+ }
1206
+
1207
+ xnd_view_t
1208
+ xnd_view_subscript(const xnd_view_t *x, const xnd_index_t indices[], int len,
1209
+ ndt_context_t *ctx)
1210
+ {
1211
+ xnd_view_t res;
1212
+
1213
+ res.flags = XND_OWN_TYPE;
1214
+ res.obj = x->obj;
1215
+
1216
+ res.view = xnd_subscript(&x->view, indices, len, ctx);
1217
+ if (xnd_err_occurred(&res.view)) {
1218
+ return xnd_view_error;
1219
+ }
1220
+
1221
+ return res;
1222
+ }
1223
+
1224
+
1225
+ /*****************************************************************************/
1226
+ /* Float format */
1227
+ /*****************************************************************************/
1228
+
1229
+ #define IEEE_LITTLE_ENDIAN 0
1230
+ #define IEEE_BIG_ENDIAN 1
1231
+ static int xnd_double_format = 0;
1232
+ static int xnd_float_format = 0;
1233
+
1234
+ int
1235
+ xnd_init_float(ndt_context_t *ctx)
1236
+ {
1237
+ double x = 9006104071832581.0;
1238
+ float y = 16711938.0;
1239
+
1240
+ #ifndef _MSC_VER /* Suppress a warning, no need to check on Windows. */
1241
+ if (sizeof(double) != 8) {
1242
+ ndt_err_format(ctx, NDT_RuntimeError,
1243
+ "unsupported platform, need sizeof(double)==8");
1244
+ return -1;
1245
+
1246
+ }
1247
+
1248
+ if (sizeof(float) != 4) {
1249
+ ndt_err_format(ctx, NDT_RuntimeError,
1250
+ "unsupported platform, need sizeof(float)==4");
1251
+ return -1;
1252
+ }
1253
+ #endif
1254
+
1255
+ if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0) {
1256
+ xnd_double_format = IEEE_BIG_ENDIAN;
1257
+ }
1258
+ else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0) {
1259
+ xnd_double_format = IEEE_LITTLE_ENDIAN;
1260
+ }
1261
+ else {
1262
+ ndt_err_format(ctx, NDT_RuntimeError,
1263
+ "unsupported platform, could not detect double endianness");
1264
+ return -1;
1265
+ }
1266
+
1267
+ if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0) {
1268
+ xnd_float_format = IEEE_BIG_ENDIAN;
1269
+ }
1270
+ else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0) {
1271
+ xnd_float_format = IEEE_LITTLE_ENDIAN;
1272
+ }
1273
+ else {
1274
+ ndt_err_format(ctx, NDT_RuntimeError,
1275
+ "unsupported platform, could not detect float endianness");
1276
+ return -1;
1277
+ }
1278
+
1279
+ return 0;
1280
+ }
1281
+
1282
+ bool
1283
+ xnd_float_is_little_endian(void)
1284
+ {
1285
+ return xnd_float_format==IEEE_LITTLE_ENDIAN;
1286
+ }
1287
+
1288
+ bool
1289
+ xnd_float_is_big_endian(void)
1290
+ {
1291
+ return xnd_float_format==IEEE_BIG_ENDIAN;
1292
+ }
1293
+
1294
+ bool
1295
+ xnd_double_is_little_endian(void)
1296
+ {
1297
+ return xnd_double_format==IEEE_LITTLE_ENDIAN;
1298
+ }
1299
+
1300
+ bool
1301
+ xnd_double_is_big_endian(void)
1302
+ {
1303
+ return xnd_double_format==IEEE_BIG_ENDIAN;
1304
+ }