carray 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +304 -0
  3. data/README.md +3 -4
  4. data/carray.gemspec +1 -1
  5. data/ext/ca_axis_dispatch.c +225 -0
  6. data/ext/ca_axis_group.c +177 -99
  7. data/ext/ca_binop_dispatch.c +54 -32
  8. data/ext/ca_binop_dispatch.h +1 -0
  9. data/ext/ca_categorical_iterator.c +66 -71
  10. data/ext/ca_compare.c +8 -2
  11. data/ext/ca_for_buffer.h +21 -68
  12. data/ext/ca_group_iter.c +27 -11
  13. data/ext/ca_kernel_iterator.c +663 -214
  14. data/ext/ca_kernel_iterator.h +231 -167
  15. data/ext/ca_monop_dispatch.c +4 -4
  16. data/ext/ca_monop_dispatch.h +4 -0
  17. data/ext/ca_obj_array.c +132 -22
  18. data/ext/ca_obj_bincmp.c +152 -121
  19. data/ext/ca_obj_binop.c +107 -210
  20. data/ext/ca_obj_bitarray.c +37 -24
  21. data/ext/ca_obj_bitfield.c +95 -62
  22. data/ext/ca_obj_block.c +1 -0
  23. data/ext/ca_obj_byte_swap.c +40 -40
  24. data/ext/ca_obj_const_string.c +96 -25
  25. data/ext/ca_obj_face.c +406 -64
  26. data/ext/ca_obj_face.h +92 -47
  27. data/ext/ca_obj_fake.c +21 -50
  28. data/ext/ca_obj_farray.c +1 -0
  29. data/ext/ca_obj_field.c +16 -3
  30. data/ext/ca_obj_fixlen_string.c +21 -21
  31. data/ext/ca_obj_grid.c +181 -124
  32. data/ext/ca_obj_meld.c +189 -107
  33. data/ext/ca_obj_moncmp.c +61 -61
  34. data/ext/ca_obj_monop.c +125 -107
  35. data/ext/ca_obj_object.c +543 -233
  36. data/ext/ca_obj_record.c +51 -16
  37. data/ext/ca_obj_reduce.c +5 -8
  38. data/ext/ca_obj_refer.c +117 -33
  39. data/ext/ca_obj_remap.c +57 -17
  40. data/ext/ca_obj_repeat.c +21 -5
  41. data/ext/ca_obj_roll.c +115 -11
  42. data/ext/ca_obj_select.c +47 -49
  43. data/ext/ca_obj_select_axis.c +58 -60
  44. data/ext/ca_obj_shift.c +22 -102
  45. data/ext/ca_obj_stack.c +223 -118
  46. data/ext/ca_obj_stride.c +195 -34
  47. data/ext/ca_obj_string.c +17 -18
  48. data/ext/ca_obj_tile.c +32 -16
  49. data/ext/ca_obj_time.c +23 -25
  50. data/ext/ca_obj_timedelta.c +21 -23
  51. data/ext/ca_obj_transpose.c +12 -3
  52. data/ext/ca_obj_triop.c +110 -117
  53. data/ext/ca_obj_window.c +149 -27
  54. data/ext/ca_op_ipower.c +24 -11
  55. data/ext/ca_op_powi.h +57 -30
  56. data/ext/ca_pow5_table.h +656 -0
  57. data/ext/ca_sort_kernels.h +70 -0
  58. data/ext/ca_sweep_engine.c +102 -79
  59. data/ext/ca_sweep_engine.h +7 -20
  60. data/ext/ca_triop_dispatch.c +4 -1
  61. data/ext/ca_triop_dispatch.h +5 -2
  62. data/ext/caframe_csv_reader.c +463 -0
  63. data/ext/carray.h +70 -27
  64. data/ext/carray_access.c +455 -211
  65. data/ext/carray_address_basis.c +177 -36
  66. data/ext/carray_attribute.c +45 -3
  67. data/ext/carray_bincount.c +32 -2
  68. data/ext/carray_broadcast.c +46 -14
  69. data/ext/carray_call_cfunc.c +0 -28
  70. data/ext/carray_cast.c +1444 -209
  71. data/ext/carray_cast_func.rb +34 -21
  72. data/ext/carray_conversion.c +197 -73
  73. data/ext/carray_copy.c +32 -11
  74. data/ext/carray_core.c +514 -122
  75. data/ext/carray_count.c +140 -87
  76. data/ext/carray_element.c +18 -27
  77. data/ext/carray_factorize.c +569 -277
  78. data/ext/carray_generate.c +76 -40
  79. data/ext/carray_histogram.c +152 -94
  80. data/ext/carray_hold.c +2 -1
  81. data/ext/carray_index_classifier.c +63 -96
  82. data/ext/carray_internal.h +385 -3
  83. data/ext/carray_lazy.c +834 -79
  84. data/ext/carray_loop.c +81 -65
  85. data/ext/carray_mask.c +682 -316
  86. data/ext/carray_math_kernel.h +1 -0
  87. data/ext/carray_median_percentile.c +221 -76
  88. data/ext/carray_memory_view.c +254 -248
  89. data/ext/carray_operator.c +1089 -359
  90. data/ext/carray_order.c +133 -69
  91. data/ext/carray_partition.c +102 -56
  92. data/ext/carray_random.c +273 -239
  93. data/ext/carray_scatter.c +308 -65
  94. data/ext/carray_segment.c +257 -0
  95. data/ext/carray_slab.c +170 -70
  96. data/ext/carray_sort.c +215 -218
  97. data/ext/carray_sort_kernel.c +8 -1
  98. data/ext/carray_struct.c +99 -21
  99. data/ext/carray_test.c +167 -64
  100. data/ext/carray_time_text.c +1182 -0
  101. data/ext/carray_utils.c +363 -98
  102. data/ext/extconf.rb +27 -2
  103. data/ext/mk_call_cfunc.rb +0 -2
  104. data/ext/mk_pow5_table.rb +35 -0
  105. data/ext/mkkernel.rb +1076 -846
  106. data/ext/ruby_carray.c +7 -1
  107. data/ext/version.h +4 -4
  108. data/ext/version.rb +4 -2
  109. data/lib/carray/attribute.rb +39 -0
  110. data/lib/carray/autoload_carray.rb +19 -0
  111. data/lib/carray/autoload_method_extension.rb +6 -0
  112. data/lib/carray/axis_group.rb +174 -26
  113. data/lib/carray/basics.rb +91 -25
  114. data/lib/carray/bincount_nd.rb +6 -0
  115. data/lib/carray/block_iterator.rb +118 -48
  116. data/lib/carray/boolean_reduce.rb +21 -29
  117. data/lib/carray/categorical.rb +94 -26
  118. data/lib/carray/categorical_iterator.rb +333 -826
  119. data/lib/carray/complex.rb +36 -29
  120. data/lib/carray/conditional.rb +94 -7
  121. data/lib/carray/const_string.rb +46 -0
  122. data/lib/carray/frame/concat.rb +157 -6
  123. data/lib/carray/frame/convert.rb +13 -7
  124. data/lib/carray/frame/csv_parser.rb +589 -82
  125. data/lib/carray/frame/describe.rb +79 -0
  126. data/lib/carray/frame/frame.rb +124 -25
  127. data/lib/carray/frame/group.rb +189 -63
  128. data/lib/carray/frame/io.rb +412 -72
  129. data/lib/carray/frame/join.rb +134 -46
  130. data/lib/carray/frame/records.rb +37 -16
  131. data/lib/carray/frame/reshape.rb +448 -0
  132. data/lib/carray/frame/sort.rb +26 -2
  133. data/lib/carray/frame/verbs.rb +715 -48
  134. data/lib/carray/frame.rb +2 -0
  135. data/lib/carray/fuse_source.rb +111 -2
  136. data/lib/carray/fusion.rb +229 -38
  137. data/lib/carray/inspect.rb +29 -11
  138. data/lib/carray/iterator.rb +14 -2
  139. data/lib/carray/lazy.rb +54 -30
  140. data/lib/carray/mask_gap_fill.rb +66 -52
  141. data/lib/carray/math.rb +32 -19
  142. data/lib/carray/meld_reduce.rb +40 -7
  143. data/lib/carray/methods/align_addr.rb +8 -4
  144. data/lib/carray/methods/bincount.rb +2 -2
  145. data/lib/carray/methods/bit_string.rb +14 -3
  146. data/lib/carray/methods/composition.rb +16 -10
  147. data/lib/carray/methods/factorize.rb +2 -2
  148. data/lib/carray/methods/gather_nd.rb +13 -2
  149. data/lib/carray/methods/insert_block.rb +9 -14
  150. data/lib/carray/methods/is_in.rb +117 -4
  151. data/lib/carray/methods/join.rb +1 -1
  152. data/lib/carray/methods/locate_addr.rb +177 -36
  153. data/lib/carray/methods/mode.rb +18 -1
  154. data/lib/carray/methods/repeat.rb +1 -20
  155. data/lib/carray/methods/resize.rb +21 -23
  156. data/lib/carray/methods/snap.rb +34 -12
  157. data/lib/carray/methods/unique.rb +11 -2
  158. data/lib/carray/record_order.rb +208 -0
  159. data/lib/carray/runtime.rb +14 -11
  160. data/lib/carray/segment_iterator.rb +990 -0
  161. data/lib/carray/serialize.rb +197 -27
  162. data/lib/carray/slab_iterator.rb +51 -27
  163. data/lib/carray/stack.rb +10 -4
  164. data/lib/carray/string_operation_extension.rb +4 -3
  165. data/lib/carray/struct.rb +142 -51
  166. data/lib/carray/struct_builder.rb +110 -14
  167. data/lib/carray/table.rb +2 -2
  168. data/lib/carray/time.rb +517 -103
  169. data/lib/carray/window_iterator.rb +127 -72
  170. data/lib/carray.rb +2 -2
  171. data/yard-stubs/ca_obj_array.rb +4 -4
  172. data/yard-stubs/ca_obj_bitarray.rb +7 -0
  173. data/yard-stubs/ca_obj_bitfield.rb +23 -12
  174. data/yard-stubs/ca_obj_fake.rb +1 -1
  175. data/yard-stubs/ca_obj_field.rb +1 -1
  176. data/yard-stubs/ca_obj_refer.rb +3 -3
  177. data/yard-stubs/ca_obj_roll.rb +0 -1
  178. data/yard-stubs/ca_obj_stride.rb +10 -7
  179. data/yard-stubs/ca_obj_transpose.rb +1 -1
  180. data/yard-stubs/ca_obj_window.rb +1 -2
  181. data/yard-stubs/carray_access.rb +5 -4
  182. data/yard-stubs/carray_broadcast.rb +1 -1
  183. data/yard-stubs/carray_cast.rb +78 -43
  184. data/yard-stubs/carray_conversion.rb +13 -1
  185. data/yard-stubs/carray_copy.rb +8 -3
  186. data/yard-stubs/carray_core.rb +3 -3
  187. data/yard-stubs/carray_count.rb +9 -0
  188. data/yard-stubs/carray_lazy.rb +5 -1
  189. data/yard-stubs/carray_loop.rb +4 -1
  190. data/yard-stubs/carray_mask.rb +34 -10
  191. data/yard-stubs/carray_math.rb +25 -13
  192. data/yard-stubs/carray_median_percentile.rb +10 -6
  193. data/yard-stubs/carray_order.rb +34 -13
  194. data/yard-stubs/carray_scatter.rb +10 -3
  195. data/yard-stubs/carray_segment.rb +72 -0
  196. data/yard-stubs/carray_slab.rb +2 -1
  197. data/yard-stubs/carray_sort.rb +43 -3
  198. data/yard-stubs/carray_test.rb +10 -0
  199. data/yard-stubs/carray_utils.rb +0 -26
  200. metadata +11 -19
  201. data/ext/ca_for_each_element.h +0 -239
  202. data/ext/carray_build_flags.h +0 -3
  203. data/ext/carray_config.h +0 -28
  204. data/ext/carray_kernels_bincmp.c +0 -4446
  205. data/ext/carray_kernels_binop.c +0 -11001
  206. data/ext/carray_kernels_init.c +0 -1131
  207. data/ext/carray_kernels_map.c +0 -3467
  208. data/ext/carray_kernels_moncmp.c +0 -2097
  209. data/ext/carray_kernels_monop.c +0 -18313
  210. data/ext/carray_kernels_reduce_aggregate.c +0 -26005
  211. data/ext/carray_kernels_reduce_boolean.c +0 -330
  212. data/ext/carray_kernels_reduce_cumulative.c +0 -14862
  213. data/ext/carray_kernels_reduce_extreme.c +0 -17494
  214. data/ext/carray_kernels_reduce_variance.c +0 -3910
  215. data/ext/carray_kernels_scan.c +0 -3693
  216. data/ext/carray_kernels_search.c +0 -32218
  217. data/ext/carray_kernels_sort.c +0 -10626
  218. data/ext/carray_kernels_triop.c +0 -1392
@@ -117,11 +117,11 @@ ca_monop_kernel_lookup (uint16_t op_id, int8_t in_data_type)
117
117
  /* op category predicates */
118
118
  /* ------------------------------------------------------------------- */
119
119
 
120
- /* True if op widens integer / boolean parent to CA_FLOAT64. False for
120
+ /* True if op widens an integer parent to CA_FLOAT64. False for
121
121
  preserve ops and cast ops. Widening ops are enumerated explicitly
122
122
  because they were added in multiple groups outside the original
123
123
  contiguous WIDENING_BEGIN..WIDENING_END range. */
124
- static int
124
+ int
125
125
  ca_monop_is_widening (uint16_t op_id)
126
126
  {
127
127
  if ( op_id >= CA_MONOP_WIDENING_BEGIN && op_id < CA_MONOP_WIDENING_END ) {
@@ -170,8 +170,8 @@ ca_lazy_promote_monop (uint16_t op_id, int8_t in_data_type)
170
170
  return (int8_t)(op_id - CA_MONOP_CAST_BASE);
171
171
  }
172
172
  if ( ca_monop_is_widening(op_id) ) {
173
- /* integer → f64, else preserve. Boolean (CA_BOOLEAN = 1) is also
174
- widened to f64 (existing eager behaviour via wrap_readonly). */
173
+ /* integer → f64, else preserve. A boolean parent never reaches a
174
+ widening op: the builder refuses it, as the eager monop does. */
175
175
  if ( in_data_type < CA_FLOAT32 ) return CA_FLOAT64;
176
176
  return in_data_type;
177
177
  }
@@ -194,6 +194,10 @@ ca_monop_func_t ca_monop_kernel_lookup (uint16_t op_id, int8_t in_data_type);
194
194
  /* Returns true iff op_id encodes a cast operation. */
195
195
  int ca_monop_is_cast (uint16_t op_id);
196
196
 
197
+ /* Returns true iff op_id widens an integer parent to CA_FLOAT64 (the
198
+ math functions: sqrt, sin, exp, ...). */
199
+ int ca_monop_is_widening (uint16_t op_id);
200
+
197
201
  /* Phase 6 P.6.3: returns true iff op_id is a "writable view" op
198
202
  (= cast or byte_swap). These ops:
199
203
  - support writable view lifecycle (CA_FLAG_READ_ONLY not set)
data/ext/ca_obj_array.c CHANGED
@@ -9,6 +9,7 @@
9
9
  ---------------------------------------------------------------------------- */
10
10
 
11
11
  #include "carray.h"
12
+ #include "carray_internal.h"
12
13
 
13
14
  /* -------------------------------------------------------------------- */
14
15
 
@@ -137,7 +138,6 @@ carray_setup_i (CArray *ca,
137
138
  CArray *mask, int allocate, int use_calloc, char *adopt_ptr)
138
139
  {
139
140
  ca_size_t elements;
140
- double length;
141
141
  int8_t i;
142
142
  ca_size_t k;
143
143
 
@@ -147,21 +147,7 @@ carray_setup_i (CArray *ca,
147
147
  CA_CHECK_DIM(ndim, dim);
148
148
  CA_CHECK_BYTES(data_type, bytes);
149
149
 
150
- /* calculate total byte length using double to detect overflow */
151
- length = bytes;
152
- for (i=0; i<ndim; i++) {
153
- length *= dim[i];
154
- }
155
-
156
- if ( length > CA_LENGTH_MAX ) {
157
- rb_raise(rb_eRuntimeError, "too large byte length");
158
- }
159
-
160
- /* calculate total number of elements (safe after length check above) */
161
- elements = 1;
162
- for (i=0; i<ndim; i++) {
163
- elements *= dim[i];
164
- }
150
+ elements = ca_shape_elements(ndim, dim, bytes);
165
151
 
166
152
  /* An adopted buffer produces an owning entity (CA_OBJ_ARRAY), not a
167
153
  wrap: free_carray xfree()s ca->ptr, so the caller's buffer must be
@@ -173,6 +159,12 @@ carray_setup_i (CArray *ca,
173
159
  "cannot adopt a raw buffer as a CA_OBJECT array");
174
160
  }
175
161
 
162
+ /* ca == NULL asks for the checks above only, so that a constructor can
163
+ run them before it allocates. */
164
+ if ( ca == NULL ) {
165
+ return 0;
166
+ }
167
+
176
168
  /* set values to the struct members */
177
169
  if ( allocate || adopt_ptr ) {
178
170
  ca->obj_type = CA_OBJ_ARRAY;
@@ -274,7 +266,9 @@ CArray *
274
266
  carray_new (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
275
267
  CArray *mask)
276
268
  {
277
- CArray *ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
269
+ CArray *ca;
270
+ carray_setup(NULL, data_type, ndim, dim, bytes, mask);
271
+ ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
278
272
  carray_setup(ca, data_type, ndim, dim, bytes, mask);
279
273
  return ca;
280
274
  }
@@ -283,7 +277,9 @@ CArray *
283
277
  carray_new_safe (int8_t data_type, int8_t ndim, ca_size_t *dim, ca_size_t bytes,
284
278
  CArray *mask)
285
279
  {
286
- CArray *ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
280
+ CArray *ca;
281
+ carray_safe_setup(NULL, data_type, ndim, dim, bytes, mask);
282
+ ca = (CArray *) ca_array_alloc(CA_OBJ_ARRAY, ndim);
287
283
  carray_safe_setup(ca, data_type, ndim, dim, bytes, mask);
288
284
  return ca;
289
285
  }
@@ -583,6 +579,8 @@ ca_fill_stride_buffer (char *dst, ca_size_t bytes, ca_size_t base, int8_t ndim,
583
579
  ca_size_t inner_count, inner_step;
584
580
  int8_t outer_ndim, k;
585
581
 
582
+ if ( ca_region_is_empty(ndim, counts) ) return;
583
+
586
584
  if ( ndim <= 0 ) {
587
585
  memcpy(dst + base * bytes, ptr, bytes);
588
586
  return;
@@ -857,6 +855,7 @@ ca_scan_construct_args (int argc, VALUE *argv, int8_t *data_type,
857
855
  rb_ca_guess_type_and_bytes(rtype, rbytes, data_type, bytes);
858
856
 
859
857
  Check_Type(rdim, T_ARRAY);
858
+ CA_CHECK_RANK(RARRAY_LEN(rdim)); /* before dim[] is filled */
860
859
  *ndim = RARRAY_LEN(rdim);
861
860
  for (i=0; i<*ndim; i++) {
862
861
  dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
@@ -886,6 +885,10 @@ rb_ca_initialize (int argc, VALUE *argv, VALUE self)
886
885
  ca_scan_construct_args(argc, argv, &data_type, &bytes, &ndim, dim);
887
886
 
888
887
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
888
+ ca_check_uninitialized(ca);
889
+ /* Checks first: a rejected argument leaves the struct as allocated, so
890
+ it takes no pool and can be initialized again. */
891
+ carray_safe_setup(NULL, data_type, ndim, dim, bytes, NULL);
889
892
  if ( ca_func[CA_OBJ_ARRAY].pool_init ) {
890
893
  ca_array_pool_alloc(ca, CA_OBJ_ARRAY, ndim);
891
894
  }
@@ -912,10 +915,7 @@ rb_ca_initialize (int argc, VALUE *argv, VALUE self)
912
915
  else if ( ca->ndim > 0 ) {
913
916
  ca_size_t idx[CA_RANK_MAX];
914
917
  volatile VALUE ridx = rb_ary_new2(ca->ndim);
915
- ca_attach(ca);
916
918
  rb_ca_index_walk(self, ca, 0, idx, ridx, CA_LOOP_STORE);
917
- ca_sync(ca);
918
- ca_detach(ca);
919
919
  }
920
920
  else {
921
921
  /* 0-D safety net (rare from CArray.new path): yield no args. */
@@ -1109,6 +1109,7 @@ rb_ca_initialize_copy (VALUE self, VALUE other)
1109
1109
  rb_call_super(1, &other);
1110
1110
 
1111
1111
  TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
1112
+ ca_check_uninitialized(ca);
1112
1113
  TypedData_Get_Struct(other, CArray, &carray_data_type, cs);
1113
1114
 
1114
1115
  ca_update_mask(cs);
@@ -1117,11 +1118,112 @@ rb_ca_initialize_copy (VALUE self, VALUE other)
1117
1118
  }
1118
1119
  carray_setup(ca, cs->data_type, cs->ndim, cs->dim, cs->bytes, cs->mask);
1119
1120
 
1120
- memcpy(ca->ptr, cs->ptr, ca_length(cs));
1121
+ if ( cs->ptr ) {
1122
+ memcpy(ca->ptr, cs->ptr, ca_length(cs));
1123
+ }
1124
+ else {
1125
+ /* An entity cold at rest (a CAObject's mask, a source) is read
1126
+ through its slots. */
1127
+ ca_copy_data(cs, ca->ptr);
1128
+ }
1129
+
1130
+ return self;
1131
+ }
1132
+
1133
+ /* dup and clone go through here before each class's initialize_copy. A
1134
+ view's copy is another view onto the same parent (Ruby's shallow copy),
1135
+ rebuilt by that class from the parent, so what the original was told
1136
+ about itself -- that it is a value array, read-only, a mask -- has to be
1137
+ carried across here, once for every class. An entity's copy owns new
1138
+ memory, so it is not a value array and its writability is its own, but
1139
+ a copy of a mask is still a mask (its class, CArrayMask, says so) and
1140
+ can no more hold a mask of its own than the original. */
1141
+ static void
1142
+ ca_dup_keep_state (VALUE self, VALUE other)
1143
+ {
1144
+ CArray *ca, *cs;
1145
+ if ( ! rb_obj_is_kind_of(other, rb_cCArray) ) {
1146
+ return;
1147
+ }
1148
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
1149
+ TypedData_Get_Struct(other, CArray, &carray_data_type, cs);
1150
+ if ( ca_is_view(cs) ) {
1151
+ ca_keep_chain_flags(ca, cs);
1152
+ }
1153
+ else if ( ca_is_mask_array(cs) ) {
1154
+ ca_set_flag(ca, CA_FLAG_MASK_ARRAY);
1155
+ }
1156
+ }
1157
+
1158
+ static VALUE
1159
+ rb_ca_initialize_dup (VALUE self, VALUE other)
1160
+ {
1161
+ rb_call_super(1, &other);
1162
+ ca_dup_keep_state(self, other);
1163
+ return self;
1164
+ }
1165
+
1166
+ /* clone freezes its result without calling #freeze, so the read-only flag
1167
+ that CArray#freeze sets would be missing: the copy refuses writes as
1168
+ frozen but answers read_only? false. Set it here when the result is
1169
+ going to be frozen (freeze: true, or freeze: omitted and the original
1170
+ frozen). */
1171
+ static VALUE
1172
+ rb_ca_initialize_clone (int argc, VALUE *argv, VALUE self)
1173
+ {
1174
+ VALUE orig, opts, vfreeze = Qnil;
1175
+ int will_freeze;
1176
+
1177
+ rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
1178
+ rb_scan_args(argc, argv, "1:", &orig, &opts);
1179
+ ca_dup_keep_state(self, orig);
1121
1180
 
1181
+ if ( ! NIL_P(opts) ) {
1182
+ vfreeze = rb_hash_lookup2(opts, ID2SYM(rb_intern("freeze")), Qnil);
1183
+ }
1184
+ will_freeze = NIL_P(vfreeze) ? OBJ_FROZEN(orig) : RTEST(vfreeze);
1185
+ if ( will_freeze ) {
1186
+ CArray *ca;
1187
+ TypedData_Get_Struct(self, CArray, &carray_data_type, ca);
1188
+ ca_set_flag(ca, CA_FLAG_READ_ONLY);
1189
+ }
1122
1190
  return self;
1123
1191
  }
1124
1192
 
1193
+ /* A wrap borrows memory it does not own. Object#dup would give the copy
1194
+ the wrap's class over memory the copy owns, so a subclass that names what
1195
+ it borrows (a libvips image's pixels) would name an array that borrows
1196
+ nothing. The copy is a plain CArray, as #copy is: the name goes with
1197
+ what is borrowed. */
1198
+ static VALUE
1199
+ rb_ca_wrap_dup (VALUE self)
1200
+ {
1201
+ return rb_ca_copy(self);
1202
+ }
1203
+
1204
+ static VALUE
1205
+ rb_ca_wrap_clone (int argc, VALUE *argv, VALUE self)
1206
+ {
1207
+ VALUE opt = Qnil, rfreeze = Qnil;
1208
+ volatile VALUE obj;
1209
+ rb_scan_args(argc, argv, "0:", &opt);
1210
+ if ( ! NIL_P(opt) ) {
1211
+ /* rb_get_kwargs refuses any key but freeze:, as Kernel#clone does. */
1212
+ ID kw[1];
1213
+ VALUE val[1];
1214
+ kw[0] = rb_intern("freeze");
1215
+ rb_get_kwargs(opt, kw, 0, 1, val);
1216
+ if ( val[0] != Qundef ) {
1217
+ rfreeze = val[0];
1218
+ }
1219
+ }
1220
+ obj = rb_ca_copy(self);
1221
+ if ( RTEST(rfreeze) || ( NIL_P(rfreeze) && OBJ_FROZEN(self) ) ) {
1222
+ rb_obj_freeze(obj);
1223
+ }
1224
+ return obj;
1225
+ }
1226
+
1125
1227
  /* @overload wrap (data_type, dim, bytes=0) { target }
1126
1228
 
1127
1229
  [TBD] (Construction)
@@ -1144,6 +1246,7 @@ rb_ca_s_wrap (int argc, VALUE *argv, VALUE self)
1144
1246
  rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
1145
1247
 
1146
1248
  Check_Type(rdim, T_ARRAY);
1249
+ CA_CHECK_RANK(RARRAY_LEN(rdim)); /* before dim[] is filled */
1147
1250
  ndim = RARRAY_LEN(rdim);
1148
1251
  for (i=0; i<ndim; i++) {
1149
1252
  dim[i] = NUM2SIZE(rb_ary_entry(rdim, i));
@@ -1212,6 +1315,7 @@ rb_cs_initialize (int argc, VALUE *argv, VALUE self)
1212
1315
  rb_ca_guess_type_and_bytes(rtype, rbytes, &data_type, &bytes);
1213
1316
 
1214
1317
  TypedData_Get_Struct(self, CScalar, &cscalar_data_type, ca);
1318
+ ca_check_uninitialized(ca);
1215
1319
  cscalar_setup(ca, data_type, bytes, NULL);
1216
1320
 
1217
1321
  if ( rb_block_given_p() ) {
@@ -1405,6 +1509,7 @@ rb_cs_initialize_copy (VALUE self, VALUE other)
1405
1509
  CScalar *ca, *cs;
1406
1510
 
1407
1511
  TypedData_Get_Struct(self, CScalar, &cscalar_data_type, ca);
1512
+ ca_check_uninitialized(ca);
1408
1513
  TypedData_Get_Struct(other, CScalar, &cscalar_data_type, cs);
1409
1514
 
1410
1515
  cscalar_setup(ca, cs->data_type, cs->bytes, NULL);
@@ -1447,6 +1552,7 @@ rb_ca_s_alloc_uninit (VALUE klass, VALUE rtype, VALUE rshape)
1447
1552
  int8_t i;
1448
1553
  rb_ca_guess_type_and_bytes(rtype, Qnil, &data_type, &bytes);
1449
1554
  Check_Type(rshape, T_ARRAY);
1555
+ CA_CHECK_RANK(RARRAY_LEN(rshape)); /* before dim[] is filled */
1450
1556
  ndim = (int8_t) RARRAY_LEN(rshape);
1451
1557
  for (i = 0; i < ndim; i++) dim[i] = NUM2SIZE(rb_ary_entry(rshape, i));
1452
1558
  return rb_carray_new(data_type, ndim, dim, bytes, NULL);
@@ -1521,6 +1627,10 @@ Init_ca_obj_array (void)
1521
1627
  #endif
1522
1628
 
1523
1629
  rb_define_method(rb_cCArray, "initialize_copy", rb_ca_initialize_copy, 1);
1630
+ rb_define_method(rb_cCArray, "initialize_dup", rb_ca_initialize_dup, 1);
1631
+ rb_define_method(rb_cCArray, "initialize_clone", rb_ca_initialize_clone, -1);
1632
+ rb_define_method(rb_cCAWrap, "dup", rb_ca_wrap_dup, 0);
1633
+ rb_define_method(rb_cCAWrap, "clone", rb_ca_wrap_clone, -1);
1524
1634
  rb_define_singleton_method(rb_cCArray, "wrap", rb_ca_s_wrap, -1);
1525
1635
 
1526
1636
  /* ------------------------------------------------------------------- */