carray 3.0.4 → 3.0.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +205 -0
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +13 -20
- data/ext/ca_categorical_iterator.c +27 -20
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +6 -6
- data/ext/ca_kernel_iterator.h +112 -83
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +1 -0
- data/ext/ca_obj_binop.c +1 -0
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +58 -43
- data/ext/ca_obj_byte_swap.c +2 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +42 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +52 -5
- data/ext/ca_obj_monop.c +46 -10
- data/ext/ca_obj_object.c +64 -12
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +4 -0
- data/ext/ca_obj_refer.c +18 -9
- data/ext/ca_obj_roll.c +26 -6
- data/ext/ca_obj_select.c +34 -5
- data/ext/ca_obj_shift.c +31 -7
- data/ext/ca_obj_stack.c +1 -0
- data/ext/ca_obj_stride.c +28 -19
- data/ext/ca_obj_string.c +11 -2
- data/ext/ca_obj_tile.c +27 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +3 -0
- data/ext/ca_obj_window.c +79 -50
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/carray.h +33 -0
- data/ext/carray_access.c +16 -3
- data/ext/carray_attribute.c +24 -0
- data/ext/carray_cast.c +243 -82
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +2 -2
- data/ext/carray_core.c +3 -0
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +9 -4
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +1 -1
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +12 -0
- data/ext/carray_kernels_bincmp.c +168 -168
- data/ext/carray_kernels_binop.c +900 -900
- data/ext/carray_kernels_init.c +4 -4
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +1984 -1984
- data/ext/carray_kernels_reduce_aggregate.c +1733 -1733
- data/ext/carray_kernels_reduce_cumulative.c +642 -642
- data/ext/carray_kernels_reduce_extreme.c +1150 -1150
- data/ext/carray_kernels_reduce_variance.c +258 -258
- data/ext/carray_kernels_scan.c +128 -128
- data/ext/carray_kernels_search.c +340 -340
- data/ext/carray_kernels_sort.c +295 -304
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_mask.c +45 -22
- data/ext/carray_memory_view.c +2 -2
- data/ext/carray_operator.c +5 -5
- data/ext/carray_order.c +227 -8
- data/ext/carray_random.c +18 -18
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +32 -9
- data/ext/carray_sort.c +224 -16
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +35 -43
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_utils.c +63 -21
- data/ext/mkkernel.rb +210 -115
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +17 -4
- data/lib/carray/basics.rb +27 -7
- data/lib/carray/categorical.rb +30 -16
- data/lib/carray/categorical_iterator.rb +6 -6
- data/lib/carray/const_string.rb +10 -0
- data/lib/carray/data_type_extension.rb +8 -1
- data/lib/carray/fixlen_string.rb +41 -2
- data/lib/carray/frame/column_verbs.rb +4 -3
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/frame.rb +6 -7
- data/lib/carray/frame/group.rb +100 -13
- data/lib/carray/frame/io.rb +3 -1
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/lazy.rb +35 -0
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/segment_iterator.rb +12 -8
- data/lib/carray/serialize.rb +19 -2
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +8 -0
- data/lib/carray/string_operation_extension.rb +13 -5
- data/lib/carray/struct_builder.rb +5 -3
- data/lib/carray/time.rb +107 -68
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +2 -0
- data/yard-stubs/carray_conversion.rb +5 -1
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +8 -3
- data/yard-stubs/carray_math.rb +14 -4
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- metadata +1 -1
data/ext/ca_obj_array.c
CHANGED
|
@@ -144,7 +144,6 @@ carray_setup_i (CArray *ca,
|
|
|
144
144
|
CArray *mask, int allocate, int use_calloc, char *adopt_ptr)
|
|
145
145
|
{
|
|
146
146
|
ca_size_t elements;
|
|
147
|
-
int8_t i;
|
|
148
147
|
ca_size_t k;
|
|
149
148
|
|
|
150
149
|
/* check arguments */
|
|
@@ -295,26 +294,54 @@ carray_new_with_mask (CArray *ca, CArray *mask)
|
|
|
295
294
|
return ca;
|
|
296
295
|
}
|
|
297
296
|
|
|
297
|
+
typedef struct {
|
|
298
|
+
CArray *ca;
|
|
299
|
+
int8_t data_type;
|
|
300
|
+
int8_t ndim;
|
|
301
|
+
ca_size_t *dim;
|
|
302
|
+
ca_size_t bytes;
|
|
303
|
+
int use_calloc;
|
|
304
|
+
} carray_new_arg;
|
|
305
|
+
|
|
306
|
+
static VALUE
|
|
307
|
+
carray_new_setup (VALUE varg)
|
|
308
|
+
{
|
|
309
|
+
carray_new_arg *a = (carray_new_arg *) varg;
|
|
310
|
+
carray_setup_i(a->ca, a->data_type, a->ndim, a->dim, a->bytes, NULL,
|
|
311
|
+
1, a->use_calloc, NULL);
|
|
312
|
+
return Qnil;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* The setup allocates the cells, after the struct: when that fails, the
|
|
316
|
+
struct goes too. */
|
|
317
|
+
static CArray *
|
|
318
|
+
carray_new_i (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
319
|
+
CArray *mask, int use_calloc)
|
|
320
|
+
{
|
|
321
|
+
carray_new_arg a;
|
|
322
|
+
carray_setup_i(NULL, data_type, ndim, dim, bytes, NULL, 1, use_calloc, NULL);
|
|
323
|
+
a.ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
|
|
324
|
+
a.data_type = data_type;
|
|
325
|
+
a.ndim = ndim;
|
|
326
|
+
a.dim = dim;
|
|
327
|
+
a.bytes = bytes;
|
|
328
|
+
a.use_calloc = use_calloc;
|
|
329
|
+
ca_fill_or_free(a.ca, carray_new_setup, (VALUE) &a);
|
|
330
|
+
return carray_new_with_mask(a.ca, mask);
|
|
331
|
+
}
|
|
332
|
+
|
|
298
333
|
CArray *
|
|
299
334
|
carray_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
300
335
|
CArray *mask)
|
|
301
336
|
{
|
|
302
|
-
|
|
303
|
-
carray_setup(NULL, data_type, ndim, dim, bytes, NULL);
|
|
304
|
-
ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
|
|
305
|
-
carray_setup(ca, data_type, ndim, dim, bytes, NULL);
|
|
306
|
-
return carray_new_with_mask(ca, mask);
|
|
337
|
+
return carray_new_i(data_type, ndim, dim, bytes, mask, 0);
|
|
307
338
|
}
|
|
308
339
|
|
|
309
340
|
CArray *
|
|
310
341
|
carray_new_safe (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
|
|
311
342
|
CArray *mask)
|
|
312
343
|
{
|
|
313
|
-
|
|
314
|
-
carray_safe_setup(NULL, data_type, ndim, dim, bytes, NULL);
|
|
315
|
-
ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
|
|
316
|
-
carray_safe_setup(ca, data_type, ndim, dim, bytes, NULL);
|
|
317
|
-
return carray_new_with_mask(ca, mask);
|
|
344
|
+
return carray_new_i(data_type, ndim, dim, bytes, mask, 1);
|
|
318
345
|
}
|
|
319
346
|
|
|
320
347
|
/* Create an entity that adopts a caller-provided data buffer instead of
|
|
@@ -440,13 +467,39 @@ cscalar_setup (CScalar *ca,
|
|
|
440
467
|
* constructs a CScalar struct without initialization
|
|
441
468
|
*/
|
|
442
469
|
|
|
470
|
+
typedef struct {
|
|
471
|
+
CScalar *ca;
|
|
472
|
+
int8_t data_type;
|
|
473
|
+
ca_size_t bytes;
|
|
474
|
+
} cscalar_new_arg;
|
|
475
|
+
|
|
476
|
+
static VALUE
|
|
477
|
+
cscalar_new_setup (VALUE varg)
|
|
478
|
+
{
|
|
479
|
+
cscalar_new_arg *a = (cscalar_new_arg *) varg;
|
|
480
|
+
cscalar_setup(a->ca, a->data_type, a->bytes, NULL);
|
|
481
|
+
return Qnil;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* The setup allocates the cell after the struct: when that fails, the
|
|
485
|
+
struct goes too. It goes by xfree, not ca_free, because its ptr was
|
|
486
|
+
never set. */
|
|
487
|
+
static CScalar *
|
|
488
|
+
cscalar_new_i (int8_t data_type, ca_size_t bytes)
|
|
489
|
+
{
|
|
490
|
+
cscalar_new_arg a;
|
|
491
|
+
cscalar_setup(NULL, data_type, bytes, NULL);
|
|
492
|
+
a.ca = ALLOC(CScalar);
|
|
493
|
+
a.data_type = data_type;
|
|
494
|
+
a.bytes = bytes;
|
|
495
|
+
ca_fill_or_xfree(a.ca, cscalar_new_setup, (VALUE) &a);
|
|
496
|
+
return a.ca;
|
|
497
|
+
}
|
|
498
|
+
|
|
443
499
|
CScalar *
|
|
444
500
|
cscalar_new (int8_t data_type, ca_size_t bytes, CArray *mask)
|
|
445
501
|
{
|
|
446
|
-
CScalar *ca;
|
|
447
|
-
cscalar_setup(NULL, data_type, bytes, NULL);
|
|
448
|
-
ca = ALLOC(CScalar);
|
|
449
|
-
cscalar_setup(ca, data_type, bytes, NULL);
|
|
502
|
+
CScalar *ca = cscalar_new_i(data_type, bytes);
|
|
450
503
|
return (CScalar *) carray_new_with_mask((CArray *) ca, mask);
|
|
451
504
|
}
|
|
452
505
|
|
|
@@ -457,10 +510,7 @@ cscalar_new (int8_t data_type, ca_size_t bytes, CArray *mask)
|
|
|
457
510
|
CScalar *
|
|
458
511
|
cscalar_new2 (int8_t data_type, ca_size_t bytes, char *val)
|
|
459
512
|
{
|
|
460
|
-
CScalar *ca;
|
|
461
|
-
cscalar_setup(NULL, data_type, bytes, NULL);
|
|
462
|
-
ca = ALLOC(CScalar);
|
|
463
|
-
cscalar_setup(ca, data_type, bytes, NULL);
|
|
513
|
+
CScalar *ca = cscalar_new_i(data_type, bytes);
|
|
464
514
|
memcpy(ca->ptr, val, ca->bytes);
|
|
465
515
|
return ca;
|
|
466
516
|
}
|
data/ext/ca_obj_bincmp.c
CHANGED
|
@@ -647,6 +647,7 @@ rb_ca_bincmp_build (VALUE l_cary, VALUE r_cary, uint16_t op_id, double eps)
|
|
|
647
647
|
r_resolved = ca_lazy_settle_scalar(r_resolved, r_scalar);
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
+
ca_refuse_without_common_type(l_resolved, r_resolved);
|
|
650
651
|
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
651
652
|
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
652
653
|
|
data/ext/ca_obj_binop.c
CHANGED
|
@@ -569,6 +569,7 @@ rb_ca_binop_build (VALUE l_cary, VALUE r_cary, uint16_t op_id)
|
|
|
569
569
|
r_resolved = ca_lazy_settle_scalar(r_resolved, r_scalar);
|
|
570
570
|
}
|
|
571
571
|
|
|
572
|
+
ca_refuse_without_common_type(l_resolved, r_resolved);
|
|
572
573
|
TypedData_Get_Struct(l_resolved, CArray, &carray_data_type, l);
|
|
573
574
|
TypedData_Get_Struct(r_resolved, CArray, &carray_data_type, r);
|
|
574
575
|
|
data/ext/ca_obj_bitarray.c
CHANGED
|
@@ -93,7 +93,8 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
|
|
|
93
93
|
ca_size_t bitlen, elements;
|
|
94
94
|
|
|
95
95
|
if ( ca_is_complex_type(parent) || ( ca_is_object_type(parent) ) ) {
|
|
96
|
-
rb_raise(rb_eCADataTypeError, "
|
|
96
|
+
rb_raise(rb_eCADataTypeError, "%s: can't view the bits of a cell of %s",
|
|
97
|
+
ca_calling_method_name(), ca_type_name[parent->data_type]);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/* The bits of one byte would share that byte's one mask cell, so a bit
|
|
@@ -106,6 +107,9 @@ ca_bitarray_setup (CABitarray *ca, CArray *parent)
|
|
|
106
107
|
"use .value.bitarray to read the bits without it");
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
/* The bits add an axis to the parent's. */
|
|
111
|
+
ca_check_rank_fits(parent->ndim + 1, "bitarray");
|
|
112
|
+
|
|
109
113
|
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
110
114
|
run them before it allocates. */
|
|
111
115
|
if ( ca == NULL ) {
|
data/ext/ca_obj_bitfield.c
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
cell, exposing it as an unsigned-integer (or boolean, when
|
|
5
5
|
bitlen == 1) CArray of the same shape as the parent.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
Bits are counted from the least significant bit of the parent cell
|
|
8
|
+
read as a host-order integer. Byte-straddling fields are handled
|
|
9
|
+
by loading up to 8 bytes, the least significant first, starting
|
|
10
|
+
`byte_offset` bytes above the least significant byte, masking with
|
|
11
|
+
`bit_mask`, and shifting by `bit_offset`.
|
|
11
12
|
|
|
12
13
|
---------------------------------------------------------------------------- */
|
|
13
14
|
|
|
@@ -32,7 +33,7 @@ typedef struct {
|
|
|
32
33
|
ca_size_t byte_offset;
|
|
33
34
|
ca_size_t bit_offset;
|
|
34
35
|
uint64_t bit_mask;
|
|
35
|
-
ca_size_t bit_start; /*
|
|
36
|
+
ca_size_t bit_start; /* the offset of the field's lowest bit */
|
|
36
37
|
ca_size_t bit_length; /* width of the field in bits */
|
|
37
38
|
int8_t sign_extend; /* the field is read as a signed integer */
|
|
38
39
|
} CABitfield;
|
|
@@ -85,6 +86,40 @@ static VALUE rb_cCABitfield;
|
|
|
85
86
|
* 8-bit field starting at bit 4 of a 2-byte parent) sees the full
|
|
86
87
|
* bit_mask. A dbytes-typed cast would silently truncate bit_mask
|
|
87
88
|
* to `1 << (dbytes * 8)`, dropping the upper bits of the field. */
|
|
89
|
+
/* The `span` bytes of a cell from `lo` bytes above its least
|
|
90
|
+
significant byte, as an integer. On a big-endian host the least
|
|
91
|
+
significant byte is the last one. */
|
|
92
|
+
static inline uint64_t
|
|
93
|
+
bitfield_load (const char *cell, ca_size_t cbytes, ca_size_t lo, ca_size_t span)
|
|
94
|
+
{
|
|
95
|
+
uint64_t v = 0;
|
|
96
|
+
#ifdef WORDS_BIGENDIAN
|
|
97
|
+
ca_size_t j;
|
|
98
|
+
for (j = 0; j < span; j++) {
|
|
99
|
+
v |= (uint64_t) (uint8_t) cell[cbytes - 1 - lo - j] << (8 * j);
|
|
100
|
+
}
|
|
101
|
+
#else
|
|
102
|
+
(void) cbytes;
|
|
103
|
+
memcpy(&v, cell + lo, (size_t) span);
|
|
104
|
+
#endif
|
|
105
|
+
return v;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
static inline void
|
|
109
|
+
bitfield_save (char *cell, ca_size_t cbytes, ca_size_t lo, ca_size_t span,
|
|
110
|
+
uint64_t v)
|
|
111
|
+
{
|
|
112
|
+
#ifdef WORDS_BIGENDIAN
|
|
113
|
+
ca_size_t j;
|
|
114
|
+
for (j = 0; j < span; j++) {
|
|
115
|
+
cell[cbytes - 1 - lo - j] = (char) (v >> (8 * j));
|
|
116
|
+
}
|
|
117
|
+
#else
|
|
118
|
+
(void) cbytes;
|
|
119
|
+
memcpy(cell + lo, &v, (size_t) span);
|
|
120
|
+
#endif
|
|
121
|
+
}
|
|
122
|
+
|
|
88
123
|
static void
|
|
89
124
|
bitfield_fetch(char *dst, ca_size_t dbytes,
|
|
90
125
|
char *src, ca_size_t sbytes,
|
|
@@ -98,13 +133,12 @@ bitfield_fetch(char *dst, ca_size_t dbytes,
|
|
|
98
133
|
if (span > 8) span = 8;
|
|
99
134
|
ca_size_t dwrite = (dbytes > 8) ? 8 : dbytes;
|
|
100
135
|
for (k = 0; k < elements; k++) {
|
|
101
|
-
uint64_t tmp =
|
|
102
|
-
memcpy(&tmp, src + k * sbytes + byte_offset, (size_t) span);
|
|
136
|
+
uint64_t tmp = bitfield_load(src + k * sbytes, sbytes, byte_offset, span);
|
|
103
137
|
uint64_t result = (tmp & bit_mask) >> bit_offset;
|
|
104
138
|
if ( result & sign ) {
|
|
105
139
|
result |= ~( ( sign << 1 ) - 1 ); /* the field's top bit is its sign */
|
|
106
140
|
}
|
|
107
|
-
|
|
141
|
+
bitfield_save(dst + k * dbytes, dwrite, 0, dwrite, result);
|
|
108
142
|
}
|
|
109
143
|
}
|
|
110
144
|
|
|
@@ -124,12 +158,10 @@ bitfield_store(char *src, ca_size_t sbytes,
|
|
|
124
158
|
if (span > 8) span = 8;
|
|
125
159
|
ca_size_t sread = (sbytes > 8) ? 8 : sbytes;
|
|
126
160
|
for (k = 0; k < elements; k++) {
|
|
127
|
-
uint64_t srcv = 0;
|
|
128
|
-
|
|
129
|
-
uint64_t tmp = 0;
|
|
130
|
-
memcpy(&tmp, dst + k * dbytes + byte_offset, (size_t) span);
|
|
161
|
+
uint64_t srcv = bitfield_load(src + k * sbytes, sread, 0, sread);
|
|
162
|
+
uint64_t tmp = bitfield_load(dst + k * dbytes, dbytes, byte_offset, span);
|
|
131
163
|
tmp = (tmp & ~bit_mask) | ((srcv << bit_offset) & bit_mask);
|
|
132
|
-
|
|
164
|
+
bitfield_save(dst + k * dbytes, dbytes, byte_offset, span, tmp);
|
|
133
165
|
}
|
|
134
166
|
}
|
|
135
167
|
|
|
@@ -160,14 +192,16 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
|
|
|
160
192
|
}
|
|
161
193
|
|
|
162
194
|
if ( offset < 0 || offset + bitlen -1 >= bitsize ) {
|
|
163
|
-
rb_raise(rb_eIndexError, "
|
|
195
|
+
rb_raise(rb_eIndexError, "%s: bits out of range for a cell of %d bits",
|
|
196
|
+
ca_calling_method_name(), (int) bitsize);
|
|
164
197
|
}
|
|
165
198
|
|
|
166
199
|
/* The bits of an object cell are a reference: writing them would leave
|
|
167
200
|
the cell pointing nowhere. A complex cell is refused as bitarray
|
|
168
201
|
refuses it. */
|
|
169
202
|
if ( ca_is_object_type(parent) || ca_is_complex_type(parent) ) {
|
|
170
|
-
rb_raise(rb_eCADataTypeError, "
|
|
203
|
+
rb_raise(rb_eCADataTypeError, "%s: can't view the bits of a cell of %s",
|
|
204
|
+
ca_calling_method_name(), ca_type_name[parent->data_type]);
|
|
171
205
|
}
|
|
172
206
|
|
|
173
207
|
/* A field is read with one 8-byte load from the byte it starts in. */
|
|
@@ -213,32 +247,11 @@ ca_bitfield_setup (CABitfield *ca, CArray *parent,
|
|
|
213
247
|
(long long) bitlen, ca_type_name[data_type]);
|
|
214
248
|
}
|
|
215
249
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
byte_offset = parent->bytes - offset/8 - window;
|
|
222
|
-
bit_offset = offset % 8;
|
|
223
|
-
bit_mask = 0;
|
|
224
|
-
for (i=0; i<bitlen; i++) {
|
|
225
|
-
bit_mask += 1ULL << ( bit_offset + i );
|
|
226
|
-
}
|
|
227
|
-
if ( byte_offset < 0 ) {
|
|
228
|
-
for (i=0; i<-byte_offset; i++) {
|
|
229
|
-
bit_mask = bit_mask << 8;
|
|
230
|
-
bit_offset += 8;
|
|
231
|
-
}
|
|
232
|
-
byte_offset = 0;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
byte_offset = offset / 8;
|
|
237
|
-
bit_offset = offset % 8;
|
|
238
|
-
bit_mask = 0;
|
|
239
|
-
for (i=0; i<bitlen; i++) {
|
|
240
|
-
bit_mask += 1ULL << ( bit_offset + i );
|
|
241
|
-
}
|
|
250
|
+
byte_offset = offset / 8;
|
|
251
|
+
bit_offset = offset % 8;
|
|
252
|
+
bit_mask = 0;
|
|
253
|
+
for (i=0; i<bitlen; i++) {
|
|
254
|
+
bit_mask += 1ULL << ( bit_offset + i );
|
|
242
255
|
}
|
|
243
256
|
|
|
244
257
|
/* ca == NULL asks for the checks above only, so that a constructor can
|
|
@@ -666,8 +679,10 @@ rb_ca_bitfield (int argc, VALUE *argv, VALUE self)
|
|
|
666
679
|
|
|
667
680
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
668
681
|
|
|
669
|
-
if (
|
|
670
|
-
|
|
682
|
+
if ( RB_INTEGER_TYPE_P(rrange) ) {
|
|
683
|
+
/* A bit of a cell: negative from the last. One beyond any cell is
|
|
684
|
+
refused by the setup's range check, as an offset past the cell is. */
|
|
685
|
+
offset = RB_FIXNUM_P(rrange) ? FIX2LONG(rrange) : CA_LENGTH_MAX;
|
|
671
686
|
if ( offset < 0 ) {
|
|
672
687
|
offset += ca->bytes * 8;
|
|
673
688
|
}
|
data/ext/ca_obj_byte_swap.c
CHANGED
|
@@ -196,7 +196,8 @@ ca_byte_swap_setup (CAByteSwap *ca, CArray *parent, VALUE data_class)
|
|
|
196
196
|
CA_CHECK_DATA_TYPE_GIVEN(parent->data_type);
|
|
197
197
|
|
|
198
198
|
if ( parent->data_type == CA_OBJECT ) {
|
|
199
|
-
rb_raise(rb_eCADataTypeError, "object array can't be byte-swapped"
|
|
199
|
+
rb_raise(rb_eCADataTypeError, "%s: an object array can't be byte-swapped",
|
|
200
|
+
ca_calling_method_name());
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
/* ca == NULL asks for the checks above only, so that a constructor can
|
data/ext/ca_obj_const_string.c
CHANGED
|
@@ -837,19 +837,31 @@ rb_ca_const_string_eq (VALUE self, VALUE other)
|
|
|
837
837
|
ca_const_string_scan_end(&b);
|
|
838
838
|
return vout;
|
|
839
839
|
}
|
|
840
|
+
/* Another array is compared cell by cell as Strings, where a CAString
|
|
841
|
+
reconciles it (an object array of Strings, a fixlen or a CAString). */
|
|
842
|
+
if ( rb_obj_is_carray(other) ) {
|
|
843
|
+
return rb_funcall(rb_ca_const_string_to_string(self), rb_intern("eq"), 1,
|
|
844
|
+
other);
|
|
845
|
+
}
|
|
840
846
|
return ca_const_string_predicate(self, other, CA_TEXT_EQ);
|
|
841
847
|
}
|
|
842
848
|
|
|
843
|
-
/* CAConstString#count(value): number of (non-masked) elements byte-equal to
|
|
849
|
+
/* CAConstString#count(value): number of (non-masked) elements byte-equal to
|
|
850
|
+
value. With no value, the number of non-masked elements, as CArray#count
|
|
851
|
+
answers. */
|
|
844
852
|
static VALUE
|
|
845
|
-
rb_ca_const_string_count (VALUE
|
|
853
|
+
rb_ca_const_string_count (int argc, VALUE *argv, VALUE self)
|
|
846
854
|
{
|
|
847
855
|
ca_const_string_scan_t s;
|
|
848
856
|
const char *qp, *p;
|
|
849
857
|
long qlen;
|
|
850
858
|
int64_t len;
|
|
851
859
|
ca_size_t i, c = 0;
|
|
860
|
+
VALUE query;
|
|
852
861
|
|
|
862
|
+
if ( rb_scan_args(argc, argv, "01", &query) == 0 ) {
|
|
863
|
+
return rb_funcall(self, rb_intern("count_not_masked"), 0);
|
|
864
|
+
}
|
|
853
865
|
if ( TYPE(query) != T_STRING ) {
|
|
854
866
|
query = rb_obj_as_string(query);
|
|
855
867
|
}
|
|
@@ -1216,7 +1228,7 @@ Init_ca_obj_const_string (void)
|
|
|
1216
1228
|
/* native byte ops (§3.7) */
|
|
1217
1229
|
rb_define_method(rb_cCAConstString, "byte_length", rb_ca_const_string_byte_length, 0);
|
|
1218
1230
|
rb_define_method(rb_cCAConstString, "eq", rb_ca_const_string_eq, 1);
|
|
1219
|
-
rb_define_method(rb_cCAConstString, "count", rb_ca_const_string_count, 1);
|
|
1231
|
+
rb_define_method(rb_cCAConstString, "count", rb_ca_const_string_count, -1);
|
|
1220
1232
|
rb_define_method(rb_cCAConstString, "start_with?", rb_ca_const_string_start_with, 1);
|
|
1221
1233
|
rb_define_method(rb_cCAConstString, "end_with?", rb_ca_const_string_end_with, 1);
|
|
1222
1234
|
rb_define_method(rb_cCAConstString, "include?", rb_ca_const_string_include, 1);
|
data/ext/ca_obj_face.c
CHANGED
|
@@ -281,7 +281,8 @@ ca_face_lift (VALUE view, VALUE face_parent)
|
|
|
281
281
|
handled by builder-side pre-strip. data_type above stays a full strip
|
|
282
282
|
(surface concern, §8 #7) — the parent pointer is the structural concern
|
|
283
283
|
(§8.3); the two axes are deliberately separate. */
|
|
284
|
-
if ( ((
|
|
284
|
+
if ( ca_is_view(view_ca) /* an entity (a copy) has no parent field */
|
|
285
|
+
&& ((CAView *) view_ca)->parent == fp
|
|
285
286
|
&& ! ca_test_flag(view_ca, CA_FLAG_MULTI_PARENTS) ) {
|
|
286
287
|
((CAView *) view_ca)->parent = ((CAView *) fp)->parent; /* C pointer: one level */
|
|
287
288
|
rb_ca_set_parent(view, rb_ca_parent(face_parent)); /* @parent ivar: lockstep */
|
|
@@ -1233,6 +1234,25 @@ ca_face_reconcile_comparison (volatile VALUE *pself, volatile VALUE *pother)
|
|
|
1233
1234
|
return;
|
|
1234
1235
|
}
|
|
1235
1236
|
|
|
1237
|
+
/* Two string arrays of different kinds (CAString, CAFixlenString,
|
|
1238
|
+
CAConstString) or of different cell widths hold their strings in
|
|
1239
|
+
different storage: the padded bytes of one are not the bytes of the
|
|
1240
|
+
other. They are compared by their strings. */
|
|
1241
|
+
if ( RTEST(rb_obj_is_carray(other)) ) {
|
|
1242
|
+
static ID id_to_string = 0;
|
|
1243
|
+
CArray *oc;
|
|
1244
|
+
if ( id_to_string == 0 ) id_to_string = rb_intern("to_string");
|
|
1245
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, oc);
|
|
1246
|
+
if ( ca_is_face(oc) && rb_respond_to(self, id_to_string)
|
|
1247
|
+
&& rb_respond_to(other, id_to_string)
|
|
1248
|
+
&& ( rb_obj_class(self) != rb_obj_class(other)
|
|
1249
|
+
|| sc->bytes != oc->bytes ) ) {
|
|
1250
|
+
*pself = rb_ca_strip_face_value(rb_funcall(self, id_to_string, 0));
|
|
1251
|
+
*pother = rb_ca_strip_face_value(rb_funcall(other, id_to_string, 0));
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1236
1256
|
storage = ca_strip_face(sc);
|
|
1237
1257
|
if ( storage->data_type == CA_FIXLEN ) {
|
|
1238
1258
|
/* genuine fixlen semantics: memcmp is the correct comparison, so self
|
|
@@ -1262,6 +1282,26 @@ ca_face_reconcile_comparison (volatile VALUE *pself, volatile VALUE *pother)
|
|
|
1262
1282
|
}
|
|
1263
1283
|
}
|
|
1264
1284
|
|
|
1285
|
+
/* A Face's parent, the array its values are stored in, is handed out as a
|
|
1286
|
+
read-only view: a write through it would change the Face's values
|
|
1287
|
+
without the Face's conversion (a tick count stored into a time, bytes
|
|
1288
|
+
into a record). The storage is written through the Face's own named
|
|
1289
|
+
methods (CATime#ticks), which take it with face_storage. */
|
|
1290
|
+
static VALUE
|
|
1291
|
+
rb_ca_face_parent (VALUE self)
|
|
1292
|
+
{
|
|
1293
|
+
volatile VALUE st = rb_ca_parent(self), view;
|
|
1294
|
+
CArray *cs, *cv;
|
|
1295
|
+
if ( NIL_P(st) ) {
|
|
1296
|
+
return st;
|
|
1297
|
+
}
|
|
1298
|
+
TypedData_Get_Struct(st, CArray, &carray_data_type, cs);
|
|
1299
|
+
view = rb_ca_refer_new(st, cs->data_type, cs->ndim, cs->dim, cs->bytes, 0);
|
|
1300
|
+
TypedData_Get_Struct(view, CArray, &carray_data_type, cv);
|
|
1301
|
+
ca_set_flag(cv, CA_FLAG_READ_ONLY);
|
|
1302
|
+
return view;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1265
1305
|
void
|
|
1266
1306
|
Init_ca_face (void)
|
|
1267
1307
|
{
|
|
@@ -1271,6 +1311,7 @@ Init_ca_face (void)
|
|
|
1271
1311
|
ahead of this Init) — CAFace inherits from it. */
|
|
1272
1312
|
rb_cCAFace = rb_define_class("CAFace", rb_cCAView);
|
|
1273
1313
|
rb_define_alloc_func(rb_cCAFace, rb_ca_face_s_allocate_forbidden);
|
|
1314
|
+
rb_define_method(rb_cCAFace, "parent", rb_ca_face_parent, 0);
|
|
1274
1315
|
|
|
1275
1316
|
/* Initialise the portable table to -1 for every slot so dispatch
|
|
1276
1317
|
can distinguish "explicitly registered 0" (CAConstString) from
|
data/ext/ca_obj_field.c
CHANGED
|
@@ -40,11 +40,12 @@ ca_field_setup (CAStride *ca, CArray *parent,
|
|
|
40
40
|
}
|
|
41
41
|
if ( data_type == CA_OBJECT ) {
|
|
42
42
|
rb_raise(rb_eCADataTypeError,
|
|
43
|
-
"
|
|
43
|
+
"%s: a field can't be read as object", ca_calling_method_name());
|
|
44
44
|
}
|
|
45
45
|
if ( ca_is_object_type(parent) ) {
|
|
46
46
|
rb_raise(rb_eCADataTypeError,
|
|
47
|
-
"a field can
|
|
47
|
+
"%s: a field can't be taken from an object array",
|
|
48
|
+
ca_calling_method_name());
|
|
48
49
|
}
|
|
49
50
|
/* A boolean cell holds 0 or 1, and a field of a numeric array is
|
|
50
51
|
written as that number. A record's boolean member is a field of a
|
|
@@ -105,6 +106,14 @@ rb_ca_field_new (VALUE cary, ca_size_t offset, int8_t data_type, ca_size_t bytes
|
|
|
105
106
|
CAStride *ca;
|
|
106
107
|
rb_check_carray_object(cary);
|
|
107
108
|
TypedData_Get_Struct(cary, CArray, &carray_data_type, parent);
|
|
109
|
+
/* A record's boolean member is a byte of a fixlen array that other
|
|
110
|
+
fields (a uint8 one, a String store of the record) can write as any
|
|
111
|
+
byte. It is read through a cast to boolean, which refuses a byte
|
|
112
|
+
that is not 0 or 1, as fake(:boolean) does. */
|
|
113
|
+
if ( data_type == CA_BOOLEAN && parent->data_type == CA_FIXLEN ) {
|
|
114
|
+
obj = rb_ca_field_new(cary, offset, CA_UINT8, 1);
|
|
115
|
+
return rb_ca_fake_new(obj, CA_BOOLEAN, 1);
|
|
116
|
+
}
|
|
108
117
|
ca = ca_field_new(parent, offset, data_type, bytes);
|
|
109
118
|
obj = ca_wrap_struct(ca);
|
|
110
119
|
rb_ca_set_parent(obj, cary);
|
|
@@ -139,7 +148,7 @@ rb_ca_field (int argc, VALUE *argv, VALUE self)
|
|
|
139
148
|
rb_scan_args(argc, argv, "21", (VALUE *) &voffset, (VALUE *) &rtype, (VALUE *) &ropt);
|
|
140
149
|
rb_scan_options(ropt, "bytes", &rbytes);
|
|
141
150
|
|
|
142
|
-
offset =
|
|
151
|
+
offset = ca_integer_arg(voffset, "offset", NULL);
|
|
143
152
|
|
|
144
153
|
if ( rb_obj_is_carray(rtype) ) {
|
|
145
154
|
CArray *ct;
|
|
@@ -149,6 +158,7 @@ rb_ca_field (int argc, VALUE *argv, VALUE self)
|
|
|
149
158
|
TypedData_Get_Struct(rtype, CArray, &carray_data_type, ct);
|
|
150
159
|
data_type = CA_FIXLEN;
|
|
151
160
|
bytes = ct->bytes * ct->elements;
|
|
161
|
+
ca_check_rank_fits((long) ca->ndim + ct->ndim, "field");
|
|
152
162
|
obj = rb_ca_field_new(self, offset, data_type, bytes);
|
|
153
163
|
ndim = ca->ndim + ct->ndim;
|
|
154
164
|
for (i=0; i<ca->ndim; i++) {
|
data/ext/ca_obj_grid.c
CHANGED
|
@@ -242,7 +242,9 @@ ca_grid_setup (CAGrid *ca, CArray *parent, int8_t ndim,
|
|
|
242
242
|
ca_set_flag(ca, CA_FLAG_SHARE_INDEX);
|
|
243
243
|
ca->axes = protos;
|
|
244
244
|
} else {
|
|
245
|
-
|
|
245
|
+
/* Zeroed: an axis's indices or holes that cannot be allocated raises
|
|
246
|
+
with the later axes not yet copied, and free_ca_grid reads them. */
|
|
247
|
+
ca->axes = ZALLOC_N(cag_axis_t, ndim);
|
|
246
248
|
for (k = 0; k < ndim; k++) {
|
|
247
249
|
ca->axes[k].kind = protos[k].kind;
|
|
248
250
|
ca->axes[k].count = protos[k].count;
|
|
@@ -319,16 +321,38 @@ ca_grid_inherit_mask (VALUE view)
|
|
|
319
321
|
return ca_view_inherit_mask(view);
|
|
320
322
|
}
|
|
321
323
|
|
|
322
|
-
|
|
324
|
+
typedef struct {
|
|
325
|
+
CAGrid *ca;
|
|
326
|
+
CArray *parent;
|
|
327
|
+
int8_t ndim;
|
|
328
|
+
cag_axis_t *protos;
|
|
329
|
+
} ca_grid_new_arg;
|
|
330
|
+
|
|
331
|
+
static VALUE
|
|
332
|
+
ca_grid_new_setup (VALUE varg)
|
|
333
|
+
{
|
|
334
|
+
ca_grid_new_arg *a = (ca_grid_new_arg *) varg;
|
|
335
|
+
ca_grid_setup(a->ca, a->parent, a->ndim, a->protos, 0);
|
|
336
|
+
return Qnil;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* holes_read_masked is the copied grid's: a copy of a mask grid is one.
|
|
340
|
+
The setup allocates the axes after the struct and its pool: when that
|
|
341
|
+
fails, the struct goes too. */
|
|
323
342
|
static CAGrid *
|
|
324
343
|
ca_grid_new_as (CArray *parent, int8_t ndim, cag_axis_t *protos,
|
|
325
344
|
int8_t holes_read_masked, CAGrid *mask_owner)
|
|
326
345
|
{
|
|
327
346
|
CAGrid *ca;
|
|
347
|
+
ca_grid_new_arg a;
|
|
328
348
|
ca_grid_check_protos(parent, ndim, protos);
|
|
329
349
|
/* check: ca_grid_check_protos above */
|
|
330
350
|
ca = (CAGrid *) ca_array_alloc(CA_OBJ_GRID, ndim);
|
|
331
|
-
|
|
351
|
+
a.ca = ca;
|
|
352
|
+
a.parent = parent;
|
|
353
|
+
a.ndim = ndim;
|
|
354
|
+
a.protos = protos;
|
|
355
|
+
ca_fill_or_free((CArray *) ca, ca_grid_new_setup, (VALUE) &a);
|
|
332
356
|
ca->holes_read_masked = holes_read_masked;
|
|
333
357
|
ca->mask_owner = mask_owner;
|
|
334
358
|
ca_fill_or_free((CArray *) ca, ca_grid_inherit_mask, (VALUE) ca);
|
|
@@ -358,7 +382,7 @@ free_ca_grid (void *ap)
|
|
|
358
382
|
if ( ca != NULL ) {
|
|
359
383
|
ca_free(ca->mask);
|
|
360
384
|
ca_free(ca->mask_standin);
|
|
361
|
-
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) ) {
|
|
385
|
+
if ( ! (ca->flags & CA_FLAG_SHARE_INDEX) && ca->axes ) {
|
|
362
386
|
int8_t k;
|
|
363
387
|
for (k = 0; k < ca->ndim; k++) {
|
|
364
388
|
if ( ca->axes[k].kind == CAG_AXIS_INDEX && ca->axes[k].indices ) {
|
|
@@ -1226,7 +1250,15 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
1226
1250
|
rb_raise(rb_eArgError, "invalid total ndim of args");
|
|
1227
1251
|
}
|
|
1228
1252
|
ref = rb_ca_refer_new(self, ca->data_type, rndim, rdim, ca->bytes, 0);
|
|
1229
|
-
|
|
1253
|
+
/* An index array that spans several axes picks along the one axis
|
|
1254
|
+
they are joined into, so it is read flat there. */
|
|
1255
|
+
{
|
|
1256
|
+
VALUE flat[CA_RANK_MAX];
|
|
1257
|
+
for (i=0; i<rndim; i++) {
|
|
1258
|
+
flat[i] = rb_obj_is_carray(argv[i]) ? rb_ca_flatten(argv[i]) : argv[i];
|
|
1259
|
+
}
|
|
1260
|
+
return rb_ca_grid(argc, flat, ref);
|
|
1261
|
+
}
|
|
1230
1262
|
}
|
|
1231
1263
|
|
|
1232
1264
|
/* Dispatch hook: route a boolean on axis 0 with plain keys elsewhere to
|
|
@@ -1256,6 +1288,21 @@ rb_ca_grid (int argc, VALUE *argv, VALUE self)
|
|
|
1256
1288
|
protos[i].holes = NULL;
|
|
1257
1289
|
continue;
|
|
1258
1290
|
}
|
|
1291
|
+
{
|
|
1292
|
+
/* An index array picks cells along its one axis. One of more axes
|
|
1293
|
+
states a shape the axis does not have. */
|
|
1294
|
+
CArray *cs;
|
|
1295
|
+
TypedData_Get_Struct(rval, CArray, &carray_data_type, cs);
|
|
1296
|
+
if ( cs->ndim > 1 ) {
|
|
1297
|
+
volatile VALUE sshape = rb_ary_new();
|
|
1298
|
+
int k;
|
|
1299
|
+
for (k = 0; k < cs->ndim; k++) rb_ary_push(sshape, SIZE2NUM(cs->dim[k]));
|
|
1300
|
+
rb_raise(rb_eArgError,
|
|
1301
|
+
"%s: index array of shape %"PRIsVALUE" on axis %d (an index "
|
|
1302
|
+
"array picks along one axis; use .flatten)",
|
|
1303
|
+
ca_calling_method_name(), sshape, (int) i);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1259
1306
|
if ( rb_ca_is_boolean_type(rval) ) {
|
|
1260
1307
|
CArray *cb;
|
|
1261
1308
|
TypedData_Get_Struct(rval, CArray, &carray_data_type, cb);
|