carray 2.0.0 → 3.0.0
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/.yardopts +5 -25
- data/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/NEWS.md +3 -0
- data/README.md +128 -44
- data/carray.gemspec +22 -24
- data/ext/ca_array_pool.c +91 -0
- data/ext/ca_axis_descriptor.h +186 -0
- data/ext/ca_axis_dispatch.c +924 -0
- data/ext/ca_axis_group.c +1208 -0
- data/ext/ca_bincmp_dispatch.c +76 -0
- data/ext/ca_bincmp_dispatch.h +85 -0
- data/ext/ca_binop_dispatch.c +125 -0
- data/ext/ca_binop_dispatch.h +159 -0
- data/ext/ca_categorical_iterator.c +1375 -0
- data/ext/ca_compare.c +94 -0
- data/ext/ca_compare.h +26 -0
- data/ext/ca_composite_dispatch.c +414 -0
- data/ext/ca_composite_dispatch.h +116 -0
- data/ext/ca_for_buffer.h +96 -0
- data/ext/ca_for_each_element.h +241 -0
- data/ext/ca_group_iter.c +304 -0
- data/ext/ca_iter_substrate.h +325 -0
- data/ext/ca_kernel_iterator.c +4321 -0
- data/ext/ca_kernel_iterator.h +2603 -0
- data/ext/ca_moncmp_dispatch.c +37 -0
- data/ext/ca_moncmp_dispatch.h +62 -0
- data/ext/ca_monop_dispatch.c +200 -0
- data/ext/ca_monop_dispatch.h +235 -0
- data/ext/ca_obj_array.c +355 -359
- data/ext/ca_obj_bincmp.c +809 -0
- data/ext/ca_obj_binop.c +892 -0
- data/ext/ca_obj_bitarray.c +369 -164
- data/ext/ca_obj_bitfield.c +294 -234
- data/ext/ca_obj_block.c +189 -711
- data/ext/ca_obj_byte_swap.c +766 -0
- data/ext/ca_obj_const_string.c +965 -0
- data/ext/ca_obj_face.c +670 -0
- data/ext/ca_obj_face.h +247 -0
- data/ext/ca_obj_fake.c +228 -100
- data/ext/ca_obj_farray.c +54 -441
- data/ext/ca_obj_field.c +82 -529
- data/ext/ca_obj_fixlen_string.c +306 -0
- data/ext/ca_obj_grid.c +858 -440
- data/ext/ca_obj_meld.c +1034 -0
- data/ext/ca_obj_moncmp.c +569 -0
- data/ext/ca_obj_monop.c +1111 -0
- data/ext/ca_obj_object.c +774 -298
- data/ext/ca_obj_record.c +468 -0
- data/ext/ca_obj_reduce.c +97 -82
- data/ext/ca_obj_refer.c +569 -459
- data/ext/ca_obj_remap.c +475 -0
- data/ext/ca_obj_repeat.c +92 -477
- data/ext/ca_obj_roll.c +616 -0
- data/ext/ca_obj_select.c +344 -296
- data/ext/ca_obj_select_axis.c +1296 -0
- data/ext/ca_obj_shift.c +230 -792
- data/ext/ca_obj_source.c +78 -0
- data/ext/ca_obj_stack.c +1173 -0
- data/ext/ca_obj_stride.c +2501 -0
- data/ext/ca_obj_string.c +268 -0
- data/ext/ca_obj_tile.c +614 -0
- data/ext/ca_obj_time.c +546 -0
- data/ext/ca_obj_timedelta.c +435 -0
- data/ext/ca_obj_transpose.c +62 -516
- data/ext/ca_obj_triop.c +746 -0
- data/ext/ca_obj_unbound_repeat.c +208 -241
- data/ext/ca_obj_window.c +1131 -563
- data/ext/ca_op_byte_swap.c +175 -0
- data/ext/ca_op_ipower.c +319 -0
- data/ext/ca_op_powi.h +88 -0
- data/ext/ca_sort_kernels.h +132 -0
- data/ext/ca_sweep_engine.c +430 -0
- data/ext/ca_sweep_engine.h +157 -0
- data/ext/ca_transform_common.c +228 -0
- data/ext/ca_triop_dispatch.c +55 -0
- data/ext/ca_triop_dispatch.h +62 -0
- data/ext/carray.h +795 -402
- data/ext/carray_access.c +831 -711
- data/ext/carray_attribute.c +98 -330
- data/ext/carray_bincount.c +255 -0
- data/ext/carray_broadcast.c +283 -0
- data/ext/carray_call_cfunc.c +1360 -828
- data/ext/carray_call_cfunc.h +160 -0
- data/ext/carray_cast.c +1212 -301
- data/ext/carray_cast_func.rb +81 -40
- data/ext/carray_class.c +53 -63
- data/ext/carray_config.h +28 -0
- data/ext/carray_conversion.c +350 -346
- data/ext/carray_copy.c +156 -268
- data/ext/carray_core.c +1342 -199
- data/ext/carray_count.c +312 -0
- data/ext/carray_data_type.c +43 -19
- data/ext/carray_element.c +585 -213
- data/ext/carray_factorize.c +2542 -0
- data/ext/carray_generate.c +230 -559
- data/ext/carray_histogram.c +490 -0
- data/ext/carray_hold.c +228 -0
- data/ext/carray_index_classifier.c +1035 -0
- data/ext/carray_index_classifier.h +27 -0
- data/ext/carray_internal.h +120 -0
- data/ext/carray_kernels_bincmp.c +4445 -0
- data/ext/carray_kernels_binop.c +10979 -0
- data/ext/carray_kernels_init.c +36 -0
- data/ext/carray_kernels_map.c +3466 -0
- data/ext/carray_kernels_moncmp.c +2096 -0
- data/ext/carray_kernels_monop.c +18312 -0
- data/ext/carray_kernels_reduce_aggregate.c +25836 -0
- data/ext/carray_kernels_reduce_boolean.c +329 -0
- data/ext/carray_kernels_reduce_cumulative.c +14592 -0
- data/ext/carray_kernels_reduce_extreme.c +16947 -0
- data/ext/carray_kernels_reduce_variance.c +3909 -0
- data/ext/carray_kernels_scan.c +3692 -0
- data/ext/carray_kernels_search.c +32137 -0
- data/ext/carray_kernels_sort.c +10625 -0
- data/ext/carray_kernels_triop.c +1391 -0
- data/ext/carray_lazy.c +567 -0
- data/ext/carray_loop.c +88 -200
- data/ext/carray_mask.c +848 -154
- data/ext/carray_math_kernel.h +120 -0
- data/ext/carray_mathfunc.c +10 -241
- data/ext/carray_median_percentile.c +1257 -0
- data/ext/carray_memory_view.c +1625 -0
- data/ext/carray_operator.c +1526 -318
- data/ext/carray_order.c +664 -1394
- data/ext/carray_partition.c +416 -0
- data/ext/carray_random.c +518 -0
- data/ext/carray_scatter.c +357 -0
- data/ext/carray_slab.c +1219 -0
- data/ext/carray_slab.h +84 -0
- data/ext/carray_sort.c +829 -0
- data/ext/carray_sort_kernel.c +620 -0
- data/ext/carray_struct.c +695 -0
- data/ext/carray_test.c +343 -229
- data/ext/carray_undef.c +34 -17
- data/ext/carray_utils.c +175 -74
- data/ext/extconf.rb +216 -55
- data/ext/mk_call_cfunc.rb +480 -0
- data/ext/mkkernel.rb +8842 -0
- data/ext/ruby_carray.c +202 -101
- data/ext/version.h +4 -14
- data/ext/version.rb +5 -13
- data/lib/carray/arrow_tensor.rb +401 -0
- data/lib/carray/attribute.rb +166 -0
- data/lib/carray/autoload_carray.rb +220 -0
- data/lib/carray/autoload_method_extension.rb +44 -0
- data/lib/carray/axis_group.rb +711 -0
- data/lib/carray/basics.rb +481 -0
- data/lib/carray/bincount_nd.rb +358 -0
- data/lib/carray/block_iterator.rb +604 -0
- data/lib/carray/boolean_reduce.rb +109 -0
- data/lib/carray/categorical.rb +561 -0
- data/lib/carray/categorical_iterator.rb +1062 -0
- data/lib/carray/complex.rb +150 -0
- data/lib/carray/conditional.rb +216 -0
- data/lib/carray/const_string.rb +228 -0
- data/lib/carray/construct.rb +139 -328
- data/lib/carray/core_extensions.rb +240 -0
- data/lib/carray/data_type_extension.rb +233 -0
- data/lib/carray/fixlen_string.rb +95 -0
- data/lib/carray/frame/concat.rb +132 -0
- data/lib/carray/frame/convert.rb +95 -0
- data/lib/carray/frame/csv_parser.rb +211 -0
- data/lib/carray/frame/frame.rb +649 -0
- data/lib/carray/frame/group.rb +186 -0
- data/lib/carray/frame/io.rb +164 -0
- data/lib/carray/frame/join.rb +248 -0
- data/lib/carray/frame/records.rb +99 -0
- data/lib/carray/frame/sort.rb +113 -0
- data/lib/carray/frame/verbs.rb +299 -0
- data/lib/carray/frame.rb +16 -0
- data/lib/carray/histogram.rb +512 -0
- data/lib/carray/inspect.rb +37 -20
- data/lib/carray/iterator.rb +57 -349
- data/lib/carray/lazy.rb +889 -0
- data/lib/carray/mask_gap_fill.rb +200 -0
- data/lib/carray/math.rb +78 -342
- data/lib/carray/meld_reduce.rb +289 -0
- data/lib/carray/methods/align_addr.rb +116 -0
- data/lib/carray/methods/bin.rb +128 -0
- data/lib/carray/methods/bincount.rb +87 -0
- data/lib/carray/methods/bit_string.rb +92 -0
- data/lib/carray/methods/broadcast.rb +63 -0
- data/lib/carray/methods/choose.rb +39 -0
- data/lib/carray/methods/composition.rb +280 -0
- data/lib/carray/methods/gather_nd.rb +206 -0
- data/lib/carray/methods/index.rb +39 -0
- data/lib/carray/methods/insert_block.rb +99 -0
- data/lib/carray/methods/is_in.rb +141 -0
- data/lib/carray/methods/join.rb +90 -0
- data/lib/carray/methods/locate_addr.rb +47 -0
- data/lib/carray/methods/mask_duplicates.rb +41 -0
- data/lib/carray/methods/meshgrid.rb +91 -0
- data/lib/carray/methods/mode.rb +126 -0
- data/lib/carray/methods/nunique.rb +46 -0
- data/lib/carray/methods/resize.rb +56 -0
- data/lib/carray/methods/snap.rb +156 -0
- data/lib/carray/methods/string_format.rb +57 -0
- data/lib/carray/methods/unique.rb +47 -0
- data/lib/carray/methods/value_counts.rb +71 -0
- data/lib/carray/mkmf.rb +124 -101
- data/lib/carray/runtime.rb +108 -0
- data/lib/carray/serialize.rb +478 -167
- data/lib/carray/slab_iterator.rb +292 -0
- data/lib/carray/stack.rb +291 -0
- data/lib/carray/string.rb +56 -180
- data/lib/carray/string_operation_extension.rb +289 -0
- data/lib/carray/struct.rb +335 -323
- data/lib/carray/struct_builder.rb +697 -0
- data/lib/carray/table.rb +41 -2
- data/lib/carray/time.rb +2255 -38
- data/lib/carray/window_iterator.rb +655 -0
- data/lib/carray.rb +55 -57
- metadata +163 -130
- data/Rakefile +0 -51
- data/TODO.md +0 -18
- data/ext/ca_iter_block.c +0 -257
- data/ext/ca_iter_dimension.c +0 -299
- data/ext/ca_iter_window.c +0 -214
- data/ext/ca_obj_mapping.c +0 -644
- data/ext/carray_iterator.c +0 -641
- data/ext/carray_math.rb +0 -850
- data/ext/carray_numeric.c +0 -259
- data/ext/carray_sort_addr.c +0 -254
- data/ext/carray_stat.c +0 -2100
- data/ext/carray_stat_proc.rb +0 -1999
- data/ext/mkmath.rb +0 -741
- data/ext/ruby_ccomplex.c +0 -509
- data/ext/ruby_float_func.c +0 -86
- data/lib/carray/array.rb +0 -8
- data/lib/carray/autoload/autoload_base.rb +0 -19
- data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
- data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
- data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
- data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
- data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
- data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
- data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
- data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
- data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
- data/lib/carray/autoload/autoload_gem_random.rb +0 -8
- data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
- data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
- data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
- data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
- data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
- data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
- data/lib/carray/autoload/autoload_object_link.rb +0 -1
- data/lib/carray/autoload/autoload_object_pack.rb +0 -2
- data/lib/carray/autoload.rb +0 -141
- data/lib/carray/basic.rb +0 -191
- data/lib/carray/broadcast.rb +0 -101
- data/lib/carray/compose.rb +0 -315
- data/lib/carray/convert.rb +0 -115
- data/lib/carray/info.rb +0 -110
- data/lib/carray/io/imagemagick.rb +0 -235
- data/lib/carray/mask.rb +0 -102
- data/lib/carray/math/histogram.rb +0 -177
- data/lib/carray/math/recurrence.rb +0 -93
- data/lib/carray/object/ca_obj_iterator.rb +0 -50
- data/lib/carray/object/ca_obj_link.rb +0 -50
- data/lib/carray/object/ca_obj_pack.rb +0 -99
- data/lib/carray/obsolete.rb +0 -256
- data/lib/carray/ordering.rb +0 -181
- data/lib/carray/testing.rb +0 -51
- data/lib/carray/transform.rb +0 -109
- data/misc/Methods.ja.md +0 -182
- data/misc/NOTE +0 -51
- data/spec/Classes/CABitfield_spec.rb +0 -58
- data/spec/Classes/CABlockIterator_spec.rb +0 -114
- data/spec/Classes/CABlock_spec.rb +0 -205
- data/spec/Classes/CAField_spec.rb +0 -39
- data/spec/Classes/CAGrid_spec.rb +0 -75
- data/spec/Classes/CAMap_spec.rb +0 -0
- data/spec/Classes/CAMapping_spec.rb +0 -105
- data/spec/Classes/CAObject_attribute_spec.rb +0 -33
- data/spec/Classes/CAObject_spec.rb +0 -33
- data/spec/Classes/CARefer_spec.rb +0 -93
- data/spec/Classes/CARepeat_spec.rb +0 -65
- data/spec/Classes/CASelect_spec.rb +0 -22
- data/spec/Classes/CAShift_spec.rb +0 -16
- data/spec/Classes/CAStruct_spec.rb +0 -71
- data/spec/Classes/CATranspose_spec.rb +0 -60
- data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
- data/spec/Classes/CAWindow_spec.rb +0 -54
- data/spec/Classes/CAWrap_spec.rb +0 -8
- data/spec/Classes/CArray_spec.rb +0 -184
- data/spec/Classes/CScalar_spec.rb +0 -55
- data/spec/Classes/ex1.rb +0 -46
- data/spec/Features/feature_130_spec.rb +0 -19
- data/spec/Features/feature_attributes_spec.rb +0 -280
- data/spec/Features/feature_boolean_spec.rb +0 -98
- data/spec/Features/feature_broadcast.rb +0 -116
- data/spec/Features/feature_cast_function.rb +0 -19
- data/spec/Features/feature_cast_spec.rb +0 -33
- data/spec/Features/feature_class_spec.rb +0 -84
- data/spec/Features/feature_complex_spec.rb +0 -42
- data/spec/Features/feature_composite_spec.rb +0 -124
- data/spec/Features/feature_convert_spec.rb +0 -46
- data/spec/Features/feature_copy_spec.rb +0 -123
- data/spec/Features/feature_creation_spec.rb +0 -84
- data/spec/Features/feature_element_spec.rb +0 -144
- data/spec/Features/feature_extream_spec.rb +0 -54
- data/spec/Features/feature_generate_spec.rb +0 -74
- data/spec/Features/feature_index_spec.rb +0 -69
- data/spec/Features/feature_mask_spec.rb +0 -580
- data/spec/Features/feature_math_spec.rb +0 -97
- data/spec/Features/feature_order_spec.rb +0 -146
- data/spec/Features/feature_ref_store_spec.rb +0 -209
- data/spec/Features/feature_serialization_spec.rb +0 -125
- data/spec/Features/feature_stat_spec.rb +0 -397
- data/spec/Features/feature_virtual_spec.rb +0 -48
- data/spec/Features/method_eq_spec.rb +0 -81
- data/spec/Features/method_is_nan_spec.rb +0 -12
- data/spec/Features/method_map_spec.rb +0 -54
- data/spec/Features/method_max_with.rb +0 -20
- data/spec/Features/method_min_with.rb +0 -19
- data/spec/Features/method_ne_spec.rb +0 -18
- data/spec/Features/method_project_spec.rb +0 -188
- data/spec/Features/method_ref_spec.rb +0 -27
- data/spec/Features/method_round_spec.rb +0 -11
- data/spec/Features/method_s_linspace_spec.rb +0 -48
- data/spec/Features/method_s_span_spec.rb +0 -14
- data/spec/Features/method_seq_spec.rb +0 -47
- data/spec/Features/method_sort_with.rb +0 -43
- data/spec/Features/method_sorted_with.rb +0 -29
- data/spec/Features/method_span_spec.rb +0 -42
- data/spec/Features/method_wrap_readonly_spec.rb +0 -43
- data/spec/UnitTest/test_CAVirtual.rb +0 -214
- data/spec/spec_all.rb +0 -10
- data/utils/ca_ase.rb +0 -21
- data/utils/ca_methods.rb +0 -15
- data/utils/cast_checker.rb +0 -30
- data/utils/convert_test.rb +0 -73
- data/utils/extract_yard.rb +0 -22
- data/utils/guess_shape.rb +0 -76
- data/utils/monkey_patch_methods.rb +0 -62
- data/utils/remove_resource_fork.sh +0 -5
data/ext/carray_test.c
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
/* ---------------------------------------------------------------------------
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
This file includes the modified routine (ca_mem_hash) from
|
|
10
|
-
|
|
11
|
-
* string.c in Ruby distribution ( ruby-1.8.6 )
|
|
12
|
-
|
|
13
|
-
Copyright (C) 1993-2003 Yukihiro Matsumoto
|
|
14
|
-
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
|
15
|
-
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
|
3
|
+
Predicates and equality/hash for CArray:
|
|
4
|
+
- internal check_* / has_same_* helpers used across ext/ sources
|
|
5
|
+
- Ruby surface: valid_index? / valid_addr? / same_shape? / == /
|
|
6
|
+
eql? / hash / freeze (docs in yard-stubs/carray_test.rb)
|
|
7
|
+
- per-dtype element-equality table `ca_eql[CA_NTYPE]`
|
|
8
|
+
- `ca_compare_common` shared body for `==` and `eql?`
|
|
16
9
|
|
|
17
10
|
---------------------------------------------------------------------------- */
|
|
18
11
|
|
|
19
12
|
#include "carray.h"
|
|
20
13
|
|
|
21
14
|
static ID id_equal;
|
|
15
|
+
static ID id_eql;
|
|
22
16
|
|
|
23
|
-
/*
|
|
17
|
+
/* Internal checking routines: raise on structural mismatch. Used
|
|
18
|
+
throughout ext/ sources at API boundaries; not exposed to Ruby. */
|
|
24
19
|
|
|
25
20
|
void
|
|
26
21
|
ca_check_type (void *ap, int8_t data_type)
|
|
@@ -127,7 +122,7 @@ rb_check_carray_object (VALUE arg)
|
|
|
127
122
|
}
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
/*
|
|
125
|
+
/* Internal predicate routines: return 0/1, do not raise. */
|
|
131
126
|
|
|
132
127
|
int
|
|
133
128
|
ca_has_same_shape (void *ap1, void *ap2)
|
|
@@ -164,8 +159,8 @@ ca_is_valid_index (void *ap, ca_size_t *idx)
|
|
|
164
159
|
return 1;
|
|
165
160
|
}
|
|
166
161
|
|
|
167
|
-
/*
|
|
168
|
-
|
|
162
|
+
/* rb_ca_is_type(arg, type) — returns 1 if arg is a CArray whose
|
|
163
|
+
data_type equals `type`, else raises if not a CArray. */
|
|
169
164
|
int
|
|
170
165
|
rb_ca_is_type (VALUE arg, int type)
|
|
171
166
|
{
|
|
@@ -177,59 +172,13 @@ rb_ca_is_type (VALUE arg, int type)
|
|
|
177
172
|
return ca->data_type == type;
|
|
178
173
|
}
|
|
179
174
|
|
|
180
|
-
/*
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
{
|
|
185
|
-
if ( ! rb_obj_is_data_class(rtype) ) {
|
|
186
|
-
VALUE inspect = rb_inspect(rtype);
|
|
187
|
-
rb_raise(rb_eRuntimeError,
|
|
188
|
-
"<%s> is not a data_class, which should has the features\n" \
|
|
189
|
-
" * constant data_class::DATA_SIZE -> integer\n" \
|
|
190
|
-
" * constant data_class::MEMBERS -> array of string\n" \
|
|
191
|
-
" * constant data_class::MEMBER_TABLE -> hash\n" \
|
|
192
|
-
" * method data_class.decode(str) -> data_class object\n" \
|
|
193
|
-
" * method data_class#encode() -> string", StringValuePtr(inspect));
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
VALUE
|
|
198
|
-
rb_obj_is_data_class (VALUE rtype)
|
|
199
|
-
{
|
|
200
|
-
VALUE has_data_size, has_member_names, has_member_table;
|
|
201
|
-
VALUE has_encode, has_decode;
|
|
202
|
-
if ( TYPE(rtype) == T_CLASS ) {
|
|
203
|
-
has_data_size =
|
|
204
|
-
rb_funcall(rtype, rb_intern("const_defined?"), 1, rb_str_new2("DATA_SIZE"));
|
|
205
|
-
has_member_names =
|
|
206
|
-
rb_funcall(rtype, rb_intern("const_defined?"), 1, rb_str_new2("MEMBERS"));
|
|
207
|
-
has_member_table =
|
|
208
|
-
rb_funcall(rtype, rb_intern("const_defined?"), 1, rb_str_new2("MEMBER_TABLE"));
|
|
209
|
-
has_encode =
|
|
210
|
-
rb_funcall(rtype, rb_intern("method_defined?"), 1, rb_str_new2("encode"));
|
|
211
|
-
has_decode = rb_respond_to(rtype, rb_intern("decode"));
|
|
212
|
-
return ( RTEST(has_data_size) &&
|
|
213
|
-
RTEST(has_member_table) && RTEST(has_member_names) &&
|
|
214
|
-
RTEST(has_encode) && RTEST(has_decode) ) ? Qtrue : Qfalse;
|
|
215
|
-
}
|
|
216
|
-
return Qfalse;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
static VALUE
|
|
220
|
-
rb_ca_s_is_data_class (VALUE self, VALUE rklass)
|
|
221
|
-
{
|
|
222
|
-
return rb_obj_is_data_class(rklass);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/* ------------------------------------------------------------- */
|
|
226
|
-
|
|
227
|
-
/* @overload valid_index? (*idx)
|
|
228
|
-
|
|
229
|
-
(Inquiry)
|
|
230
|
-
Returns true if the given number list is valid as array index for the object
|
|
231
|
-
*/
|
|
175
|
+
/* [MOVED] data_class identity predicates
|
|
176
|
+
(ca_check_data_class / rb_obj_is_data_class / rb_ca_s_is_data_class)
|
|
177
|
+
live in ca_obj_record.c; signatures stay in carray.h for cross-file
|
|
178
|
+
extern use. */
|
|
232
179
|
|
|
180
|
+
/* CArray#valid_index?(*idx) — 1 if the index tuple is in range, else 0.
|
|
181
|
+
* The number of indices must equal ndim (raises otherwise). */
|
|
233
182
|
static VALUE
|
|
234
183
|
rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
235
184
|
{
|
|
@@ -245,11 +194,6 @@ rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
|
245
194
|
}
|
|
246
195
|
for (i=0; i<ca->ndim; i++) {
|
|
247
196
|
idx = NUM2SIZE(argv[i]);
|
|
248
|
-
/*
|
|
249
|
-
if ( idx < 0 ) {
|
|
250
|
-
idx += ca->dim[i];
|
|
251
|
-
}
|
|
252
|
-
*/
|
|
253
197
|
if ( idx < 0 || idx >= ca->dim[i] ) {
|
|
254
198
|
return Qfalse;
|
|
255
199
|
}
|
|
@@ -258,12 +202,7 @@ rb_ca_is_valid_index (int argc, VALUE *argv, VALUE self)
|
|
|
258
202
|
return Qtrue;
|
|
259
203
|
}
|
|
260
204
|
|
|
261
|
-
/*
|
|
262
|
-
|
|
263
|
-
(Inquiry)
|
|
264
|
-
Returns true if the given number is valid as array address for the object
|
|
265
|
-
*/
|
|
266
|
-
|
|
205
|
+
/* CArray#valid_addr?(addr) — 1 if addr is in range 0...elements, else 0. */
|
|
267
206
|
static VALUE
|
|
268
207
|
rb_ca_is_valid_addr (VALUE self, VALUE raddr)
|
|
269
208
|
{
|
|
@@ -272,11 +211,6 @@ rb_ca_is_valid_addr (VALUE self, VALUE raddr)
|
|
|
272
211
|
|
|
273
212
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
274
213
|
addr = NUM2SIZE(raddr);
|
|
275
|
-
/*
|
|
276
|
-
if ( addr < 0 ) {
|
|
277
|
-
addr += ca->elements;
|
|
278
|
-
}
|
|
279
|
-
*/
|
|
280
214
|
if ( addr < 0 || addr >= ca->elements ) {
|
|
281
215
|
return Qfalse;
|
|
282
216
|
}
|
|
@@ -285,12 +219,8 @@ rb_ca_is_valid_addr (VALUE self, VALUE raddr)
|
|
|
285
219
|
}
|
|
286
220
|
}
|
|
287
221
|
|
|
288
|
-
/*
|
|
289
|
-
|
|
290
|
-
(Inquiry)
|
|
291
|
-
Returns true if the object has the same shape with the given array.
|
|
292
|
-
*/
|
|
293
|
-
|
|
222
|
+
/* CArray#same_shape?(other) — 1 if self and other share ndim and dim[].
|
|
223
|
+
* Scalars compare true against any array (see ca_has_same_shape). */
|
|
294
224
|
static VALUE
|
|
295
225
|
rb_ca_has_same_shape (VALUE self, VALUE other)
|
|
296
226
|
{
|
|
@@ -302,25 +232,25 @@ rb_ca_has_same_shape (VALUE self, VALUE other)
|
|
|
302
232
|
|
|
303
233
|
/* ----------------------------------------------------------------------- */
|
|
304
234
|
|
|
305
|
-
typedef int (*ca_eql_func)();
|
|
235
|
+
typedef int (*ca_eql_func)(const char *, const char *, ca_size_t);
|
|
306
236
|
|
|
307
237
|
#define eql_type(type) \
|
|
308
238
|
static int \
|
|
309
|
-
eql_## type (
|
|
239
|
+
eql_## type (const char *a, const char *b, ca_size_t bytes) \
|
|
310
240
|
{ \
|
|
311
|
-
return ( *a == *b ); \
|
|
241
|
+
return ( *(const type*)a == *(const type*)b ); \
|
|
312
242
|
}
|
|
313
243
|
|
|
314
244
|
static int
|
|
315
|
-
eql_VALUE (
|
|
245
|
+
eql_VALUE (const char *a, const char *b, ca_size_t bytes)
|
|
316
246
|
{
|
|
317
|
-
return (
|
|
247
|
+
return RTEST(rb_funcall(*(const VALUE*)a, id_equal, 1, *(const VALUE*)b)) ? 1 : 0;
|
|
318
248
|
}
|
|
319
249
|
|
|
320
250
|
static int
|
|
321
|
-
eql_data (char *a, char *b,
|
|
251
|
+
eql_data (const char *a, const char *b, ca_size_t bytes)
|
|
322
252
|
{
|
|
323
|
-
return ( memcmp(a, b, bytes) ) ? 0 : 1;
|
|
253
|
+
return ( memcmp(a, b, (size_t)bytes) ) ? 0 : 1;
|
|
324
254
|
}
|
|
325
255
|
|
|
326
256
|
eql_type(boolean8_t)
|
|
@@ -334,10 +264,16 @@ eql_type(int64_t)
|
|
|
334
264
|
eql_type(uint64_t)
|
|
335
265
|
eql_type(float32_t)
|
|
336
266
|
eql_type(float64_t)
|
|
337
|
-
eql_type(float128_t)
|
|
338
267
|
eql_type(cmplx64_t)
|
|
339
268
|
eql_type(cmplx128_t)
|
|
340
|
-
|
|
269
|
+
|
|
270
|
+
/* Placeholder for CA_FLOAT128 / CA_CMPLX256 slots (ca_valid[12] =
|
|
271
|
+
ca_valid[15] = 0, so never invoked). */
|
|
272
|
+
static int
|
|
273
|
+
eql_retired (const char *a, const char *b, ca_size_t bytes)
|
|
274
|
+
{
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
341
277
|
|
|
342
278
|
ca_eql_func
|
|
343
279
|
ca_eql[CA_NTYPE] = {
|
|
@@ -353,15 +289,29 @@ ca_eql[CA_NTYPE] = {
|
|
|
353
289
|
eql_uint64_t,
|
|
354
290
|
eql_float32_t,
|
|
355
291
|
eql_float64_t,
|
|
356
|
-
|
|
292
|
+
eql_retired, /* float128_t: ca_valid[12] = 0 */
|
|
357
293
|
eql_cmplx64_t,
|
|
358
294
|
eql_cmplx128_t,
|
|
359
|
-
|
|
295
|
+
eql_retired, /* cmplx256_t: ca_valid[15] = 0 */
|
|
360
296
|
eql_VALUE,
|
|
361
297
|
};
|
|
362
298
|
|
|
363
|
-
|
|
364
|
-
|
|
299
|
+
/* ca_compare_common(a, b, strict) — shared body of ca_equal (==) and
|
|
300
|
+
* ca_eql_strict (eql?). Returns 1 if arrays match under the selected
|
|
301
|
+
* semantics, else 0.
|
|
302
|
+
*
|
|
303
|
+
* Common structure: metadata pre-check (scalar / data_type / bytes /
|
|
304
|
+
* ndim / elements / dim), mask attach via ca_attach_n (recurses into
|
|
305
|
+
* mask), unified loop over the four masked/unmasked combinations.
|
|
306
|
+
*
|
|
307
|
+
* The only difference is the per-element comparator:
|
|
308
|
+
* == : ca_eql[data_type] (type-specific, so float NaN != NaN)
|
|
309
|
+
* eql?: memcmp for numeric, rb_funcall(:eql?) for CA_OBJECT
|
|
310
|
+
*
|
|
311
|
+
* The unmasked-unmasked branch takes a bulk memcmp or per-cell
|
|
312
|
+
* shortcut to amortise per-element function pointer dispatch. */
|
|
313
|
+
static int
|
|
314
|
+
ca_compare_common (void *ap, void *bp, int strict)
|
|
365
315
|
{
|
|
366
316
|
CArray *ca = (CArray *) ap;
|
|
367
317
|
CArray *cb = (CArray *) bp;
|
|
@@ -372,83 +322,121 @@ ca_equal (void *ap, void *bp)
|
|
|
372
322
|
ca_size_t bytes;
|
|
373
323
|
char *pa;
|
|
374
324
|
char *pb;
|
|
375
|
-
ca_eql_func eql;
|
|
325
|
+
ca_eql_func eql = NULL; /* used only when !strict */
|
|
326
|
+
int is_object;
|
|
376
327
|
|
|
377
|
-
if ( ca_is_scalar(ca) ^ ca_is_scalar(cb) ) {
|
|
328
|
+
if ( ca_is_scalar(ca) ^ ca_is_scalar(cb) ) {
|
|
378
329
|
return 0;
|
|
379
330
|
}
|
|
380
|
-
|
|
381
|
-
if ( ca->data_type != cb->data_type ) { /* data_type comparison */
|
|
331
|
+
if ( ca->data_type != cb->data_type ) {
|
|
382
332
|
return 0;
|
|
383
333
|
}
|
|
384
|
-
|
|
385
|
-
if ( ca->bytes != cb->bytes ) { /* data_type comparison */
|
|
334
|
+
if ( ca->bytes != cb->bytes ) {
|
|
386
335
|
return 0;
|
|
387
336
|
}
|
|
388
|
-
|
|
389
|
-
if ( ca->ndim != cb->ndim ) { /* ndim comparison */
|
|
337
|
+
if ( ca->ndim != cb->ndim ) {
|
|
390
338
|
return 0;
|
|
391
339
|
}
|
|
392
|
-
|
|
393
|
-
if ( ca->elements != cb->elements ) { /* elements comparison */
|
|
340
|
+
if ( ca->elements != cb->elements ) {
|
|
394
341
|
return 0;
|
|
395
342
|
}
|
|
396
|
-
|
|
397
343
|
for (i=0; i<ca->ndim; i++) {
|
|
398
|
-
if ( ca->dim[i] != cb->dim[i] ) {
|
|
344
|
+
if ( ca->dim[i] != cb->dim[i] ) {
|
|
399
345
|
return 0;
|
|
400
346
|
}
|
|
401
347
|
}
|
|
402
348
|
|
|
403
|
-
ca_attach_n(2, ca, cb);
|
|
349
|
+
ca_attach_n(2, ca, cb); /* recurses into ca->mask / cb->mask */
|
|
404
350
|
|
|
405
351
|
masked_a = ca_is_any_masked(ca);
|
|
406
352
|
masked_b = ca_is_any_masked(cb);
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
353
|
+
bytes = ca->bytes;
|
|
354
|
+
pa = ca->ptr;
|
|
355
|
+
pb = cb->ptr;
|
|
356
|
+
is_object = ( ca->data_type == CA_OBJECT );
|
|
357
|
+
|
|
358
|
+
if ( ! strict ) {
|
|
359
|
+
eql = ca_eql[ca->data_type];
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* unmasked-unmasked fast path: one bulk memcmp for numeric, per-cell
|
|
363
|
+
rb_funcall for CA_OBJECT. Avoids per-element function pointer dispatch
|
|
364
|
+
and enables SIMD memcmp on the common case. For strict (eql?) numeric
|
|
365
|
+
comparison is bitwise (= NaN.eql?(NaN) yields true since their bit
|
|
366
|
+
patterns match), so memcmp gives the right semantics. For non-strict
|
|
367
|
+
(==) of numeric data_types, type-equality is byte-equality EXCEPT for
|
|
368
|
+
floats where -0.0 == +0.0 (different bit pattern, same value) and
|
|
369
|
+
NaN != NaN (same bit pattern, unequal value) -- so we must keep the
|
|
370
|
+
per-element comparator there.
|
|
371
|
+
|
|
372
|
+
Integer / bool / fixlen data_types are byte-exact, so memcmp matches both
|
|
373
|
+
semantics. data_type >= CA_FLOAT32 (= floats / complex / object) needs
|
|
374
|
+
the comparator. */
|
|
375
|
+
if ( ! masked_a && ! masked_b ) {
|
|
376
|
+
if ( is_object ) {
|
|
377
|
+
ID id = strict ? id_eql : id_equal;
|
|
378
|
+
VALUE *va = (VALUE *) pa;
|
|
379
|
+
VALUE *vb = (VALUE *) pb;
|
|
380
|
+
for (i=0; i<ca->elements; i++) {
|
|
381
|
+
volatile VALUE x = va[i];
|
|
382
|
+
volatile VALUE y = vb[i];
|
|
383
|
+
if ( ! RTEST(rb_funcall(x, id, 1, y)) ) {
|
|
384
|
+
flag = 0;
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
422
387
|
}
|
|
423
|
-
pa += bytes; pb += bytes;
|
|
424
388
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
flag = 0;
|
|
431
|
-
break;
|
|
432
|
-
}
|
|
433
|
-
pa += bytes; pb += bytes;
|
|
389
|
+
else if ( strict
|
|
390
|
+
|| ca->data_type <= CA_UINT64
|
|
391
|
+
|| ca->data_type == CA_FIXLEN ) {
|
|
392
|
+
/* bytewise comparable: single memcmp */
|
|
393
|
+
flag = ( memcmp(pa, pb, (size_t)(ca->elements * bytes)) == 0 ) ? 1 : 0;
|
|
434
394
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
395
|
+
else {
|
|
396
|
+
/* float / complex == : per-element comparator preserves NaN/-0.0 semantics */
|
|
397
|
+
for (i=0; i<ca->elements; i++) {
|
|
398
|
+
if ( ! eql(pa, pb, bytes) ) {
|
|
399
|
+
flag = 0;
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
pa += bytes; pb += bytes;
|
|
442
403
|
}
|
|
443
|
-
pa += bytes; pb += bytes;
|
|
444
404
|
}
|
|
445
405
|
}
|
|
446
|
-
else {
|
|
406
|
+
else {
|
|
407
|
+
/* masked path: unified loop. ma/mb NULL => that side has no any-masked
|
|
408
|
+
cells. Loop invariants are simple enough that branch prediction
|
|
409
|
+
absorbs the per-iteration NULL test. */
|
|
410
|
+
ma = masked_a ? (boolean8_t *) ca->mask->ptr : NULL;
|
|
411
|
+
mb = masked_b ? (boolean8_t *) cb->mask->ptr : NULL;
|
|
447
412
|
for (i=0; i<ca->elements; i++) {
|
|
448
|
-
|
|
413
|
+
boolean8_t am = ma ? ma[i] : 0;
|
|
414
|
+
boolean8_t bm = mb ? mb[i] : 0;
|
|
415
|
+
if ( am != bm ) {
|
|
449
416
|
flag = 0;
|
|
450
417
|
break;
|
|
451
418
|
}
|
|
419
|
+
if ( ! am ) {
|
|
420
|
+
int eq;
|
|
421
|
+
if ( is_object ) {
|
|
422
|
+
volatile VALUE x = *(VALUE *) pa;
|
|
423
|
+
volatile VALUE y = *(VALUE *) pb;
|
|
424
|
+
ID id = strict ? id_eql : id_equal;
|
|
425
|
+
eq = RTEST(rb_funcall(x, id, 1, y));
|
|
426
|
+
}
|
|
427
|
+
else if ( strict
|
|
428
|
+
|| ca->data_type <= CA_UINT64
|
|
429
|
+
|| ca->data_type == CA_FIXLEN ) {
|
|
430
|
+
eq = ( memcmp(pa, pb, (size_t)bytes) == 0 );
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
eq = eql(pa, pb, bytes);
|
|
434
|
+
}
|
|
435
|
+
if ( ! eq ) {
|
|
436
|
+
flag = 0;
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
452
440
|
pa += bytes; pb += bytes;
|
|
453
441
|
}
|
|
454
442
|
}
|
|
@@ -458,12 +446,22 @@ ca_equal (void *ap, void *bp)
|
|
|
458
446
|
return flag;
|
|
459
447
|
}
|
|
460
448
|
|
|
461
|
-
|
|
449
|
+
int
|
|
450
|
+
ca_equal (void *ap, void *bp)
|
|
451
|
+
{
|
|
452
|
+
return ca_compare_common(ap, bp, 0);
|
|
453
|
+
}
|
|
462
454
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
455
|
+
static int
|
|
456
|
+
ca_eql_strict (void *ap, void *bp)
|
|
457
|
+
{
|
|
458
|
+
return ca_compare_common(ap, bp, 1);
|
|
459
|
+
}
|
|
466
460
|
|
|
461
|
+
/* CArray#==(other) — elementwise equality returning true / false.
|
|
462
|
+
* data_class, data_type, shape, and mask state must all match; NaN
|
|
463
|
+
* compares unequal per IEEE semantics. Non-CArray other returns
|
|
464
|
+
* false. */
|
|
467
465
|
static VALUE
|
|
468
466
|
rb_ca_equal (VALUE self, VALUE other)
|
|
469
467
|
{
|
|
@@ -480,7 +478,7 @@ rb_ca_equal (VALUE self, VALUE other)
|
|
|
480
478
|
else {
|
|
481
479
|
VALUE dc1 = rb_ca_data_class(self);
|
|
482
480
|
VALUE dc2 = rb_ca_data_class(other);
|
|
483
|
-
if ( ! rb_funcall(dc1,
|
|
481
|
+
if ( ! RTEST(rb_funcall(dc1, id_equal, 1, dc2)) ) {
|
|
484
482
|
return Qfalse;
|
|
485
483
|
}
|
|
486
484
|
}
|
|
@@ -492,100 +490,115 @@ rb_ca_equal (VALUE self, VALUE other)
|
|
|
492
490
|
return ( ca_equal(ca, cb) ) ? Qtrue : Qfalse;
|
|
493
491
|
}
|
|
494
492
|
|
|
495
|
-
/*
|
|
496
|
-
|
|
493
|
+
/* CArray#eql?(other) — Hash-invariant equality (satisfies a.eql?(b) =>
|
|
494
|
+
* a.hash == b.hash). Same structural checks as ==, but element
|
|
495
|
+
* comparison is bitwise (numeric) or Object#eql? (CA_OBJECT), so
|
|
496
|
+
* NaN.eql?(NaN) holds. */
|
|
497
|
+
static VALUE
|
|
498
|
+
rb_ca_eql (VALUE self, VALUE other)
|
|
499
|
+
{
|
|
500
|
+
CArray *ca, *cb;
|
|
497
501
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
502
|
+
if ( ! rb_obj_is_carray(other) ) {
|
|
503
|
+
return Qfalse;
|
|
504
|
+
}
|
|
501
505
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
506
|
+
if ( rb_ca_has_data_class(self) || rb_ca_has_data_class(other) ) {
|
|
507
|
+
if ( rb_ca_has_data_class(self) ^ rb_ca_has_data_class(other) ) {
|
|
508
|
+
return Qfalse;
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
VALUE dc1 = rb_ca_data_class(self);
|
|
512
|
+
VALUE dc2 = rb_ca_data_class(other);
|
|
513
|
+
if ( ! RTEST(rb_funcall(dc1, id_eql, 1, dc2)) ) {
|
|
514
|
+
return Qfalse;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
511
517
|
}
|
|
512
|
-
|
|
518
|
+
|
|
519
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
520
|
+
TypedData_Get_Struct(other, CArray, &carray_data_type, cb);
|
|
521
|
+
|
|
522
|
+
return ( ca_eql_strict(ca, cb) ) ? Qtrue : Qfalse;
|
|
513
523
|
}
|
|
514
524
|
|
|
515
|
-
|
|
525
|
+
/* ca_hash(ca) — cheap Hash key for CArray. Mixes metadata (data_type,
|
|
526
|
+
* ndim, bytes, elements, scalar-ness, shape, mask presence) and, for
|
|
527
|
+
* unmasked arrays only, samples the leading CA_HASH_SAMPLE_BYTES of
|
|
528
|
+
* data. Masked arrays skip the data sample entirely — otherwise
|
|
529
|
+
* masked positions would have to be zeroed in the sample to preserve
|
|
530
|
+
* the eql?→hash invariant, and masked CArrays are rare as Hash keys.
|
|
531
|
+
* The collision rate cost buys no ca->mask->ptr access and no
|
|
532
|
+
* xmalloc/memcpy per call. */
|
|
533
|
+
|
|
534
|
+
#define CA_HASH_SAMPLE_BYTES 64
|
|
535
|
+
|
|
536
|
+
static st_index_t
|
|
516
537
|
ca_hash (CArray *ca)
|
|
517
538
|
{
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
hash ^= ca_mem_hash(ca->mask->ptr, ca->elements);
|
|
540
|
-
ca_detach(ca);
|
|
541
|
-
free(tptr);
|
|
542
|
-
}
|
|
543
|
-
else {
|
|
539
|
+
st_index_t h;
|
|
540
|
+
int scalar_flag = ca_is_scalar(ca) ? 1 : 0;
|
|
541
|
+
int masked_flag;
|
|
542
|
+
ca_size_t data_len = ca_length(ca);
|
|
543
|
+
ca_size_t sample = (data_len < CA_HASH_SAMPLE_BYTES) ? data_len : CA_HASH_SAMPLE_BYTES;
|
|
544
|
+
|
|
545
|
+
h = rb_memhash(&ca->data_type, sizeof(ca->data_type));
|
|
546
|
+
h ^= rb_memhash(&ca->ndim, sizeof(ca->ndim));
|
|
547
|
+
h ^= rb_memhash(&ca->bytes, sizeof(ca->bytes));
|
|
548
|
+
h ^= rb_memhash(&ca->elements, sizeof(ca->elements));
|
|
549
|
+
h ^= rb_memhash(&scalar_flag, sizeof(scalar_flag));
|
|
550
|
+
if ( ca->ndim > 0 ) {
|
|
551
|
+
h ^= rb_memhash(ca->dim, sizeof(ca_size_t) * ca->ndim);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/* ca_is_any_masked() attaches/detaches the mask internally and returns
|
|
555
|
+
only a boolean, so we never touch ca->mask->ptr here. */
|
|
556
|
+
masked_flag = ca_is_any_masked(ca) ? 1 : 0;
|
|
557
|
+
h ^= rb_memhash(&masked_flag, sizeof(masked_flag));
|
|
558
|
+
|
|
559
|
+
if ( ! masked_flag && sample > 0 ) {
|
|
544
560
|
ca_attach(ca);
|
|
545
|
-
|
|
561
|
+
h ^= rb_memhash(ca->ptr, sample);
|
|
546
562
|
ca_detach(ca);
|
|
547
563
|
}
|
|
548
|
-
return hash;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
/* @overload hash
|
|
552
564
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
*/
|
|
565
|
+
return h;
|
|
566
|
+
}
|
|
556
567
|
|
|
568
|
+
/* CArray#hash — Hash key value; wraps ca_hash into a Ruby Integer. */
|
|
557
569
|
VALUE
|
|
558
570
|
rb_ca_hash (VALUE self)
|
|
559
571
|
{
|
|
560
572
|
CArray *ca;
|
|
561
|
-
|
|
573
|
+
st_index_t hash;
|
|
562
574
|
|
|
563
575
|
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
564
576
|
hash = ca_hash(ca);
|
|
565
|
-
return
|
|
577
|
+
return ST2FIX(hash);
|
|
566
578
|
}
|
|
567
579
|
|
|
568
580
|
/* ----------------------------------------------------------------------- */
|
|
569
581
|
|
|
582
|
+
/* Mutation guard. Rejects both a Ruby-frozen object (FrozenError) and an
|
|
583
|
+
* array carrying CA_FLAG_READ_ONLY, whether set on self or inherited from a
|
|
584
|
+
* read-only parent (RuntimeError). Data-value stores are additionally gated
|
|
585
|
+
* in the xfer PUT path (ca_is_readonly), but mask writes, the `x[i] = UNDEF`
|
|
586
|
+
* masking path, and the direct-ptr entity hot paths in elem_store/incr/decr
|
|
587
|
+
* do not pass through xfer -- mutation entry points guard here so a
|
|
588
|
+
* read-only-flag-only (non-frozen) array is fully protected. */
|
|
570
589
|
void
|
|
571
590
|
rb_ca_modify (VALUE self)
|
|
572
591
|
{
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
rb_raise(rb_eSecurityError, "Insecure: can't modify carray");
|
|
592
|
+
CArray *ca;
|
|
593
|
+
rb_check_frozen(self);
|
|
594
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
595
|
+
if ( ca_is_readonly(ca) ) {
|
|
596
|
+
rb_raise(rb_eRuntimeError, "can not modify read-only array");
|
|
579
597
|
}
|
|
580
|
-
*/
|
|
581
598
|
}
|
|
582
599
|
|
|
583
|
-
/*
|
|
584
|
-
|
|
585
|
-
Freeze the object.
|
|
586
|
-
|
|
587
|
-
*/
|
|
588
|
-
|
|
600
|
+
/* CArray#freeze — freeze self and set CA_FLAG_READ_ONLY so subsequent
|
|
601
|
+
* mutations raise FrozenError. */
|
|
589
602
|
VALUE
|
|
590
603
|
rb_ca_freeze (VALUE self)
|
|
591
604
|
{
|
|
@@ -595,20 +608,121 @@ rb_ca_freeze (VALUE self)
|
|
|
595
608
|
return rb_obj_freeze(self);
|
|
596
609
|
}
|
|
597
610
|
|
|
611
|
+
/* CArray#set_read_only_flag — set CA_FLAG_READ_ONLY so subsequent mutations
|
|
612
|
+
* raise (RuntimeError), WITHOUT rb_obj_freeze. One-way at the public surface:
|
|
613
|
+
* there is no public method to clear the flag, so the read-only guarantee
|
|
614
|
+
* cannot be weakened from user code. Unlike #freeze the Ruby object stays
|
|
615
|
+
* non-frozen, so views / Faces derived from it remain non-frozen and can
|
|
616
|
+
* memoise. A caller wanting a mutable array uses `.copy` (a copy does not
|
|
617
|
+
* inherit the flag). */
|
|
618
|
+
VALUE
|
|
619
|
+
rb_ca_set_read_only_flag (VALUE self)
|
|
620
|
+
{
|
|
621
|
+
CArray *ca;
|
|
622
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
623
|
+
ca_set_flag(ca, CA_FLAG_READ_ONLY);
|
|
624
|
+
return self;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/* Ensure-body arg for rb_ca_without_read_only_flag. */
|
|
628
|
+
struct without_read_only_state {
|
|
629
|
+
CArray *ca;
|
|
630
|
+
int was_readonly;
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
static VALUE
|
|
634
|
+
without_read_only_body (VALUE arg)
|
|
635
|
+
{
|
|
636
|
+
return rb_yield(Qnil);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
static VALUE
|
|
640
|
+
without_read_only_ensure (VALUE arg)
|
|
641
|
+
{
|
|
642
|
+
struct without_read_only_state *s = (struct without_read_only_state *) arg;
|
|
643
|
+
if (s->was_readonly) {
|
|
644
|
+
ca_set_flag(s->ca, CA_FLAG_READ_ONLY);
|
|
645
|
+
}
|
|
646
|
+
return Qnil;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/* CArray#without_read_only_flag { ... } — PRIVATE, block-only escape reserved
|
|
650
|
+
* for library / class authors who understand the READONLY invariants of the
|
|
651
|
+
* subsystem they are working in. The public "One-way" guarantee stated on
|
|
652
|
+
* rb_ca_set_read_only_flag above is NOT weakened by this method: it is not
|
|
653
|
+
* accessible from user code by design (private + explicit `send` requirement
|
|
654
|
+
* is the signal, "I know internal invariants and I am not general user code").
|
|
655
|
+
*
|
|
656
|
+
* READONLY is set for many different reasons across the library, and the
|
|
657
|
+
* semantic behind the flag varies by class:
|
|
658
|
+
*
|
|
659
|
+
* (a) the entity backs external immutable memory (wrap_memory_view over
|
|
660
|
+
* an Arrow / Parquet / mmap MAP_PRIVATE buffer) — the values buffer
|
|
661
|
+
* is truly immutable, but CArray-side metadata (mask slot) is not;
|
|
662
|
+
* a bounded lift for mask attach is safe.
|
|
663
|
+
* (b) writes are permitted only through a formal, invariant-preserving
|
|
664
|
+
* API (a future variant, e.g. classes that keep derived caches in
|
|
665
|
+
* sync on write) — lifting READONLY would enable a low-level bypass
|
|
666
|
+
* of the invariant; DO NOT lift.
|
|
667
|
+
* (c) there is no writable target at all — CAObject today, the planned
|
|
668
|
+
* CASource similarly (elements are produced by a Ruby callback / an
|
|
669
|
+
* upstream source, not stored in a buffer) — lifting READONLY is
|
|
670
|
+
* meaningless because there is nothing to write to.
|
|
671
|
+
*
|
|
672
|
+
* A general lift primitive would be dangerous. The author must know which
|
|
673
|
+
* of (a) / (b) / (c) applies in their subsystem before reaching for this
|
|
674
|
+
* primitive: it exists so a library / class author who does know can perform
|
|
675
|
+
* a bounded escape without inventing a new flag.
|
|
676
|
+
*
|
|
677
|
+
* Canonical use: an interop bridge attaching a validity mask onto the
|
|
678
|
+
* read-only CAWrap returned by wrap_memory_view — the values buffer is
|
|
679
|
+
* immutable (producer's contract) but the mask slot is CArray-side metadata
|
|
680
|
+
* the bridge owns.
|
|
681
|
+
*
|
|
682
|
+
* Mechanics: clears CA_FLAG_READ_ONLY on self for the duration of the block;
|
|
683
|
+
* rb_ensure restores the flag on normal return AND on raise. Frozen objects
|
|
684
|
+
* still raise FrozenError. Self only: does not walk parent chains, does not
|
|
685
|
+
* touch ca->mask's flag.
|
|
686
|
+
*
|
|
687
|
+
* Caller discipline (not enforced by the primitive): confine usage to
|
|
688
|
+
* entities (CArray / CScalar / CAWrap). On a view of a read-only parent,
|
|
689
|
+
* the yielded block's mask= walks create_mask into the parent chain and
|
|
690
|
+
* mutates the parent's mask allocation as a side effect, breaking the
|
|
691
|
+
* view-inherits-readonly guarantee for sibling views of the same parent. */
|
|
692
|
+
VALUE
|
|
693
|
+
rb_ca_without_read_only_flag (VALUE self)
|
|
694
|
+
{
|
|
695
|
+
CArray *ca;
|
|
696
|
+
struct without_read_only_state s;
|
|
697
|
+
rb_check_frozen(self);
|
|
698
|
+
rb_need_block();
|
|
699
|
+
TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
|
|
700
|
+
s.ca = ca;
|
|
701
|
+
s.was_readonly = ca_test_flag(ca, CA_FLAG_READ_ONLY);
|
|
702
|
+
if (s.was_readonly) {
|
|
703
|
+
ca_unset_flag(ca, CA_FLAG_READ_ONLY);
|
|
704
|
+
}
|
|
705
|
+
return rb_ensure(without_read_only_body, Qnil,
|
|
706
|
+
without_read_only_ensure, (VALUE) &s);
|
|
707
|
+
}
|
|
708
|
+
|
|
598
709
|
void
|
|
599
|
-
Init_carray_test ()
|
|
710
|
+
Init_carray_test (void)
|
|
600
711
|
{
|
|
601
712
|
id_equal = rb_intern("==");
|
|
602
|
-
|
|
713
|
+
id_eql = rb_intern("eql?");
|
|
714
|
+
|
|
603
715
|
rb_define_method(rb_cCArray, "valid_index?", rb_ca_is_valid_index, -1);
|
|
604
716
|
rb_define_method(rb_cCArray, "valid_addr?", rb_ca_is_valid_addr, 1);
|
|
605
717
|
rb_define_method(rb_cCArray, "same_shape?", rb_ca_has_same_shape, 1);
|
|
606
718
|
rb_define_method(rb_cCArray, "freeze", rb_ca_freeze, 0);
|
|
719
|
+
rb_define_method(rb_cCArray, "set_read_only_flag", rb_ca_set_read_only_flag, 0);
|
|
720
|
+
rb_define_private_method(rb_cCArray, "without_read_only_flag",
|
|
721
|
+
rb_ca_without_read_only_flag, 0);
|
|
607
722
|
|
|
608
|
-
rb_define_method(rb_cCArray, "==",
|
|
609
|
-
|
|
610
|
-
rb_define_method(rb_cCArray, "hash", rb_ca_hash,
|
|
611
|
-
|
|
612
|
-
rb_define_singleton_method(rb_cCArray, "data_class?", rb_ca_s_is_data_class, 1);
|
|
723
|
+
rb_define_method(rb_cCArray, "==", rb_ca_equal, 1);
|
|
724
|
+
rb_define_method(rb_cCArray, "eql?", rb_ca_eql, 1);
|
|
725
|
+
rb_define_method(rb_cCArray, "hash", rb_ca_hash, 0);
|
|
613
726
|
|
|
727
|
+
/* CArray.data_class?(klass) is bound in Init_ca_obj_record. */
|
|
614
728
|
}
|