carray 3.0.1 → 3.0.3

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +824 -0
  3. data/README.md +5 -6
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +258 -4
  6. data/ext/ca_axis_group.c +368 -184
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +90 -41
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +960 -245
  14. data/ext/ca_kernel_iterator.h +352 -181
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +194 -42
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +5 -4
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +180 -50
  25. data/ext/ca_obj_face.c +428 -62
  26. data/ext/ca_obj_face.h +107 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +39 -26
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +235 -55
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +551 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +88 -75
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -123
  46. data/ext/ca_obj_stride.c +267 -35
  47. data/ext/ca_obj_string.c +25 -22
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +157 -29
  54. data/ext/ca_op_ipower.c +25 -13
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_rng_normal.h +42 -0
  58. data/ext/ca_rng_xoshiro256pp.h +105 -0
  59. data/ext/ca_sort_kernels.h +70 -0
  60. data/ext/ca_sweep_engine.c +385 -198
  61. data/ext/ca_sweep_engine.h +31 -23
  62. data/ext/ca_triop_dispatch.c +4 -1
  63. data/ext/ca_triop_dispatch.h +5 -2
  64. data/ext/caframe_csv_reader.c +463 -0
  65. data/ext/carray.h +90 -28
  66. data/ext/carray_access.c +487 -231
  67. data/ext/carray_address_basis.c +731 -0
  68. data/ext/carray_attribute.c +45 -3
  69. data/ext/carray_bincount.c +32 -2
  70. data/ext/carray_broadcast.c +49 -17
  71. data/ext/carray_call_cfunc.c +667 -511
  72. data/ext/carray_cast.c +1556 -247
  73. data/ext/carray_cast_func.rb +34 -21
  74. data/ext/carray_conversion.c +197 -73
  75. data/ext/carray_copy.c +84 -38
  76. data/ext/carray_core.c +591 -119
  77. data/ext/carray_count.c +148 -96
  78. data/ext/carray_element.c +18 -27
  79. data/ext/carray_factorize.c +604 -291
  80. data/ext/carray_generate.c +76 -40
  81. data/ext/carray_histogram.c +152 -94
  82. data/ext/carray_hold.c +2 -1
  83. data/ext/carray_index_classifier.c +63 -96
  84. data/ext/carray_internal.h +400 -1
  85. data/ext/carray_lazy.c +834 -79
  86. data/ext/carray_loop.c +88 -66
  87. data/ext/carray_mask.c +705 -324
  88. data/ext/carray_math_kernel.h +1 -0
  89. data/ext/carray_median_percentile.c +263 -63
  90. data/ext/carray_memory_view.c +254 -248
  91. data/ext/carray_operator.c +1093 -363
  92. data/ext/carray_order.c +133 -69
  93. data/ext/carray_partition.c +102 -56
  94. data/ext/carray_random.c +582 -204
  95. data/ext/carray_scatter.c +308 -65
  96. data/ext/carray_segment.c +257 -0
  97. data/ext/carray_slab.c +183 -70
  98. data/ext/carray_sort.c +235 -240
  99. data/ext/carray_sort_kernel.c +8 -1
  100. data/ext/carray_struct.c +99 -21
  101. data/ext/carray_test.c +167 -64
  102. data/ext/carray_time_text.c +1182 -0
  103. data/ext/carray_utils.c +363 -98
  104. data/ext/extconf.rb +27 -2
  105. data/ext/mk_call_cfunc.rb +103 -118
  106. data/ext/mk_pow5_table.rb +35 -0
  107. data/ext/mkkernel.rb +1349 -851
  108. data/ext/ruby_carray.c +17 -2
  109. data/ext/version.h +4 -4
  110. data/ext/version.rb +4 -2
  111. data/lib/carray/attribute.rb +39 -0
  112. data/lib/carray/autoload_carray.rb +24 -3
  113. data/lib/carray/autoload_method_extension.rb +18 -0
  114. data/lib/carray/axis_group.rb +245 -20
  115. data/lib/carray/basics.rb +95 -25
  116. data/lib/carray/bincount_nd.rb +6 -0
  117. data/lib/carray/block_iterator.rb +200 -54
  118. data/lib/carray/boolean_reduce.rb +21 -29
  119. data/lib/carray/categorical.rb +244 -59
  120. data/lib/carray/categorical_iterator.rb +391 -757
  121. data/lib/carray/complex.rb +36 -29
  122. data/lib/carray/conditional.rb +94 -7
  123. data/lib/carray/const_string.rb +177 -27
  124. data/lib/carray/construct.rb +40 -0
  125. data/lib/carray/data_type_extension.rb +3 -0
  126. data/lib/carray/data_type_limits.rb +91 -0
  127. data/lib/carray/fixlen_string.rb +1 -1
  128. data/lib/carray/frame/concat.rb +157 -6
  129. data/lib/carray/frame/convert.rb +13 -7
  130. data/lib/carray/frame/csv_parser.rb +590 -76
  131. data/lib/carray/frame/describe.rb +79 -0
  132. data/lib/carray/frame/frame.rb +205 -35
  133. data/lib/carray/frame/group.rb +199 -40
  134. data/lib/carray/frame/io.rb +452 -60
  135. data/lib/carray/frame/join.rb +134 -46
  136. data/lib/carray/frame/records.rb +54 -19
  137. data/lib/carray/frame/reshape.rb +448 -0
  138. data/lib/carray/frame/sort.rb +26 -2
  139. data/lib/carray/frame/verbs.rb +726 -56
  140. data/lib/carray/frame.rb +2 -0
  141. data/lib/carray/fuse_source.rb +111 -2
  142. data/lib/carray/fusion.rb +229 -38
  143. data/lib/carray/inspect.rb +71 -20
  144. data/lib/carray/iterator.rb +157 -2
  145. data/lib/carray/lazy.rb +54 -67
  146. data/lib/carray/mask_gap_fill.rb +66 -50
  147. data/lib/carray/math.rb +32 -19
  148. data/lib/carray/meld_reduce.rb +40 -7
  149. data/lib/carray/methods/align_addr.rb +8 -4
  150. data/lib/carray/methods/bincount.rb +2 -2
  151. data/lib/carray/methods/bit_string.rb +14 -3
  152. data/lib/carray/methods/composition.rb +16 -10
  153. data/lib/carray/methods/discovery_along.rb +74 -0
  154. data/lib/carray/methods/factorize.rb +50 -0
  155. data/lib/carray/methods/gather_nd.rb +13 -2
  156. data/lib/carray/methods/insert_block.rb +9 -14
  157. data/lib/carray/methods/is_in.rb +130 -6
  158. data/lib/carray/methods/join.rb +1 -1
  159. data/lib/carray/methods/locate_addr.rb +235 -21
  160. data/lib/carray/methods/mask_duplicates.rb +35 -1
  161. data/lib/carray/methods/mode.rb +18 -1
  162. data/lib/carray/methods/nunique.rb +22 -1
  163. data/lib/carray/methods/repeat.rb +91 -0
  164. data/lib/carray/methods/resize.rb +21 -23
  165. data/lib/carray/methods/snap.rb +34 -12
  166. data/lib/carray/methods/unique.rb +52 -3
  167. data/lib/carray/record_order.rb +208 -0
  168. data/lib/carray/rng.rb +86 -0
  169. data/lib/carray/runtime.rb +14 -11
  170. data/lib/carray/segment_iterator.rb +990 -0
  171. data/lib/carray/serialize.rb +197 -27
  172. data/lib/carray/slab_iterator.rb +109 -40
  173. data/lib/carray/stack.rb +10 -4
  174. data/lib/carray/string_operation_extension.rb +9 -4
  175. data/lib/carray/struct.rb +142 -51
  176. data/lib/carray/struct_builder.rb +110 -14
  177. data/lib/carray/table.rb +2 -2
  178. data/lib/carray/time.rb +535 -105
  179. data/lib/carray/window_iterator.rb +259 -82
  180. data/lib/carray.rb +4 -2
  181. data/yard-stubs/ca_obj_array.rb +4 -4
  182. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  183. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  184. data/yard-stubs/ca_obj_block.rb +2 -7
  185. data/yard-stubs/ca_obj_fake.rb +1 -1
  186. data/yard-stubs/ca_obj_field.rb +1 -1
  187. data/yard-stubs/ca_obj_refer.rb +3 -3
  188. data/yard-stubs/ca_obj_roll.rb +0 -1
  189. data/yard-stubs/ca_obj_stride.rb +10 -7
  190. data/yard-stubs/ca_obj_transpose.rb +1 -1
  191. data/yard-stubs/ca_obj_window.rb +11 -4
  192. data/yard-stubs/carray_access.rb +6 -5
  193. data/yard-stubs/carray_broadcast.rb +2 -2
  194. data/yard-stubs/carray_cast.rb +78 -43
  195. data/yard-stubs/carray_conversion.rb +13 -1
  196. data/yard-stubs/carray_copy.rb +8 -3
  197. data/yard-stubs/carray_core.rb +3 -83
  198. data/yard-stubs/carray_count.rb +16 -2
  199. data/yard-stubs/carray_lazy.rb +210 -1
  200. data/yard-stubs/carray_loop.rb +4 -1
  201. data/yard-stubs/carray_mask.rb +34 -10
  202. data/yard-stubs/carray_math.rb +1499 -4
  203. data/yard-stubs/carray_median_percentile.rb +26 -8
  204. data/yard-stubs/carray_order.rb +43 -82
  205. data/yard-stubs/carray_scatter.rb +10 -3
  206. data/yard-stubs/carray_segment.rb +72 -0
  207. data/yard-stubs/carray_slab.rb +11 -8
  208. data/yard-stubs/carray_sort.rb +50 -8
  209. data/yard-stubs/carray_test.rb +10 -0
  210. data/yard-stubs/carray_utils.rb +0 -26
  211. metadata +19 -19
  212. data/ext/ca_for_each_element.h +0 -239
  213. data/ext/carray_build_flags.h +0 -3
  214. data/ext/carray_config.h +0 -28
  215. data/ext/carray_kernels_bincmp.c +0 -4446
  216. data/ext/carray_kernels_binop.c +0 -11001
  217. data/ext/carray_kernels_init.c +0 -1131
  218. data/ext/carray_kernels_map.c +0 -3467
  219. data/ext/carray_kernels_moncmp.c +0 -2097
  220. data/ext/carray_kernels_monop.c +0 -18313
  221. data/ext/carray_kernels_reduce_aggregate.c +0 -25837
  222. data/ext/carray_kernels_reduce_boolean.c +0 -330
  223. data/ext/carray_kernels_reduce_cumulative.c +0 -14593
  224. data/ext/carray_kernels_reduce_extreme.c +0 -16948
  225. data/ext/carray_kernels_reduce_variance.c +0 -3910
  226. data/ext/carray_kernels_scan.c +0 -3693
  227. data/ext/carray_kernels_search.c +0 -32138
  228. data/ext/carray_kernels_sort.c +0 -10626
  229. data/ext/carray_kernels_triop.c +0 -1392
@@ -12,6 +12,7 @@
12
12
  ---------------------------------------------------------------------------- */
13
13
 
14
14
  #include "carray.h"
15
+ #include "carray_internal.h"
15
16
 
16
17
  typedef struct {
17
18
  int16_t obj_type;
@@ -32,6 +33,8 @@ typedef struct {
32
33
  ca_size_t bit_offset;
33
34
  uint64_t bit_mask;
34
35
  ca_size_t bit_start; /* original offset before endian adjustment */
36
+ ca_size_t bit_length; /* width of the field in bits */
37
+ int8_t sign_extend; /* the field is read as a signed integer */
35
38
  } CABitfield;
36
39
 
37
40
  static size_t
@@ -73,20 +76,6 @@ static int8_t CA_OBJ_BITFIELD;
73
76
 
74
77
  static VALUE rb_cCABitfield;
75
78
 
76
- static ca_size_t
77
- bitfield_bitlen (uint64_t bit_mask, ca_size_t bytes)
78
- {
79
- ca_size_t bitsize = bytes * 8;
80
- ca_size_t count = 0;
81
- ca_size_t i;
82
- for (i=0; i<bitsize; i++) {
83
- if ( ( bit_mask >> i ) & 1 ) {
84
- count++;
85
- }
86
- }
87
- return count;
88
- }
89
-
90
79
  /* Generic per-cell fetch: load up to 8 bytes from src starting at
91
80
  byte_offset, mask with bit_mask, shift down by bit_offset, and
92
81
  write the low `dwrite` bytes of the result to dst.
@@ -100,8 +89,10 @@ static void
100
89
  bitfield_fetch(char *dst, ca_size_t dbytes,
101
90
  char *src, ca_size_t sbytes,
102
91
  ca_size_t byte_offset, ca_size_t bit_offset, uint64_t bit_mask,
92
+ ca_size_t bit_length, int sign_extend,
103
93
  ca_size_t elements)
104
94
  {
95
+ uint64_t sign = ( sign_extend && bit_length < 64 ) ? ( 1ULL << ( bit_length - 1 ) ) : 0;
105
96
  ca_size_t k;
106
97
  ca_size_t span = sbytes - byte_offset;
107
98
  if (span > 8) span = 8;
@@ -110,6 +101,9 @@ bitfield_fetch(char *dst, ca_size_t dbytes,
110
101
  uint64_t tmp = 0;
111
102
  memcpy(&tmp, src + k * sbytes + byte_offset, (size_t) span);
112
103
  uint64_t result = (tmp & bit_mask) >> bit_offset;
104
+ if ( result & sign ) {
105
+ result |= ~( ( sign << 1 ) - 1 ); /* the field's top bit is its sign */
106
+ }
113
107
  memcpy(dst + k * dbytes, &result, (size_t) dwrite);
114
108
  }
115
109
  }
@@ -142,12 +136,14 @@ bitfield_store(char *src, ca_size_t sbytes,
142
136
 
143
137
  /* ------------------------------------------------------------------- */
144
138
 
139
+ /* `data_type` is the integer type the field is read as, or CA_NONE for
140
+ the narrowest unsigned type that holds it (boolean for one bit). A
141
+ signed type reads the field's top bit as its sign. */
145
142
  int
146
143
  ca_bitfield_setup (CABitfield *ca, CArray *parent,
147
- ca_size_t offset, ca_size_t bitlen)
144
+ ca_size_t offset, ca_size_t bitlen, int8_t data_type)
148
145
  {
149
146
  int8_t ndim;
150
- int8_t data_type;
151
147
  ca_size_t bytes = 0, elements;
152
148
  ca_size_t bitsize;
153
149
  ca_size_t byte_offset;
@@ -163,11 +159,37 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
163
159
  rb_raise(rb_eIndexError, "invalid bit length specified for bit field");
164
160
  }
165
161
 
166
- if ( offset + bitlen -1 >= bitsize ) {
162
+ if ( offset < 0 || offset + bitlen -1 >= bitsize ) {
167
163
  rb_raise(rb_eIndexError, "invalid offset for bit field");
168
164
  }
169
165
 
170
- if ( bitlen == 1 ) {
166
+ /* The bits of an object cell are a reference: writing them would leave
167
+ the cell pointing nowhere. A complex cell is refused as bitarray
168
+ refuses it. */
169
+ if ( ca_is_object_type(parent) || ca_is_complex_type(parent) ) {
170
+ rb_raise(rb_eCADataTypeError, "invalid data_type for bitfield");
171
+ }
172
+
173
+ /* A field is read with one 8-byte load from the byte it starts in. */
174
+ if ( offset % 8 + bitlen > 64 ) {
175
+ rb_raise(rb_eIndexError,
176
+ "a bit field of %lld bits at bit %lld spans more than 8 bytes",
177
+ (long long) bitlen, (long long) offset);
178
+ }
179
+
180
+ if ( data_type != CA_NONE ) {
181
+ switch ( data_type ) {
182
+ case CA_BOOLEAN:
183
+ case CA_INT8: case CA_UINT8: case CA_INT16: case CA_UINT16:
184
+ case CA_INT32: case CA_UINT32: case CA_INT64: case CA_UINT64:
185
+ break;
186
+ default:
187
+ rb_raise(rb_eCADataTypeError,
188
+ "a bit field is read as an integer type, not <%s>",
189
+ ca_type_name[data_type]);
190
+ }
191
+ }
192
+ else if ( bitlen == 1 ) {
171
193
  data_type = CA_BOOLEAN;
172
194
  }
173
195
  else if ( bitlen <= 8 ) {
@@ -185,16 +207,18 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
185
207
 
186
208
  CA_CHECK_BYTES(data_type, bytes);
187
209
 
188
- if ( bitlen > bytes * 8 ) {
189
- rb_raise(rb_eArgError, "invalid bit length for specified data_type");
190
- }
191
-
192
- if ( ( data_type == CA_BOOLEAN ) && ( bitlen > 1 ) ) {
193
- rb_raise(rb_eArgError, "invalid bit length for specified data_type");
210
+ if ( bitlen > bytes * 8 ||
211
+ ( ( data_type == CA_BOOLEAN ) && ( bitlen > 1 ) ) ) {
212
+ rb_raise(rb_eArgError, "a bit field of %lld bits does not fit <%s>",
213
+ (long long) bitlen, ca_type_name[data_type]);
194
214
  }
195
215
 
196
216
  if ( ca_endian == CA_BIG_ENDIAN ) {
197
- byte_offset = parent->bytes - offset/8 - bytes;
217
+ /* The window is placed by the narrowest width that holds the field,
218
+ not by the type it is read as, which may be wider. */
219
+ ca_size_t window = ( bitlen <= 8 ) ? 1 : ( bitlen <= 16 ) ? 2 :
220
+ ( bitlen <= 32 ) ? 4 : 8;
221
+ byte_offset = parent->bytes - offset/8 - window;
198
222
  bit_offset = offset % 8;
199
223
  bit_mask = 0;
200
224
  for (i=0; i<bitlen; i++) {
@@ -217,6 +241,12 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
217
241
  }
218
242
  }
219
243
 
244
+ /* ca == NULL asks for the checks above only, so that a constructor can
245
+ run them before it allocates. */
246
+ if ( ca == NULL ) {
247
+ return 0;
248
+ }
249
+
220
250
  ca->obj_type = CA_OBJ_BITFIELD;
221
251
  ca->data_type = data_type;
222
252
  ca->flags = 0;
@@ -237,6 +267,9 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
237
267
  ca->bit_offset = bit_offset;
238
268
  ca->bit_mask = bit_mask;
239
269
  ca->bit_start = offset; /* preserve original offset for clone/copy */
270
+ ca->bit_length = bitlen;
271
+ ca->sign_extend = ( data_type == CA_INT8 || data_type == CA_INT16 ||
272
+ data_type == CA_INT32 || data_type == CA_INT64 );
240
273
 
241
274
  memcpy(ca->dim, parent->dim, ndim * sizeof(ca_size_t));
242
275
 
@@ -248,10 +281,13 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
248
281
  }
249
282
 
250
283
  CABitfield *
251
- ca_bitfield_new (CArray *parent, ca_size_t offset, ca_size_t bitlen)
284
+ ca_bitfield_new (CArray *parent, ca_size_t offset, ca_size_t bitlen,
285
+ int8_t data_type)
252
286
  {
253
- CABitfield *ca = (CABitfield *) ca_array_alloc(CA_OBJ_BITFIELD, parent->ndim);
254
- ca_bitfield_setup(ca, parent, offset, bitlen);
287
+ CABitfield *ca;
288
+ ca_bitfield_setup(NULL, parent, offset, bitlen, data_type);
289
+ ca = (CABitfield *) ca_array_alloc(CA_OBJ_BITFIELD, parent->ndim);
290
+ ca_bitfield_setup(ca, parent, offset, bitlen, data_type);
255
291
  return ca;
256
292
  }
257
293
 
@@ -281,9 +317,8 @@ static void *
281
317
  ca_bitfield_func_clone (void *ap)
282
318
  {
283
319
  CABitfield *ca = (CABitfield *) ap;
284
- return ca_bitfield_new(ca->parent,
285
- ca->bit_start,
286
- bitfield_bitlen(ca->bit_mask, ca->bytes));
320
+ return ca_bitfield_new(ca->parent, ca->bit_start, ca->bit_length,
321
+ ca->data_type);
287
322
  }
288
323
 
289
324
  /* Per-cell get/put: fetch the parent cell into a scratch buffer,
@@ -293,19 +328,21 @@ static void
293
328
  ca_bitfield_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
294
329
  {
295
330
  CABitfield *ca = (CABitfield *) ap;
296
- char *v = xmalloc(ca->parent->bytes);
331
+ volatile VALUE holder;
332
+ char *v = ALLOCV_N(char, holder, ca->parent->bytes);
297
333
  ca_fetch_index(ca->parent, idx, v);
298
334
  if ( dir == CA_XFER_GET ) {
299
335
  memset(data, 0, ca->bytes);
300
336
  bitfield_fetch(data, ca->bytes, v, ca->parent->bytes,
301
- ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
337
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
338
+ ca->bit_length, ca->sign_extend, 1);
302
339
  }
303
340
  else {
304
341
  bitfield_store(data, ca->bytes, v, ca->parent->bytes,
305
342
  ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
306
343
  ca_store_index(ca->parent, idx, v);
307
344
  }
308
- xfree(v);
345
+ ALLOCV_END(holder);
309
346
  }
310
347
 
311
348
  /* Batched gather / scatter. CABitfield is a 1:1 view (each parent
@@ -342,7 +379,8 @@ ca_bitfield_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
342
379
  directly from the attached parent. */
343
380
  memset(d, 0, n * ca->bytes);
344
381
  bitfield_fetch(d, ca->bytes, eff_parent->ptr, pbytes,
345
- ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
382
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
383
+ ca->bit_length, ca->sign_extend, n);
346
384
  } else {
347
385
  /* Bulk RMW directly against parent memory (bitfield_store
348
386
  preserves non-field bits). */
@@ -359,7 +397,8 @@ ca_bitfield_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
359
397
  for (i = 0; i < n; i++) {
360
398
  memset(d + i * ca->bytes, 0, ca->bytes);
361
399
  bitfield_fetch(d + i * ca->bytes, ca->bytes, v + i * pbytes, pbytes,
362
- ca->byte_offset, ca->bit_offset, ca->bit_mask, 1);
400
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
401
+ ca->bit_length, ca->sign_extend, 1);
363
402
  }
364
403
  }
365
404
  else {
@@ -382,6 +421,7 @@ static void
382
421
  ca_bitfield_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
383
422
  ca_size_t *strides, void *data, int dir)
384
423
  {
424
+ if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
385
425
  CABitfield *ca = (CABitfield *) ap;
386
426
  int8_t ndim = ca->ndim;
387
427
  ca_size_t native[CA_RANK_MAX], idx[CA_RANK_MAX];
@@ -467,7 +507,8 @@ ca_bitfield_func_xfer_all (void *ap, void *data, int dir)
467
507
  if ( dir == CA_XFER_GET ) {
468
508
  memset(d, 0, n * ca->bytes);
469
509
  bitfield_fetch(d, ca->bytes, eff_parent->ptr, pbytes,
470
- ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
510
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
511
+ ca->bit_length, ca->sign_extend, n);
471
512
  } else {
472
513
  bitfield_store(d, ca->bytes, eff_parent->ptr, pbytes,
473
514
  ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
@@ -491,7 +532,8 @@ ca_bitfield_func_xfer_all (void *ap, void *data, int dir)
491
532
  ca_xfer_stride(parent, pstarts, parent->dim, pnative, scratch, CA_XFER_GET);
492
533
  memset(d, 0, n * ca->bytes);
493
534
  bitfield_fetch(d, ca->bytes, scratch, pbytes,
494
- ca->byte_offset, ca->bit_offset, ca->bit_mask, n);
535
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
536
+ ca->bit_length, ca->sign_extend, n);
495
537
  } else {
496
538
  /* CAREFUL: gather parent into scratch before splicing so the
497
539
  non-field bits are preserved across the RMW. */
@@ -510,8 +552,7 @@ ca_bitfield_func_fill_data (void *ap, void *ptr)
510
552
  CABitfield *ca = (CABitfield *) ap;
511
553
  ca_attach(ca->parent);
512
554
  ca_bitfield_fill(ca, ptr);
513
- ca_sync(ca->parent);
514
- ca_detach(ca->parent);
555
+ ca_sync_detach(ca->parent);
515
556
  }
516
557
 
517
558
 
@@ -542,20 +583,6 @@ ca_bitfield_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
542
583
  ca_fill_stride_via_addrs(ap, base, ndim, counts, steps, ptr);
543
584
  }
544
585
 
545
- static void
546
- ca_bitfield_func_create_mask (void *ap)
547
- {
548
- CABitfield *ca = (CABitfield *) ap;
549
-
550
- ca_update_mask(ca->parent);
551
- if ( ! ca->parent->mask ) {
552
- ca_create_mask(ca->parent);
553
- }
554
-
555
- ca->mask = (CArray *) ca_refer_new(ca->parent->mask,
556
- CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
557
- }
558
-
559
586
  ca_operation_function_t ca_bitfield_func = {
560
587
  -1, /* CA_OBJ_BITFIELD */
561
588
  CA_VIEW_ARRAY,
@@ -566,7 +593,7 @@ ca_operation_function_t ca_bitfield_func = {
566
593
  ca_bitfield_func_sync,
567
594
  ca_bitfield_func_detach,
568
595
  ca_bitfield_func_fill_data,
569
- ca_bitfield_func_create_mask,
596
+ ca_view_func_create_mask,
570
597
  ca_bitfield_func_xfer_index,
571
598
  ca_bitfield_func_xfer_addrs,
572
599
  NULL, /* fold_stride: never fold — per-cell bit transform */
@@ -583,7 +610,8 @@ ca_bitfield_attach (CABitfield *ca)
583
610
  {
584
611
  memset(ca->ptr, 0, ca_length(ca));
585
612
  bitfield_fetch(ca->ptr, ca->bytes, ca->parent->ptr, ca->parent->bytes,
586
- ca->byte_offset, ca->bit_offset, ca->bit_mask, ca->elements);
613
+ ca->byte_offset, ca->bit_offset, ca->bit_mask,
614
+ ca->bit_length, ca->sign_extend, ca->elements);
587
615
  }
588
616
 
589
617
  static void
@@ -614,14 +642,15 @@ ca_bitfield_fill (CABitfield *ca, char *ptr)
614
642
  /* ------------------------------------------------------------------- */
615
643
 
616
644
  VALUE
617
- rb_ca_bitfield_new (VALUE cary, ca_size_t offset, ca_size_t bitlen)
645
+ rb_ca_bitfield_new (VALUE cary, ca_size_t offset, ca_size_t bitlen,
646
+ int8_t data_type)
618
647
  {
619
648
  volatile VALUE obj;
620
649
  CArray *parent;
621
650
  CABitfield *ca;
622
651
  rb_check_carray_object(cary);
623
652
  TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
624
- ca = ca_bitfield_new(parent, offset, bitlen);
653
+ ca = ca_bitfield_new(parent, offset, bitlen, data_type);
625
654
  obj = ca_wrap_struct(ca);
626
655
  rb_ca_set_parent(obj, cary);
627
656
  return obj;
@@ -641,6 +670,9 @@ rb_ca_bitfield (int argc, VALUE *argv, VALUE self)
641
670
 
642
671
  if ( TYPE(rrange) == T_FIXNUM ) {
643
672
  offset = NUM2INT(rrange);
673
+ if ( offset < 0 ) {
674
+ offset += ca->bytes * 8;
675
+ }
644
676
  bitlen = 1;
645
677
  }
646
678
  else {
@@ -651,7 +683,8 @@ rb_ca_bitfield (int argc, VALUE *argv, VALUE self)
651
683
  }
652
684
  }
653
685
 
654
- return rb_ca_bitfield_new(self, offset, bitlen);
686
+ return rb_ca_bitfield_new(self, offset, bitlen,
687
+ NIL_P(rtype) ? CA_NONE : rb_ca_guess_type(rtype));
655
688
  }
656
689
 
657
690
  static VALUE
@@ -667,14 +700,14 @@ rb_ca_bitfield_initialize_copy (VALUE self, VALUE other)
667
700
  CABitfield *ca, *cs;
668
701
 
669
702
  TypedData_Get_Struct(self, CABitfield, &cabitfield_data_type, ca);
703
+ ca_check_uninitialized(ca);
670
704
  TypedData_Get_Struct(other, CABitfield, &cabitfield_data_type, cs);
671
705
 
672
706
  if ( ca_func[CA_OBJ_BITFIELD].pool_init ) {
673
707
  ca_array_pool_alloc(ca, CA_OBJ_BITFIELD, cs->parent->ndim);
674
708
  }
675
- ca_bitfield_setup(ca, cs->parent,
676
- cs->bit_start,
677
- bitfield_bitlen(cs->bit_mask, cs->bytes));
709
+ ca_bitfield_setup(ca, cs->parent, cs->bit_start, cs->bit_length,
710
+ cs->data_type);
678
711
 
679
712
  return self;
680
713
  }
data/ext/ca_obj_block.c CHANGED
@@ -254,6 +254,7 @@ rb_cb_initialize_copy (VALUE self, VALUE other)
254
254
  {
255
255
  CABlock *ca, *cs;
256
256
  TypedData_Get_Struct(self, CABlock, &cablock_data_type, ca);
257
+ ca_check_uninitialized(ca);
257
258
  TypedData_Get_Struct(other, CABlock, &cablock_data_type, cs);
258
259
  /* `self` was created by rb_cb_s_allocate (TypedData_Make_Struct) with
259
260
  ca->_pool == NULL. Wire up the pool before ca_block_setup so the
@@ -269,8 +270,10 @@ rb_cb_initialize_copy (VALUE self, VALUE other)
269
270
  }
270
271
 
271
272
  /* Per-axis accessor macro: defines a method that returns the named
272
- CABlock tail array (size0 / start / step / count) as a Ruby Array.
273
- `offset` is a single Integer and uses its own accessor below. */
273
+ CABlock tail array (size0 / start / step) as a Ruby Array.
274
+ `offset` is a single Integer and uses its own accessor below.
275
+ `count` has no accessor: it is what `shape` already answers, and the
276
+ name belongs to CArray#count. */
274
277
  #define rb_cb_get_attr_ary(name) \
275
278
  rb_cb_ ## name (VALUE self) \
276
279
  { \
@@ -288,7 +291,6 @@ rb_cb_ ## name (VALUE self) \
288
291
  static VALUE rb_cb_get_attr_ary(size0)
289
292
  static VALUE rb_cb_get_attr_ary(start)
290
293
  static VALUE rb_cb_get_attr_ary(step)
291
- static VALUE rb_cb_get_attr_ary(count)
292
294
 
293
295
  static VALUE
294
296
  rb_cb_offset (VALUE self)
@@ -376,7 +378,6 @@ Init_ca_obj_block (void)
376
378
  rb_define_method(rb_cCABlock, "size0", rb_cb_size0, 0);
377
379
  rb_define_method(rb_cCABlock, "start", rb_cb_start, 0);
378
380
  rb_define_method(rb_cCABlock, "step", rb_cb_step, 0);
379
- rb_define_method(rb_cCABlock, "count", rb_cb_count, 0);
380
381
  rb_define_method(rb_cCABlock, "offset", rb_cb_offset, 0);
381
382
 
382
383
  rb_define_method(rb_cCABlock, "idx2addr0", rb_cb_idx2addr0, -1);
@@ -13,6 +13,7 @@
13
13
  ---------------------------------------------------------------------------- */
14
14
 
15
15
  #include "carray.h"
16
+ #include "carray_internal.h"
16
17
  #include "ca_iter_substrate.h" /* ca_xfer_stride_transform_fused */
17
18
  #include "ca_monop_dispatch.h" /* CA_MONOP_BYTE_SWAP dispatch id */
18
19
  #include "ca_obj_face.h" /* CA_FACE_LIFT_IF_FACE for CARecord parent */
@@ -198,6 +199,12 @@ ca_byte_swap_setup (CAByteSwap *ca, CArray *parent, VALUE data_class)
198
199
  rb_raise(rb_eCADataTypeError, "object array can't be byte-swapped");
199
200
  }
200
201
 
202
+ /* ca == NULL asks for the checks above only, so that a constructor can
203
+ run them before it allocates. */
204
+ if ( ca == NULL ) {
205
+ return 0;
206
+ }
207
+
201
208
  ca->obj_type = CA_OBJ_BYTE_SWAP;
202
209
  ca->data_type = parent->data_type;
203
210
  ca->flags = 0;
@@ -229,7 +236,9 @@ ca_byte_swap_setup (CAByteSwap *ca, CArray *parent, VALUE data_class)
229
236
  CAByteSwap *
230
237
  ca_byte_swap_new (CArray *parent, VALUE data_class)
231
238
  {
232
- CAByteSwap *ca = (CAByteSwap *) ca_array_alloc(CA_OBJ_BYTE_SWAP, parent->ndim);
239
+ CAByteSwap *ca;
240
+ ca_byte_swap_setup(NULL, parent, data_class);
241
+ ca = (CAByteSwap *) ca_array_alloc(CA_OBJ_BYTE_SWAP, parent->ndim);
233
242
  ca_byte_swap_setup(ca, parent, data_class);
234
243
  return ca;
235
244
  }
@@ -319,12 +328,12 @@ ca_byte_swap_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
319
328
  ca_byte_swap_apply_one(ca, (char *) data);
320
329
  }
321
330
  else {
322
- char v[32];
323
- char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
331
+ volatile VALUE holder;
332
+ char *buf = ALLOCV_N(char, holder, ca->bytes);
324
333
  memcpy(buf, data, ca->bytes);
325
334
  ca_byte_swap_apply_one(ca, buf);
326
335
  ca_store_index(ca->parent, idx, buf);
327
- if ( buf != v ) xfree(buf);
336
+ ALLOCV_END(holder);
328
337
  }
329
338
  }
330
339
 
@@ -405,6 +414,7 @@ static void
405
414
  ca_byte_swap_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
406
415
  ca_size_t *strides, void *data, int dir)
407
416
  {
417
+ if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
408
418
  CAByteSwap *ca = (CAByteSwap *) ap;
409
419
  char *d = (char *) data;
410
420
  int is_struct = ( ca->data_type == CA_FIXLEN && RTEST(ca->data_class) );
@@ -471,10 +481,17 @@ static void
471
481
  ca_byte_swap_func_sync (void *ap)
472
482
  {
473
483
  CAByteSwap *ca = (CAByteSwap *) ap;
474
- /* Swap is involutive, so applying it once to the view buffer
475
- restores the parent byte order before the copy-back. */
476
- ca_byte_swap_apply(ca, ca->ptr);
477
- memcpy(ca->parent->ptr, ca->ptr, ca_length(ca));
484
+ /* Swap is involutive, so applying it once to a copy of the view buffer
485
+ restores the parent byte order. Not the view buffer in place: the
486
+ window stays open after a sync, and a second sync (a stack holding
487
+ this view twice) would swap it again. The swap of a record calls
488
+ Ruby, so it runs on the copy and reaches the parent only whole. */
489
+ volatile VALUE holder;
490
+ char *tmp = ALLOCV_N(char, holder, ca_length(ca));
491
+ memcpy(tmp, ca->ptr, ca_length(ca));
492
+ ca_byte_swap_apply(ca, tmp);
493
+ memcpy(ca->parent->ptr, tmp, ca_length(ca));
494
+ ALLOCV_END(holder);
478
495
  ca_sync(ca->parent);
479
496
  }
480
497
 
@@ -509,8 +526,8 @@ static void
509
526
  ca_byte_swap_func_fill_data (void *ap, void *ptr)
510
527
  {
511
528
  CAByteSwap *ca = (CAByteSwap *) ap;
512
- char v[32];
513
- char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
529
+ volatile VALUE holder;
530
+ char *buf = ALLOCV_N(char, holder, ca->bytes);
514
531
  memcpy(buf, ptr, ca->bytes);
515
532
  if ( !ca_byte_swap_apply_one(ca, buf) ) {
516
533
  /* Bare CA_FIXLEN fill: broadcast the raw bytes into the view
@@ -523,13 +540,12 @@ ca_byte_swap_func_fill_data (void *ap, void *ptr)
523
540
  memcpy(ca->ptr + i * ca->bytes, ptr, ca->bytes);
524
541
  }
525
542
  }
526
- ca_sync(ca);
527
- ca_detach(ca);
528
- if ( buf != v ) xfree(buf);
543
+ ca_sync_detach(ca);
544
+ ALLOCV_END(holder);
529
545
  return;
530
546
  }
531
547
  ca_fill(ca->parent, buf);
532
- if ( buf != v ) xfree(buf);
548
+ ALLOCV_END(holder);
533
549
  }
534
550
 
535
551
  /* fill_data with a region. Swapping is per value, not per cell, so the one
@@ -543,8 +559,8 @@ ca_byte_swap_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
543
559
  ca_size_t *counts, ca_size_t *steps, void *ptr)
544
560
  {
545
561
  CAByteSwap *ca = (CAByteSwap *) ap;
546
- char v[32];
547
- char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
562
+ volatile VALUE holder;
563
+ char *buf = ALLOCV_N(char, holder, ca->bytes);
548
564
  memcpy(buf, ptr, ca->bytes);
549
565
  if ( ca_byte_swap_apply_one(ca, buf) ) {
550
566
  ca_fill_stride(ca->parent, base, ndim, counts, steps, buf);
@@ -552,7 +568,7 @@ ca_byte_swap_func_fill_stride (void *ap, ca_size_t base, int8_t ndim,
552
568
  else {
553
569
  ca_fill_stride_default(ca, base, ndim, counts, steps, ptr);
554
570
  }
555
- if ( buf != v ) xfree(buf);
571
+ ALLOCV_END(holder);
556
572
  }
557
573
 
558
574
  static void
@@ -560,8 +576,8 @@ ca_byte_swap_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
560
576
  void *ptr)
561
577
  {
562
578
  CAByteSwap *ca = (CAByteSwap *) ap;
563
- char v[32];
564
- char *buf = (ca->bytes <= 32) ? v : xmalloc(ca->bytes);
579
+ volatile VALUE holder;
580
+ char *buf = ALLOCV_N(char, holder, ca->bytes);
565
581
  memcpy(buf, ptr, ca->bytes);
566
582
  if ( ca_byte_swap_apply_one(ca, buf) ) {
567
583
  ca_fill_addrs(ca->parent, n, addrs, buf);
@@ -569,23 +585,7 @@ ca_byte_swap_func_fill_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
569
585
  else {
570
586
  ca_fill_addrs_default(ca, n, addrs, ptr);
571
587
  }
572
- if ( buf != v ) xfree(buf);
573
- }
574
-
575
- static void
576
- ca_byte_swap_func_create_mask (void *ap)
577
- {
578
- CAByteSwap *ca = (CAByteSwap *) ap;
579
- ca_update_mask(ca->parent);
580
- if ( ! ca->parent->mask ) {
581
- ca_create_mask(ca->parent);
582
- }
583
- /* Mask is byte-wide (boolean), so the swap is a no-op for the
584
- mask itself. Share the parent's mask via a CARefer to keep the
585
- two in lockstep. */
586
- ca->mask =
587
- (CArray *) ca_refer_new(ca->parent->mask,
588
- CA_BOOLEAN, ca->ndim, ca->dim, 0, 0);
588
+ ALLOCV_END(holder);
589
589
  }
590
590
 
591
591
  ca_operation_function_t ca_byte_swap_func = {
@@ -598,7 +598,7 @@ ca_operation_function_t ca_byte_swap_func = {
598
598
  ca_byte_swap_func_sync,
599
599
  ca_byte_swap_func_detach,
600
600
  ca_byte_swap_func_fill_data,
601
- ca_byte_swap_func_create_mask,
601
+ ca_view_func_create_mask,
602
602
  ca_byte_swap_func_xfer_index,
603
603
  ca_byte_swap_func_xfer_addrs,
604
604
  NULL, /* fold_stride: never fold — value-conversion boundary */
@@ -658,6 +658,7 @@ rb_ca_byte_swap_initialize_copy (VALUE self, VALUE other)
658
658
  {
659
659
  CAByteSwap *ca, *cs;
660
660
  TypedData_Get_Struct(self, CAByteSwap, &cabyteswap_data_type, ca);
661
+ ca_check_uninitialized(ca);
661
662
  TypedData_Get_Struct(other, CAByteSwap, &cabyteswap_data_type, cs);
662
663
  if ( ca_func[CA_OBJ_BYTE_SWAP].pool_init ) {
663
664
  ca_array_pool_alloc(ca, CA_OBJ_BYTE_SWAP, cs->parent->ndim);
@@ -732,10 +733,9 @@ rb_ca_swap_bytes_bang (VALUE self)
732
733
  }
733
734
 
734
735
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
735
- ca_attach(ca);
736
+ ca_attach(ca); /* window: nothing raises inside */
736
737
  ca_byte_swap_buffer(ca->data_type, ca->bytes, ca->elements, ca->ptr);
737
- ca_sync(ca);
738
- ca_detach(ca);
738
+ ca_sync_detach(ca);
739
739
  return self;
740
740
  }
741
741