carray 3.0.2 → 3.0.4
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 +568 -0
- data/README.md +6 -6
- data/carray.gemspec +1 -1
- data/ext/ca_axis_descriptor.h +27 -24
- data/ext/ca_axis_dispatch.c +220 -0
- data/ext/ca_axis_group.c +201 -123
- data/ext/ca_binop_dispatch.c +46 -52
- data/ext/ca_binop_dispatch.h +1 -1
- data/ext/ca_categorical_iterator.c +249 -183
- data/ext/ca_compare.c +7 -12
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +38 -23
- data/ext/ca_kernel_iterator.c +1765 -2076
- data/ext/ca_kernel_iterator.h +584 -566
- data/ext/ca_monop_dispatch.c +86 -63
- data/ext/ca_monop_dispatch.h +5 -0
- data/ext/ca_obj_array.c +223 -56
- data/ext/ca_obj_bincmp.c +172 -138
- data/ext/ca_obj_binop.c +116 -230
- data/ext/ca_obj_bitarray.c +40 -26
- data/ext/ca_obj_bitfield.c +100 -68
- data/ext/ca_obj_block.c +19 -9
- data/ext/ca_obj_byte_swap.c +45 -46
- data/ext/ca_obj_const_string.c +269 -44
- data/ext/ca_obj_face.c +612 -89
- data/ext/ca_obj_face.h +111 -47
- data/ext/ca_obj_fake.c +36 -79
- data/ext/ca_obj_farray.c +7 -3
- data/ext/ca_obj_field.c +33 -8
- data/ext/ca_obj_fixlen_string.c +23 -24
- data/ext/ca_obj_grid.c +541 -210
- data/ext/ca_obj_meld.c +331 -111
- data/ext/ca_obj_moncmp.c +80 -65
- data/ext/ca_obj_monop.c +177 -149
- data/ext/ca_obj_object.c +664 -248
- data/ext/ca_obj_record.c +63 -23
- data/ext/ca_obj_reduce.c +18 -16
- data/ext/ca_obj_refer.c +140 -58
- data/ext/ca_obj_remap.c +85 -24
- data/ext/ca_obj_repeat.c +24 -9
- data/ext/ca_obj_roll.c +121 -16
- data/ext/ca_obj_select.c +61 -58
- data/ext/ca_obj_select_axis.c +73 -107
- data/ext/ca_obj_shift.c +32 -102
- data/ext/ca_obj_stack.c +372 -122
- data/ext/ca_obj_stride.c +348 -140
- data/ext/ca_obj_string.c +88 -22
- data/ext/ca_obj_tile.c +38 -21
- data/ext/ca_obj_time.c +45 -31
- data/ext/ca_obj_timedelta.c +43 -29
- data/ext/ca_obj_transpose.c +17 -6
- data/ext/ca_obj_triop.c +125 -141
- data/ext/ca_obj_window.c +330 -44
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +104 -81
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +542 -0
- data/ext/carray.h +241 -92
- data/ext/carray_access.c +608 -276
- data/ext/carray_address_basis.c +494 -97
- data/ext/carray_attribute.c +129 -4
- data/ext/carray_bincount.c +39 -7
- data/ext/carray_broadcast.c +56 -19
- data/ext/carray_build_flags.h +1 -1
- data/ext/carray_call_cfunc.c +108 -28
- data/ext/carray_cast.c +1576 -223
- data/ext/carray_cast_func.rb +77 -24
- data/ext/carray_class.c +4 -3
- data/ext/carray_conversion.c +208 -75
- data/ext/carray_copy.c +82 -24
- data/ext/carray_core.c +646 -162
- data/ext/carray_count.c +171 -88
- data/ext/carray_element.c +94 -60
- data/ext/carray_factorize.c +670 -324
- data/ext/carray_generate.c +260 -83
- data/ext/carray_histogram.c +209 -106
- data/ext/carray_hold.c +14 -16
- data/ext/carray_index_classifier.c +422 -243
- data/ext/carray_internal.h +692 -3
- data/ext/carray_kernels_bincmp.c +7 -0
- data/ext/carray_kernels_binop.c +487 -120
- data/ext/carray_kernels_init.c +653 -50
- data/ext/carray_kernels_moncmp.c +15 -8
- data/ext/carray_kernels_monop.c +99 -43
- data/ext/carray_kernels_reduce_aggregate.c +3925 -6112
- data/ext/carray_kernels_reduce_boolean.c +112 -36
- data/ext/carray_kernels_reduce_cumulative.c +2127 -6903
- data/ext/carray_kernels_reduce_extreme.c +3032 -2892
- data/ext/carray_kernels_reduce_variance.c +439 -500
- data/ext/carray_kernels_scan.c +1097 -488
- data/ext/carray_kernels_search.c +3787 -2176
- data/ext/carray_kernels_sort.c +1200 -920
- data/ext/carray_kernels_triop.c +479 -7
- data/ext/carray_key_windows.c +216 -0
- data/ext/carray_lazy.c +967 -153
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +910 -324
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +299 -100
- data/ext/carray_memory_view.c +872 -758
- data/ext/carray_operator.c +1171 -364
- data/ext/carray_order.c +505 -133
- data/ext/carray_partition.c +112 -65
- data/ext/carray_random.c +327 -239
- data/ext/carray_round.c +273 -0
- data/ext/carray_scatter.c +346 -78
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +249 -86
- data/ext/carray_sort.c +224 -227
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +118 -39
- data/ext/carray_test.c +193 -69
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_undef.c +4 -0
- data/ext/carray_utils.c +579 -113
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +19 -4
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1202 -1014
- data/ext/ruby_carray.c +17 -5
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +160 -17
- data/lib/carray/autoload_carray.rb +23 -27
- data/lib/carray/autoload_method_extension.rb +20 -5
- data/lib/carray/axis_group.rb +360 -63
- data/lib/carray/basics.rb +162 -28
- data/lib/carray/bincount_nd.rb +18 -2
- data/lib/carray/block_iterator.rb +231 -58
- data/lib/carray/boolean_reduce.rb +34 -42
- data/lib/carray/categorical.rb +242 -52
- data/lib/carray/categorical_iterator.rb +437 -827
- data/lib/carray/complex.rb +41 -34
- data/lib/carray/conditional.rb +150 -14
- data/lib/carray/const_string.rb +59 -4
- data/lib/carray/construct.rb +15 -11
- data/lib/carray/data_type_extension.rb +1 -0
- data/lib/carray/distance_limit.rb +77 -0
- data/lib/carray/fixlen_string.rb +7 -1
- data/lib/carray/frame/column_verbs.rb +70 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +82 -7
- data/lib/carray/frame/csv_parser.rb +688 -87
- data/lib/carray/frame/describe.rb +80 -0
- data/lib/carray/frame/frame.rb +369 -45
- data/lib/carray/frame/group.rb +631 -90
- data/lib/carray/frame/io.rb +506 -79
- data/lib/carray/frame/join.rb +411 -62
- data/lib/carray/frame/records.rb +116 -19
- data/lib/carray/frame/reshape.rb +455 -0
- data/lib/carray/frame/sort.rb +30 -18
- data/lib/carray/frame/verbs.rb +868 -61
- data/lib/carray/frame/windows.rb +117 -0
- data/lib/carray/frame.rb +4 -0
- data/lib/carray/fuse_source.rb +118 -2
- data/lib/carray/fusion.rb +257 -42
- data/lib/carray/histogram.rb +6 -1
- data/lib/carray/inspect.rb +54 -13
- data/lib/carray/iterator.rb +99 -9
- data/lib/carray/key_windows.rb +620 -0
- data/lib/carray/lazy.rb +216 -193
- data/lib/carray/mask_gap_fill.rb +112 -92
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +52 -21
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bin.rb +26 -18
- data/lib/carray/methods/bincount.rb +18 -2
- data/lib/carray/methods/bit_string.rb +15 -4
- data/lib/carray/methods/choose.rb +16 -3
- data/lib/carray/methods/composition.rb +18 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +25 -5
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_between.rb +59 -0
- data/lib/carray/methods/is_in.rb +140 -10
- data/lib/carray/methods/join.rb +2 -7
- data/lib/carray/methods/lag.rb +49 -0
- data/lib/carray/methods/locate_addr.rb +182 -45
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/nunique.rb +11 -6
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/methods/value_counts.rb +4 -11
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/rng.rb +3 -0
- data/lib/carray/runtime.rb +65 -17
- data/lib/carray/segment_iterator.rb +1221 -0
- data/lib/carray/serialize.rb +214 -30
- data/lib/carray/slab_iterator.rb +101 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string.rb +105 -5
- data/lib/carray/string_operation_extension.rb +12 -4
- data/lib/carray/struct.rb +137 -58
- data/lib/carray/struct_builder.rb +124 -17
- data/lib/carray/time.rb +1222 -186
- data/lib/carray/window_iterator.rb +242 -81
- data/lib/carray.rb +9 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +5 -1
- data/yard-stubs/ca_obj_grid.rb +21 -10
- data/yard-stubs/ca_obj_refer.rb +5 -4
- data/yard-stubs/ca_obj_roll.rb +2 -3
- data/yard-stubs/ca_obj_shift.rb +5 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_tile.rb +1 -1
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +9 -5
- data/yard-stubs/carray_access.rb +11 -5
- data/yard-stubs/carray_attribute.rb +0 -5
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +88 -43
- data/yard-stubs/carray_conversion.rb +15 -2
- data/yard-stubs/carray_copy.rb +12 -5
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_element.rb +10 -4
- data/yard-stubs/carray_generate.rb +21 -1
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +60 -12
- data/yard-stubs/carray_math.rb +52 -14
- data/yard-stubs/carray_median_percentile.rb +15 -8
- data/yard-stubs/carray_memory_view.rb +40 -23
- data/yard-stubs/carray_order.rb +61 -29
- data/yard-stubs/carray_random.rb +13 -4
- data/yard-stubs/carray_scatter.rb +21 -9
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +10 -2
- data/yard-stubs/carray_sort.rb +49 -8
- data/yard-stubs/carray_test.rb +15 -3
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +19 -5
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_kernels_map.c +0 -3467
- data/lib/carray/arrow_tensor.rb +0 -401
- data/lib/carray/table.rb +0 -108
data/ext/carray_sort_kernel.c
CHANGED
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
#include <string.h>
|
|
52
52
|
#include <math.h>
|
|
53
53
|
|
|
54
|
-
#define CA_SORT_INSERTION_THRESHOLD 16
|
|
55
54
|
|
|
56
55
|
/* ---------------------------------------------------------------------------
|
|
57
56
|
DEFINE_SORT_MERGE(TYPE, SUFFIX)
|
|
@@ -616,5 +615,13 @@ DEFINE_PARTITION_QUICK(uint64_t, u64);
|
|
|
616
615
|
DEFINE_PARTITION_QUICK(float32_t, f32);
|
|
617
616
|
DEFINE_PARTITION_QUICK(double, f64);
|
|
618
617
|
|
|
618
|
+
/* The pair mergesort above for object pairs, which have no `<`: every
|
|
619
|
+
comparison goes through cmp (see CA_SORT_MERGE_BY_CMP). */
|
|
620
|
+
void
|
|
621
|
+
ca_sort_merge_pair_object (ca_pair_object *a, ca_pair_object *aux,
|
|
622
|
+
ca_size_t n,
|
|
623
|
+
int (*cmp)(const void *, const void *))
|
|
624
|
+
CA_SORT_MERGE_BY_CMP(ca_pair_object)
|
|
625
|
+
|
|
619
626
|
/* No Init function: this file exposes only C kernels (via ca_sort_kernels.h);
|
|
620
627
|
it registers no Ruby methods. */
|
data/ext/carray_struct.c
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
C-native member access for CAStruct subclasses. The hooked
|
|
4
4
|
methods (`[]`, `[]=`, `initialize`) are installed on a subclass by
|
|
5
|
-
`CArray.
|
|
5
|
+
`CArray.install_struct_methods(klass)` — called from the
|
|
6
6
|
bottom of lib/carray/struct.rb once CAStruct is defined, so this
|
|
7
7
|
ext can load before that file.
|
|
8
8
|
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
(primitive / bitfield / endian-swap)
|
|
17
17
|
DISPATCH_TABLE hit -> Proc invoked via rb_funcall("call")
|
|
18
18
|
(nested struct / CArray template / fixlen)
|
|
19
|
-
|
|
19
|
+
a Symbol, or a name that is not a member, raises: a member is
|
|
20
|
+
s["name"] or s[position], and its accessor s.name
|
|
20
21
|
|
|
21
22
|
---------------------------------------------------------------------------- */
|
|
22
23
|
|
|
23
24
|
#include "carray.h"
|
|
25
|
+
#include "carray_internal.h" /* ca_obj2integer_fitting */
|
|
24
26
|
#include <string.h>
|
|
25
27
|
|
|
26
28
|
/* ---------------------------------------------------------------------
|
|
@@ -54,7 +56,7 @@ ca_struct_read_primitive_fast (const char *p, int type_code)
|
|
|
54
56
|
case CA_BOOLEAN: {
|
|
55
57
|
int8_t v;
|
|
56
58
|
memcpy(&v, p, 1);
|
|
57
|
-
return v ?
|
|
59
|
+
return v ? Qtrue : Qfalse;
|
|
58
60
|
}
|
|
59
61
|
case CA_INT8: {
|
|
60
62
|
int8_t v;
|
|
@@ -116,47 +118,55 @@ ca_struct_write_primitive_fast (char *p, int type_code, VALUE val)
|
|
|
116
118
|
{
|
|
117
119
|
switch (type_code) {
|
|
118
120
|
case CA_BOOLEAN: {
|
|
119
|
-
|
|
121
|
+
/* The values a boolean array takes: true / false / 1 / 0. */
|
|
122
|
+
int8_t v;
|
|
123
|
+
if ( val == Qtrue || val == INT2FIX(1) ) v = 1;
|
|
124
|
+
else if ( val == Qfalse || val == INT2FIX(0) ) v = 0;
|
|
125
|
+
else {
|
|
126
|
+
rb_raise(rb_eCADataTypeError,
|
|
127
|
+
"can't cast object '%"PRIsVALUE"' to <boolean>",
|
|
128
|
+
rb_inspect(val));
|
|
129
|
+
}
|
|
120
130
|
memcpy(p, &v, 1);
|
|
121
131
|
return;
|
|
122
132
|
}
|
|
123
133
|
case CA_INT8: {
|
|
124
|
-
int8_t v = (int8_t)
|
|
134
|
+
int8_t v = (int8_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT8));
|
|
125
135
|
memcpy(p, &v, 1);
|
|
126
136
|
return;
|
|
127
137
|
}
|
|
128
138
|
case CA_UINT8: {
|
|
129
|
-
uint8_t v = (uint8_t)
|
|
139
|
+
uint8_t v = (uint8_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT8));
|
|
130
140
|
memcpy(p, &v, 1);
|
|
131
141
|
return;
|
|
132
142
|
}
|
|
133
143
|
case CA_INT16: {
|
|
134
|
-
int16_t v = (int16_t)
|
|
144
|
+
int16_t v = (int16_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT16));
|
|
135
145
|
memcpy(p, &v, 2);
|
|
136
146
|
return;
|
|
137
147
|
}
|
|
138
148
|
case CA_UINT16: {
|
|
139
|
-
uint16_t v = (uint16_t)
|
|
149
|
+
uint16_t v = (uint16_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT16));
|
|
140
150
|
memcpy(p, &v, 2);
|
|
141
151
|
return;
|
|
142
152
|
}
|
|
143
153
|
case CA_INT32: {
|
|
144
|
-
int32_t v = (int32_t)
|
|
154
|
+
int32_t v = (int32_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT32));
|
|
145
155
|
memcpy(p, &v, 4);
|
|
146
156
|
return;
|
|
147
157
|
}
|
|
148
158
|
case CA_UINT32: {
|
|
149
|
-
uint32_t v = (uint32_t)
|
|
159
|
+
uint32_t v = (uint32_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT32));
|
|
150
160
|
memcpy(p, &v, 4);
|
|
151
161
|
return;
|
|
152
162
|
}
|
|
153
163
|
case CA_INT64: {
|
|
154
|
-
int64_t v = (int64_t) NUM2LL(val);
|
|
164
|
+
int64_t v = (int64_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT64));
|
|
155
165
|
memcpy(p, &v, 8);
|
|
156
166
|
return;
|
|
157
167
|
}
|
|
158
168
|
case CA_UINT64: {
|
|
159
|
-
uint64_t v = (uint64_t)
|
|
169
|
+
uint64_t v = (uint64_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT64));
|
|
160
170
|
memcpy(p, &v, 8);
|
|
161
171
|
return;
|
|
162
172
|
}
|
|
@@ -201,8 +211,10 @@ ca_struct_read_bitfield_fast (const char *p, int view_bytes,
|
|
|
201
211
|
uint64_t mask = (bits >= 64) ? ~(uint64_t)0
|
|
202
212
|
: ((uint64_t)1 << bits) - 1;
|
|
203
213
|
uint64_t val = (word >> bit_in_word) & mask;
|
|
204
|
-
/*
|
|
214
|
+
/* A 1-bit field is a boolean, as a record array's column of it is.
|
|
215
|
+
Wider fields are unsigned Integers; bit-fields don't carry a sign
|
|
205
216
|
bit in carray's CABitfield convention either. */
|
|
217
|
+
if (bits == 1) return val ? Qtrue : Qfalse;
|
|
206
218
|
if (bits <= 31) return INT2FIX((long) val);
|
|
207
219
|
if (bits <= 32) return ULONG2NUM((unsigned long) val);
|
|
208
220
|
return ULL2NUM(val);
|
|
@@ -212,7 +224,19 @@ static void
|
|
|
212
224
|
ca_struct_write_bitfield_fast (char *p, int view_bytes,
|
|
213
225
|
int bit_in_word, int bits, VALUE val)
|
|
214
226
|
{
|
|
215
|
-
uint64_t v
|
|
227
|
+
uint64_t v;
|
|
228
|
+
if ( bits == 1 ) {
|
|
229
|
+
if ( val == Qtrue || val == INT2FIX(1) ) v = 1;
|
|
230
|
+
else if ( val == Qfalse || val == INT2FIX(0) ) v = 0;
|
|
231
|
+
else {
|
|
232
|
+
rb_raise(rb_eCADataTypeError,
|
|
233
|
+
"can't cast object '%"PRIsVALUE"' to <boolean>",
|
|
234
|
+
rb_inspect(val));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
v = NUM2ULL(val);
|
|
239
|
+
}
|
|
216
240
|
uint64_t mask = (bits >= 64) ? ~(uint64_t)0
|
|
217
241
|
: ((uint64_t)1 << bits) - 1;
|
|
218
242
|
v &= mask;
|
|
@@ -310,32 +334,32 @@ ca_struct_write_endian_swapped_fast (char *p, int type_code, VALUE val)
|
|
|
310
334
|
{
|
|
311
335
|
switch (type_code) {
|
|
312
336
|
case CA_INT16: {
|
|
313
|
-
uint16_t v = (uint16_t)
|
|
337
|
+
uint16_t v = (uint16_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT16));
|
|
314
338
|
v = CA_BSWAP16(v); memcpy(p, &v, 2);
|
|
315
339
|
return;
|
|
316
340
|
}
|
|
317
341
|
case CA_UINT16: {
|
|
318
|
-
uint16_t v = (uint16_t)
|
|
342
|
+
uint16_t v = (uint16_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT16));
|
|
319
343
|
v = CA_BSWAP16(v); memcpy(p, &v, 2);
|
|
320
344
|
return;
|
|
321
345
|
}
|
|
322
346
|
case CA_INT32: {
|
|
323
|
-
uint32_t v = (uint32_t)
|
|
347
|
+
uint32_t v = (uint32_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT32));
|
|
324
348
|
v = CA_BSWAP32(v); memcpy(p, &v, 4);
|
|
325
349
|
return;
|
|
326
350
|
}
|
|
327
351
|
case CA_UINT32: {
|
|
328
|
-
uint32_t v = (uint32_t)
|
|
352
|
+
uint32_t v = (uint32_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT32));
|
|
329
353
|
v = CA_BSWAP32(v); memcpy(p, &v, 4);
|
|
330
354
|
return;
|
|
331
355
|
}
|
|
332
356
|
case CA_INT64: {
|
|
333
|
-
uint64_t v = (uint64_t) NUM2LL(val);
|
|
357
|
+
uint64_t v = (uint64_t) NUM2LL(ca_obj2integer_fitting(val, CA_INT64));
|
|
334
358
|
v = CA_BSWAP64(v); memcpy(p, &v, 8);
|
|
335
359
|
return;
|
|
336
360
|
}
|
|
337
361
|
case CA_UINT64: {
|
|
338
|
-
uint64_t v =
|
|
362
|
+
uint64_t v = (uint64_t) rb_num2ull(ca_obj2integer_fitting(val, CA_UINT64));
|
|
339
363
|
v = CA_BSWAP64(v); memcpy(p, &v, 8);
|
|
340
364
|
return;
|
|
341
365
|
}
|
|
@@ -384,6 +408,45 @@ ca_struct_resolve_name (VALUE klass, VALUE name)
|
|
|
384
408
|
return rb_funcall(name, rb_intern("to_s"), 0);
|
|
385
409
|
}
|
|
386
410
|
|
|
411
|
+
/* The member an element's `[]` / `[]=` names: a String naming a member,
|
|
412
|
+
or an Integer position. A Symbol is not a member name here -- the
|
|
413
|
+
member is s["name"] or the accessor s.name -- and a name that is not a
|
|
414
|
+
member raises rather than calling a method of that name. */
|
|
415
|
+
static VALUE
|
|
416
|
+
ca_struct_member_name (VALUE klass, VALUE name)
|
|
417
|
+
{
|
|
418
|
+
VALUE name_s;
|
|
419
|
+
if ( SYMBOL_P(name) ) {
|
|
420
|
+
VALUE str = rb_sym2str(name);
|
|
421
|
+
if ( ! NIL_P(rb_hash_aref(rb_const_get(klass, rb_intern("MEMBER_TABLE")),
|
|
422
|
+
str)) ) {
|
|
423
|
+
rb_raise(rb_eTypeError,
|
|
424
|
+
"a struct member is named by a String (s[\"%"PRIsVALUE"\"]) or "
|
|
425
|
+
"read by its accessor (s.%"PRIsVALUE"), not by a Symbol",
|
|
426
|
+
str, str);
|
|
427
|
+
}
|
|
428
|
+
rb_raise(rb_eTypeError,
|
|
429
|
+
"a struct member is named by a String, not by a Symbol "
|
|
430
|
+
"(%"PRIsVALUE" has no member %"PRIsVALUE" either)",
|
|
431
|
+
klass, rb_inspect(str));
|
|
432
|
+
}
|
|
433
|
+
if ( ! RB_TYPE_P(name, T_STRING) && ! RB_TYPE_P(name, T_FIXNUM) ) {
|
|
434
|
+
rb_raise(rb_eTypeError,
|
|
435
|
+
"a struct member is named by a String or an Integer position "
|
|
436
|
+
"(got %s)", rb_obj_classname(name));
|
|
437
|
+
}
|
|
438
|
+
name_s = ca_struct_resolve_name(klass, name);
|
|
439
|
+
if ( NIL_P(name_s)
|
|
440
|
+
|| NIL_P(rb_hash_aref(rb_const_get(klass, rb_intern("MEMBER_TABLE")),
|
|
441
|
+
name_s)) ) {
|
|
442
|
+
rb_raise(rb_eArgError, "%"PRIsVALUE" has no member %"PRIsVALUE
|
|
443
|
+
" (members: %"PRIsVALUE")",
|
|
444
|
+
klass, rb_inspect(name),
|
|
445
|
+
rb_inspect(rb_const_get(klass, rb_intern("MEMBERS"))));
|
|
446
|
+
}
|
|
447
|
+
return name_s;
|
|
448
|
+
}
|
|
449
|
+
|
|
387
450
|
/* ---------------------------------------------------------------------
|
|
388
451
|
Shared write-dispatch helper reused by `[]=` and `initialize`.
|
|
389
452
|
Returns 1 if the member was written, 0 if neither table contained
|
|
@@ -446,7 +509,7 @@ static VALUE
|
|
|
446
509
|
rb_ca_struct_aref (VALUE self, VALUE name)
|
|
447
510
|
{
|
|
448
511
|
VALUE klass = rb_obj_class(self);
|
|
449
|
-
VALUE name_s =
|
|
512
|
+
VALUE name_s = ca_struct_member_name(klass, name);
|
|
450
513
|
|
|
451
514
|
/* Fast path. FAST_PRIMITIVES may be absent on subclasses built
|
|
452
515
|
outside Builder — fall through to the dispatch table in that
|
|
@@ -454,12 +517,14 @@ rb_ca_struct_aref (VALUE self, VALUE name)
|
|
|
454
517
|
if (rb_const_defined(klass, rb_intern("FAST_PRIMITIVES"))) {
|
|
455
518
|
VALUE fast_table = rb_const_get(klass, rb_intern("FAST_PRIMITIVES"));
|
|
456
519
|
VALUE entry = rb_hash_aref(fast_table, name_s);
|
|
457
|
-
|
|
520
|
+
VALUE data_val = rb_ivar_get(self, rb_intern("@data"));
|
|
521
|
+
CArray *ca;
|
|
522
|
+
TypedData_Get_Struct(data_val, CArray, &carray_data_type, ca);
|
|
523
|
+
/* The fast path reads ca->ptr, which only an entity holds. A nested
|
|
524
|
+
element's @data is a view on its parent's bytes and goes through the
|
|
525
|
+
dispatch procs below, which reach them through field views. */
|
|
526
|
+
if (!NIL_P(entry) && ca_is_entity(ca)) {
|
|
458
527
|
int kind = NUM2INT(rb_ary_entry(entry, 0));
|
|
459
|
-
VALUE data_val = rb_ivar_get(self, rb_intern("@data"));
|
|
460
|
-
CArray *ca;
|
|
461
|
-
TypedData_Get_Struct(data_val, CArray, &carray_data_type, ca);
|
|
462
|
-
/* @data is a CScalar entity, so ca->ptr is always valid. */
|
|
463
528
|
switch (kind) {
|
|
464
529
|
case FAST_KIND_PRIMITIVE: {
|
|
465
530
|
/* [kind, offset, type_code] */
|
|
@@ -502,8 +567,9 @@ rb_ca_struct_aref (VALUE self, VALUE name)
|
|
|
502
567
|
return rb_funcall(reader, rb_intern("call"), 1, data_val);
|
|
503
568
|
}
|
|
504
569
|
|
|
505
|
-
|
|
506
|
-
|
|
570
|
+
rb_raise(rb_eArgError, "%"PRIsVALUE" has no reader for member %"PRIsVALUE,
|
|
571
|
+
klass, name_s);
|
|
572
|
+
return Qnil;
|
|
507
573
|
}
|
|
508
574
|
|
|
509
575
|
/* ---------------------------------------------------------------------
|
|
@@ -514,18 +580,31 @@ static VALUE
|
|
|
514
580
|
rb_ca_struct_aset (VALUE self, VALUE name, VALUE val)
|
|
515
581
|
{
|
|
516
582
|
VALUE klass = rb_obj_class(self);
|
|
517
|
-
VALUE name_s
|
|
583
|
+
VALUE name_s;
|
|
584
|
+
|
|
585
|
+
/* The fast path writes into the record's bytes directly. */
|
|
586
|
+
rb_check_frozen(self);
|
|
587
|
+
name_s = ca_struct_member_name(klass, name);
|
|
588
|
+
|
|
589
|
+
/* An element is one record of values: it has no mask to hold UNDEF. A
|
|
590
|
+
record is masked in its record array (a[i] = UNDEF). */
|
|
591
|
+
if ( val == CA_UNDEF ) {
|
|
592
|
+
rb_raise(rb_eTypeError,
|
|
593
|
+
"a struct element has no masked state; mask the record in its "
|
|
594
|
+
"record array instead");
|
|
595
|
+
}
|
|
518
596
|
|
|
519
597
|
/* Fast path (see rb_ca_struct_aref for the absent-FAST_PRIMITIVES
|
|
520
598
|
rationale and entry-shape contract). */
|
|
521
599
|
if (rb_const_defined(klass, rb_intern("FAST_PRIMITIVES"))) {
|
|
522
600
|
VALUE fast_table = rb_const_get(klass, rb_intern("FAST_PRIMITIVES"));
|
|
523
601
|
VALUE entry = rb_hash_aref(fast_table, name_s);
|
|
524
|
-
|
|
602
|
+
VALUE data_val = rb_ivar_get(self, rb_intern("@data"));
|
|
603
|
+
CArray *ca;
|
|
604
|
+
TypedData_Get_Struct(data_val, CArray, &carray_data_type, ca);
|
|
605
|
+
/* Only an entity @data is written through ca->ptr (see the reader). */
|
|
606
|
+
if (!NIL_P(entry) && ca_is_entity(ca)) {
|
|
525
607
|
int kind = NUM2INT(rb_ary_entry(entry, 0));
|
|
526
|
-
VALUE data_val = rb_ivar_get(self, rb_intern("@data"));
|
|
527
|
-
CArray *ca;
|
|
528
|
-
TypedData_Get_Struct(data_val, CArray, &carray_data_type, ca);
|
|
529
608
|
switch (kind) {
|
|
530
609
|
case FAST_KIND_PRIMITIVE: {
|
|
531
610
|
ca_size_t offset = NUM2SIZE(rb_ary_entry(entry, 1));
|
|
@@ -565,9 +644,9 @@ rb_ca_struct_aset (VALUE self, VALUE name, VALUE val)
|
|
|
565
644
|
return val;
|
|
566
645
|
}
|
|
567
646
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
return
|
|
647
|
+
rb_raise(rb_eArgError, "%"PRIsVALUE" has no writer for member %"PRIsVALUE,
|
|
648
|
+
klass, name_s);
|
|
649
|
+
return Qnil;
|
|
571
650
|
}
|
|
572
651
|
|
|
573
652
|
/* ---------------------------------------------------------------------
|
|
@@ -689,7 +768,7 @@ void
|
|
|
689
768
|
Init_carray_struct (void)
|
|
690
769
|
{
|
|
691
770
|
/* Singleton on rb_cCArray so lib/carray/struct.rb can call it as
|
|
692
|
-
`CArray.
|
|
693
|
-
|
|
694
|
-
|
|
771
|
+
`CArray.install_struct_methods(klass)`. */
|
|
772
|
+
rb_define_private_method(rb_singleton_class(rb_cCArray), "install_struct_methods",
|
|
773
|
+
rb_carray_install_castruct_methods, 1);
|
|
695
774
|
}
|