xnd 0.2.0dev6 → 0.2.0dev7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/Rakefile +1 -1
  4. data/ext/ruby_xnd/GPATH +0 -0
  5. data/ext/ruby_xnd/GRTAGS +0 -0
  6. data/ext/ruby_xnd/GTAGS +0 -0
  7. data/ext/ruby_xnd/extconf.rb +8 -5
  8. data/ext/ruby_xnd/gc_guard.c +53 -2
  9. data/ext/ruby_xnd/gc_guard.h +8 -2
  10. data/ext/ruby_xnd/include/overflow.h +147 -0
  11. data/ext/ruby_xnd/include/ruby_xnd.h +62 -0
  12. data/ext/ruby_xnd/include/xnd.h +590 -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/ruby_xnd.c +556 -47
  18. data/ext/ruby_xnd/ruby_xnd.h +2 -1
  19. data/ext/ruby_xnd/xnd/Makefile +80 -0
  20. data/ext/ruby_xnd/xnd/config.h +26 -0
  21. data/ext/ruby_xnd/xnd/config.h.in +3 -0
  22. data/ext/ruby_xnd/xnd/config.log +421 -0
  23. data/ext/ruby_xnd/xnd/config.status +1023 -0
  24. data/ext/ruby_xnd/xnd/configure +376 -8
  25. data/ext/ruby_xnd/xnd/configure.ac +48 -7
  26. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +3 -1
  27. data/ext/ruby_xnd/xnd/doc/xnd/{types.rst → xnd.rst} +3 -18
  28. data/ext/ruby_xnd/xnd/libxnd/Makefile +142 -0
  29. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +43 -3
  30. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +19 -3
  31. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +42 -3
  32. data/ext/ruby_xnd/xnd/libxnd/bitmaps.o +0 -0
  33. data/ext/ruby_xnd/xnd/libxnd/bounds.c +366 -0
  34. data/ext/ruby_xnd/xnd/libxnd/bounds.o +0 -0
  35. data/ext/ruby_xnd/xnd/libxnd/contrib.h +98 -0
  36. data/ext/ruby_xnd/xnd/libxnd/contrib/bfloat16.h +213 -0
  37. data/ext/ruby_xnd/xnd/libxnd/copy.c +155 -4
  38. data/ext/ruby_xnd/xnd/libxnd/copy.o +0 -0
  39. data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.cu +121 -0
  40. data/ext/ruby_xnd/xnd/libxnd/cuda/cuda_memory.h +58 -0
  41. data/ext/ruby_xnd/xnd/libxnd/equal.c +195 -7
  42. data/ext/ruby_xnd/xnd/libxnd/equal.o +0 -0
  43. data/ext/ruby_xnd/xnd/libxnd/inline.h +32 -0
  44. data/ext/ruby_xnd/xnd/libxnd/libxnd.a +0 -0
  45. data/ext/ruby_xnd/xnd/libxnd/libxnd.so +1 -0
  46. data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0 +1 -0
  47. data/ext/ruby_xnd/xnd/libxnd/libxnd.so.0.2.0dev3 +0 -0
  48. data/ext/ruby_xnd/xnd/libxnd/shape.c +207 -0
  49. data/ext/ruby_xnd/xnd/libxnd/shape.o +0 -0
  50. data/ext/ruby_xnd/xnd/libxnd/split.c +2 -2
  51. data/ext/ruby_xnd/xnd/libxnd/split.o +0 -0
  52. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile +39 -0
  53. data/ext/ruby_xnd/xnd/libxnd/xnd.c +613 -91
  54. data/ext/ruby_xnd/xnd/libxnd/xnd.h +145 -4
  55. data/ext/ruby_xnd/xnd/libxnd/xnd.o +0 -0
  56. data/ext/ruby_xnd/xnd/python/test_xnd.py +1125 -50
  57. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +609 -124
  58. data/ext/ruby_xnd/xnd/python/xnd/_version.py +1 -0
  59. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +1652 -101
  60. data/ext/ruby_xnd/xnd/python/xnd/libxnd.a +0 -0
  61. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so +1 -0
  62. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0 +1 -0
  63. data/ext/ruby_xnd/xnd/python/xnd/libxnd.so.0.2.0dev3 +0 -0
  64. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +1 -1
  65. data/ext/ruby_xnd/xnd/python/xnd/util.h +25 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/xnd.h +590 -0
  67. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +106 -6
  68. data/ext/ruby_xnd/xnd/python/xnd_support.py +4 -0
  69. data/ext/ruby_xnd/xnd/setup.py +46 -4
  70. data/lib/ruby_xnd.so +0 -0
  71. data/lib/xnd.rb +39 -3
  72. data/lib/xnd/version.rb +2 -2
  73. data/xnd.gemspec +2 -1
  74. metadata +58 -5
@@ -0,0 +1,121 @@
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 <stdint.h>
35
+ #include "ndtypes.h"
36
+
37
+
38
+ /*****************************************************************************/
39
+ /* Expose some cuda memory functions */
40
+ /*****************************************************************************/
41
+
42
+ extern "C" void *
43
+ xnd_cuda_calloc_managed(uint16_t align, int64_t size, ndt_context_t *ctx)
44
+ {
45
+ char *ptr;
46
+ cudaError_t err;
47
+
48
+ size = size == 0 ? 1 : size;
49
+
50
+ if (size < 0 || (uint64_t)size > SIZE_MAX) {
51
+ ndt_err_format(ctx, NDT_ValueError,
52
+ "cudaMallocManaged: invalid size");
53
+ return NULL;
54
+ }
55
+
56
+ err = cudaMallocManaged(&ptr, (size_t)size);
57
+ if (err != cudaSuccess) {
58
+ ndt_err_format(ctx, NDT_MemoryError,
59
+ "cudaMallocManaged: allocation failed");
60
+ return NULL;
61
+ }
62
+
63
+ if (((uintptr_t)ptr) % align != 0) {
64
+ ndt_err_format(ctx, NDT_ValueError,
65
+ "cudaMallocManaged: alignment requirement too large");
66
+ cudaFree(ptr);
67
+ return NULL;
68
+ }
69
+
70
+ memset(ptr, '\0', (size_t)size);
71
+
72
+ return ptr;
73
+ }
74
+
75
+ extern "C" void
76
+ xnd_cuda_free(void *ptr)
77
+ {
78
+ cudaError_t err;
79
+
80
+ err = cudaFree(ptr);
81
+ if (err != cudaSuccess) {
82
+ fprintf(stderr, "cudaFree: unexpected failure\n");
83
+ }
84
+ }
85
+
86
+ extern "C" int
87
+ xnd_cuda_mem_prefetch_async(const void *ptr, int64_t count, int dev,
88
+ ndt_context_t *ctx)
89
+ {
90
+ cudaError_t err;
91
+
92
+ if (count < 0 || (uint64_t)count > SIZE_MAX) {
93
+ ndt_err_format(ctx, NDT_ValueError,
94
+ "cudaMemPrefetchAsync: invalid count");
95
+ return -1;
96
+ }
97
+
98
+ err = cudaMemPrefetchAsync(ptr, (size_t)count, dev);
99
+ if (err != cudaSuccess) {
100
+ ndt_err_format(ctx, NDT_MemoryError,
101
+ "cudaMemPrefetchAsync: prefetching failed");
102
+ return -1;
103
+ }
104
+
105
+ return 0;
106
+ }
107
+
108
+ extern "C" int
109
+ xnd_cuda_device_synchronize(ndt_context_t *ctx)
110
+ {
111
+ cudaError_t err;
112
+
113
+ err = cudaDeviceSynchronize();
114
+ if (err != cudaSuccess) {
115
+ ndt_err_format(ctx, NDT_RuntimeError,
116
+ "cuda device synchronization failed");
117
+ return -1;
118
+ }
119
+
120
+ return 0;
121
+ }
@@ -0,0 +1,58 @@
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 CUDA_MEMORY_H
35
+ #define CUDA_MEMORY_H
36
+
37
+ #include <stdint.h>
38
+ #include "ndtypes.h"
39
+
40
+
41
+ /*****************************************************************************/
42
+ /* Expose some cuda memory functions */
43
+ /*****************************************************************************/
44
+
45
+ #ifdef __cpplusplus
46
+ extern "C" void *xnd_cuda_calloc_managed(uint16_t align, int64_t size, ndt_context_t *ctx);
47
+ extern "C" void xnd_cuda_free(void *ptr);
48
+ extern "C" int xnd_cuda_mem_prefetch_async(const void *ptr, int64_t count, int dev, ndt_context_t *ctx);
49
+ extern "C" int xnd_cuda_device_synchronize(ndt_context_t *ctx);
50
+ #else
51
+ void *xnd_cuda_calloc_managed(uint16_t align, int64_t size, ndt_context_t *ctx);
52
+ void xnd_cuda_free(void *ptr);
53
+ int xnd_cuda_mem_prefetch_async(const void *ptr, int64_t count, int dev, ndt_context_t *ctx);
54
+ int xnd_cuda_device_synchronize(ndt_context_t *ctx);
55
+ #endif
56
+
57
+
58
+ #endif /* CUDA_MEMORY_H */
@@ -55,9 +55,7 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
55
55
  assert(ndt_is_concrete(t) && ndt_is_concrete(u));
56
56
 
57
57
  if (t->tag != u->tag) {
58
- ndt_err_format(ctx, NDT_TypeError,
59
- "mixed type comparisons are not implemented");
60
- return -1;
58
+ return 0;
61
59
  }
62
60
 
63
61
  if (xnd_is_na(x) || xnd_is_na(y)) {
@@ -111,6 +109,20 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
111
109
  return 1;
112
110
  }
113
111
 
112
+ case VarDimElem: {
113
+ const xnd_t xnext = apply_stored_index(x, ctx);
114
+ if (xnd_err_occurred(&xnext)) {
115
+ return -1;
116
+ }
117
+
118
+ const xnd_t ynext = apply_stored_index(y, ctx);
119
+ if (xnd_err_occurred(&ynext)) {
120
+ return -1;
121
+ }
122
+
123
+ return xnd_strict_equal(&xnext, &ynext, ctx);
124
+ }
125
+
114
126
  case Tuple: {
115
127
  if (u->Tuple.shape != t->Tuple.shape) {
116
128
  return 0;
@@ -161,6 +173,20 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
161
173
  return 1;
162
174
  }
163
175
 
176
+ case Union: {
177
+ const xnd_t xnext = xnd_union_next(x, ctx);
178
+ if (xnext.ptr == NULL) {
179
+ return -1;
180
+ }
181
+
182
+ const xnd_t ynext = xnd_union_next(y, ctx);
183
+ if (ynext.ptr == NULL) {
184
+ return -1;
185
+ }
186
+
187
+ return xnd_strict_equal(&xnext, &ynext, ctx);
188
+ }
189
+
164
190
  case Ref: {
165
191
  const xnd_t xnext = xnd_ref_next(x, ctx);
166
192
  if (xnext.ptr == NULL) {
@@ -296,6 +322,12 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
296
322
  return a == b;
297
323
  }
298
324
 
325
+ case BFloat16: {
326
+ double a = xnd_bfloat_unpack(x->ptr);
327
+ double b = xnd_bfloat_unpack(y->ptr);
328
+ return a == b;
329
+ }
330
+
299
331
  case Float16: {
300
332
  double a = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
301
333
  double b = xnd_float_unpack2((unsigned char *)y->ptr, le(u->flags));
@@ -314,6 +346,19 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
314
346
  return a == b;
315
347
  }
316
348
 
349
+ case BComplex32: {
350
+ double a_real, a_imag;
351
+ double b_real, b_imag;
352
+
353
+ a_real = xnd_bfloat_unpack(x->ptr);
354
+ a_imag = xnd_bfloat_unpack(x->ptr+2);
355
+
356
+ b_real = xnd_bfloat_unpack(y->ptr);
357
+ b_imag = xnd_bfloat_unpack(y->ptr+2);
358
+
359
+ return a_real == b_real && a_imag == b_imag;
360
+ }
361
+
317
362
  case Complex32: {
318
363
  double a_real, a_imag;
319
364
  double b_real, b_imag;
@@ -371,8 +416,8 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
371
416
  }
372
417
 
373
418
  case String: {
374
- const char *a = XND_POINTER_DATA(x->ptr);
375
- const char *b = XND_POINTER_DATA(y->ptr);
419
+ const char *a = XND_STRING_DATA(x->ptr);
420
+ const char *b = XND_STRING_DATA(y->ptr);
376
421
  return strcmp(a, b) == 0;
377
422
  }
378
423
 
@@ -393,6 +438,26 @@ xnd_strict_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
393
438
  return memcmp(a, b, (size_t)asize) == 0;
394
439
  }
395
440
 
441
+ case Array: {
442
+ int64_t ashape, bshape;
443
+
444
+ ashape = XND_ARRAY_SHAPE(x->ptr);
445
+ bshape = XND_ARRAY_SHAPE(y->ptr);
446
+
447
+ if (ashape != bshape) {
448
+ return 0;
449
+ }
450
+
451
+ for (int64_t i = 0; i < ashape; i++) {
452
+ const xnd_t xnext = xnd_array_next(x, i);
453
+ const xnd_t ynext = xnd_array_next(y, i);
454
+ n = xnd_strict_equal(&xnext, &ynext, ctx);
455
+ if (n <= 0) return n;
456
+ }
457
+
458
+ return 1;
459
+ }
460
+
396
461
  /* NOT REACHED: xnd types must be concrete. */
397
462
  case Module: case Function:
398
463
  case AnyKind: case SymbolicDim: case EllipsisDim: case Typevar:
@@ -495,6 +560,11 @@ equal_int64(const int64_t a, const xnd_t * const x)
495
560
  return a >= 0 ? (uint64_t)a == b : 0;
496
561
  }
497
562
 
563
+ case BFloat16: {
564
+ double b = xnd_bfloat_unpack(x->ptr);
565
+ return llabs(a) <= 4503599627370496LL ? (double)a == b : 0;
566
+ }
567
+
498
568
  case Float16: {
499
569
  double b = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
500
570
  return llabs(a) <= 4503599627370496LL ? (double)a == b : 0;
@@ -510,6 +580,17 @@ equal_int64(const int64_t a, const xnd_t * const x)
510
580
  return llabs(a) <= 4503599627370496LL ? (double)a == b : 0;
511
581
  }
512
582
 
583
+ case BComplex32: {
584
+ double real = xnd_bfloat_unpack(x->ptr);
585
+ double imag = xnd_bfloat_unpack(x->ptr+2);
586
+
587
+ if (imag == 0.0 && llabs(a) <= 4503599627370496LL) {
588
+ return (double)a == real;
589
+ }
590
+
591
+ return 0;
592
+ }
593
+
513
594
  case Complex32: {
514
595
  double real = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
515
596
  double imag = xnd_float_unpack2((unsigned char *)(x->ptr+2), le(t->flags));
@@ -601,6 +682,11 @@ equal_uint64(const uint64_t a, const xnd_t * const x)
601
682
  return a == b;
602
683
  }
603
684
 
685
+ case BFloat16: {
686
+ double b = xnd_bfloat_unpack(x->ptr);
687
+ return a <= 4503599627370496ULL ? (double)a == b : 0;
688
+ }
689
+
604
690
  case Float16: {
605
691
  double b = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
606
692
  return a <= 4503599627370496ULL ? (double)a == b : 0;
@@ -616,6 +702,17 @@ equal_uint64(const uint64_t a, const xnd_t * const x)
616
702
  return a <= 4503599627370496ULL ? (double)a == b : 0;
617
703
  }
618
704
 
705
+ case BComplex32: {
706
+ double real = xnd_bfloat_unpack(x->ptr);
707
+ double imag = xnd_bfloat_unpack(x->ptr+2);
708
+
709
+ if (imag == 0.0 && a <= 4503599627370496ULL) {
710
+ return (double)a == real;
711
+ }
712
+
713
+ return 0;
714
+ }
715
+
619
716
  case Complex32: {
620
717
  double real = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
621
718
  double imag = xnd_float_unpack2((unsigned char *)(x->ptr+2), le(t->flags));
@@ -707,6 +804,11 @@ equal_float64(const double a, const xnd_t * const x)
707
804
  return b <= 4503599627370496ULL ? a == (double)b : 0;
708
805
  }
709
806
 
807
+ case BFloat16: {
808
+ double b = xnd_bfloat_unpack(x->ptr);
809
+ return a == b;
810
+ }
811
+
710
812
  case Float16: {
711
813
  double b = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
712
814
  return a == b;
@@ -722,6 +824,19 @@ equal_float64(const double a, const xnd_t * const x)
722
824
  return a == b;
723
825
  }
724
826
 
827
+ case BComplex32: {
828
+ double real, imag;
829
+
830
+ real = xnd_bfloat_unpack(x->ptr);
831
+ imag = xnd_bfloat_unpack(x->ptr+2);
832
+
833
+ if (imag == 0.0) {
834
+ return a == real;
835
+ }
836
+
837
+ return 0;
838
+ }
839
+
725
840
  case Complex32: {
726
841
  double real, imag;
727
842
 
@@ -819,6 +934,11 @@ equal_complex128(const double real, const double imag, const xnd_t * const x)
819
934
  return b <= 4503599627370496ULL ? real == (double)b : 0;
820
935
  }
821
936
 
937
+ case BFloat16: {
938
+ double b = xnd_bfloat_unpack(x->ptr);
939
+ return imag == 0.0 && real == b;
940
+ }
941
+
822
942
  case Float16: {
823
943
  double b = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
824
944
  return imag == 0.0 && real == b;
@@ -834,6 +954,12 @@ equal_complex128(const double real, const double imag, const xnd_t * const x)
834
954
  return imag == 0.0 && real == b;
835
955
  }
836
956
 
957
+ case BComplex32: {
958
+ double a = xnd_bfloat_unpack(x->ptr);
959
+ double b = xnd_bfloat_unpack(x->ptr+2);
960
+ return real == a && imag == b;
961
+ }
962
+
837
963
  case Complex32: {
838
964
  double a = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
839
965
  double b = xnd_float_unpack2((unsigned char *)(x->ptr+2), le(t->flags));
@@ -859,6 +985,8 @@ equal_complex128(const double real, const double imag, const xnd_t * const x)
859
985
  int
860
986
  xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
861
987
  {
988
+ APPLY_STORED_INDICES_INT(x)
989
+ APPLY_STORED_INDICES_INT(y)
862
990
  const ndt_t * const t = x->type;
863
991
  const ndt_t * const u = y->type;
864
992
  int n;
@@ -972,6 +1100,20 @@ xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
972
1100
  return 1;
973
1101
  }
974
1102
 
1103
+ case Union: {
1104
+ const xnd_t xnext = xnd_union_next(x, ctx);
1105
+ if (xnext.ptr == NULL) {
1106
+ return -1;
1107
+ }
1108
+
1109
+ const xnd_t ynext = xnd_union_next(y, ctx);
1110
+ if (ynext.ptr == NULL) {
1111
+ return -1;
1112
+ }
1113
+
1114
+ return xnd_equal(&xnext, &ynext, ctx);
1115
+ }
1116
+
975
1117
  case Constr: {
976
1118
  if (u->tag != Constr || strcmp(u->Constr.name, t->Constr.name) != 0) {
977
1119
  return 0;
@@ -1094,6 +1236,11 @@ xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
1094
1236
  return equal_uint64(a, y);
1095
1237
  }
1096
1238
 
1239
+ case BFloat16: {
1240
+ double a = xnd_bfloat_unpack(x->ptr);
1241
+ return equal_float64(a, y);
1242
+ }
1243
+
1097
1244
  case Float16: {
1098
1245
  double a = xnd_float_unpack2((unsigned char *)x->ptr, le(t->flags));
1099
1246
  return equal_float64(a, y);
@@ -1109,6 +1256,19 @@ xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
1109
1256
  return equal_float64(a, y);
1110
1257
  }
1111
1258
 
1259
+ case BComplex32: {
1260
+ double real, imag;
1261
+
1262
+ real = xnd_bfloat_unpack(x->ptr);
1263
+ imag = xnd_bfloat_unpack(x->ptr+2);
1264
+
1265
+ if (imag == 0.0) {
1266
+ return equal_float64(real, y);
1267
+ }
1268
+
1269
+ return equal_complex128(real, imag, y);
1270
+ }
1271
+
1112
1272
  case Complex32: {
1113
1273
  double real, imag;
1114
1274
 
@@ -1172,8 +1332,8 @@ xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
1172
1332
  return 0;
1173
1333
  }
1174
1334
 
1175
- const char *a = XND_POINTER_DATA(x->ptr);
1176
- const char *b = XND_POINTER_DATA(y->ptr);
1335
+ const char *a = XND_STRING_DATA(x->ptr);
1336
+ const char *b = XND_STRING_DATA(y->ptr);
1177
1337
  return strcmp(a, b) == 0;
1178
1338
  }
1179
1339
 
@@ -1198,8 +1358,36 @@ xnd_equal(const xnd_t *x, const xnd_t *y, ndt_context_t *ctx)
1198
1358
  return memcmp(a, b, (size_t)asize) == 0;
1199
1359
  }
1200
1360
 
1361
+ case Array: {
1362
+ int64_t ashape, bshape;
1363
+
1364
+ if (u->tag != Array) {
1365
+ return 0;
1366
+ }
1367
+
1368
+ ashape = XND_ARRAY_SHAPE(x->ptr);
1369
+ bshape = XND_ARRAY_SHAPE(y->ptr);
1370
+
1371
+ if (ashape != bshape) {
1372
+ return 0;
1373
+ }
1374
+
1375
+ for (int64_t i = 0; i < ashape; i++) {
1376
+ const xnd_t xnext = xnd_array_next(x, i);
1377
+ const xnd_t ynext = xnd_array_next(y, i);
1378
+ n = xnd_equal(&xnext, &ynext, ctx);
1379
+ if (n <= 0) return n;
1380
+ }
1381
+
1382
+ return 1;
1383
+ }
1384
+
1385
+ /* NOT REACHED: intercepted by apply_stored_indices(). */
1386
+ case VarDimElem:
1201
1387
  /* NOT REACHED: intercepted by equal_ref(). */
1202
1388
  case Ref:
1389
+ ndt_err_format(ctx, NDT_RuntimeError, "unexpected VarDimElem or Ref");
1390
+ return -1;
1203
1391
 
1204
1392
  /* NOT REACHED: xnd types must be concrete. */
1205
1393
  case Module: case Function: