carray 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +56 -0
  3. data/GPL +340 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +33 -0
  6. data/LEGAL +50 -0
  7. data/NOTE +73 -0
  8. data/Rakefile +20 -0
  9. data/TODO +5 -0
  10. data/ca_iter_block.c +242 -0
  11. data/ca_iter_dimension.c +287 -0
  12. data/ca_iter_window.c +202 -0
  13. data/ca_obj_array.c +1189 -0
  14. data/ca_obj_bitarray.c +523 -0
  15. data/ca_obj_bitfield.c +636 -0
  16. data/ca_obj_block.c +885 -0
  17. data/ca_obj_fake.c +405 -0
  18. data/ca_obj_farray.c +482 -0
  19. data/ca_obj_field.c +625 -0
  20. data/ca_obj_grid.c +738 -0
  21. data/ca_obj_mapping.c +614 -0
  22. data/ca_obj_object.c +777 -0
  23. data/ca_obj_reduce.c +299 -0
  24. data/ca_obj_refer.c +627 -0
  25. data/ca_obj_repeat.c +640 -0
  26. data/ca_obj_select.c +558 -0
  27. data/ca_obj_shift.c +952 -0
  28. data/ca_obj_transpose.c +582 -0
  29. data/ca_obj_unbound_repeat.c +557 -0
  30. data/ca_obj_window.c +1023 -0
  31. data/carray.h +1381 -0
  32. data/carray_access.c +1798 -0
  33. data/carray_attribute.c +903 -0
  34. data/carray_call_cfunc.c +1107 -0
  35. data/carray_cast.c +1155 -0
  36. data/carray_cast_func.rb +498 -0
  37. data/carray_class.c +132 -0
  38. data/carray_conversion.c +518 -0
  39. data/carray_copy.c +453 -0
  40. data/carray_core.c +1307 -0
  41. data/carray_element.c +572 -0
  42. data/carray_generate.c +681 -0
  43. data/carray_iterator.c +630 -0
  44. data/carray_loop.c +462 -0
  45. data/carray_mask.c +1174 -0
  46. data/carray_math.rb +834 -0
  47. data/carray_numeric.c +257 -0
  48. data/carray_operator.c +582 -0
  49. data/carray_order.c +1040 -0
  50. data/carray_random.c +529 -0
  51. data/carray_sort_addr.c +261 -0
  52. data/carray_stat.c +2102 -0
  53. data/carray_stat_proc.rb +1990 -0
  54. data/carray_test.c +602 -0
  55. data/carray_undef.c +69 -0
  56. data/carray_utils.c +740 -0
  57. data/ext/calculus/carray_calculus.c +792 -0
  58. data/ext/calculus/carray_interp.c +355 -0
  59. data/ext/calculus/extconf.rb +12 -0
  60. data/ext/calculus/lib/autoload/autoload_math_calculus.rb +2 -0
  61. data/ext/calculus/lib/math/calculus.rb +119 -0
  62. data/ext/calculus/lib/math/interp/adapter_interp1d.rb +31 -0
  63. data/ext/dataframe/API.txt +11 -0
  64. data/ext/dataframe/extconf.rb +3 -0
  65. data/ext/dataframe/lib/carray/autoload/autoload_dataframe_dataframe.rb +14 -0
  66. data/ext/dataframe/lib/carray/dataframe/dataframe.rb +1104 -0
  67. data/ext/dataframe/sample/test_uniq_sort.rb +5 -0
  68. data/ext/fortio/extconf.rb +3 -0
  69. data/ext/fortio/lib/carray/autoload/autoload_fortran_format.rb +5 -0
  70. data/ext/fortio/lib/carray/io/fortran_format.rb +43 -0
  71. data/ext/fortio/lib/fortio.rb +3 -0
  72. data/ext/fortio/lib/fortio/fortran_format.rb +603 -0
  73. data/ext/fortio/lib/fortio/fortran_format.tab.rb +536 -0
  74. data/ext/fortio/lib/fortio/fortran_format.y +215 -0
  75. data/ext/fortio/lib/fortio/fortran_namelist.rb +151 -0
  76. data/ext/fortio/lib/fortio/fortran_namelist.tab.rb +470 -0
  77. data/ext/fortio/lib/fortio/fortran_namelist.y +213 -0
  78. data/ext/fortio/lib/fortio/fortran_sequential.rb +345 -0
  79. data/ext/fortio/ruby_fortio.c +182 -0
  80. data/ext/fortio/test/test_H.rb +5 -0
  81. data/ext/fortio/test/test_T.rb +7 -0
  82. data/ext/fortio/test/test_fortran_format.rb +86 -0
  83. data/ext/fortio/test/test_namelist.rb +25 -0
  84. data/ext/fortio/test/test_sequential.rb +13 -0
  85. data/ext/fortio/test/test_sequential2.rb +13 -0
  86. data/ext/fortio/work/test.rb +10 -0
  87. data/ext/fortio/work/test_e.rb +19 -0
  88. data/ext/fortio/work/test_ep.rb +10 -0
  89. data/ext/fortio/work/test_parse.rb +12 -0
  90. data/ext/imagemap/carray_imagemap.c +495 -0
  91. data/ext/imagemap/doc/call_graph.dot +28 -0
  92. data/ext/imagemap/draw.c +567 -0
  93. data/ext/imagemap/extconf.rb +13 -0
  94. data/ext/imagemap/lib/autoload/autoload_graphics_imagemap.rb +1 -0
  95. data/ext/imagemap/lib/graphics/imagemap.rb +273 -0
  96. data/ext/imagemap/lib/image_map.rb +4 -0
  97. data/ext/imagemap/test/swath_index.rb +83 -0
  98. data/ext/imagemap/test/swath_warp.rb +99 -0
  99. data/ext/imagemap/test/test.rb +23 -0
  100. data/ext/imagemap/test/test_image.rb +42 -0
  101. data/ext/imagemap/test/test_line.rb +14 -0
  102. data/ext/imagemap/test/test_rotate.rb +17 -0
  103. data/ext/imagemap/test/test_triangle.rb +20 -0
  104. data/ext/imagemap/test/test_warp.rb +26 -0
  105. data/ext/mathfunc/carray_mathfunc.c +321 -0
  106. data/ext/mathfunc/extconf.rb +18 -0
  107. data/ext/mathfunc/lib/autoload/autoload_math_mathfunc.rb +1 -0
  108. data/ext/mathfunc/lib/math/mathfunc.rb +15 -0
  109. data/ext/mathfunc/test/test_hypot.rb +5 -0
  110. data/ext/mathfunc/test/test_j0.rb +22 -0
  111. data/ext/mathfunc/test/test_jn.rb +8 -0
  112. data/ext/mathfunc/test/test_sph.rb +9 -0
  113. data/ext/narray/README +22 -0
  114. data/ext/narray/ca_wrap_narray.c +491 -0
  115. data/ext/narray/carray_narray.c +21 -0
  116. data/ext/narray/extconf.rb +57 -0
  117. data/ext/narray/lib/autoload/autoload_math_narray.rb +1 -0
  118. data/ext/narray/lib/autoload/autoload_math_narray_miss.rb +11 -0
  119. data/ext/narray/lib/math/narray.rb +17 -0
  120. data/ext/narray/lib/math/narray_miss.rb +45 -0
  121. data/extconf.rb +3 -25
  122. data/lib/carray.rb +28 -0
  123. data/lib/carray/autoload/autoload_base.rb +23 -0
  124. data/lib/carray/autoload/autoload_graphics_gnuplot.rb +2 -0
  125. data/lib/carray/autoload/autoload_io_csv.rb +14 -0
  126. data/lib/carray/autoload/autoload_io_excel.rb +5 -0
  127. data/lib/carray/autoload/autoload_io_imagemagick.rb +6 -0
  128. data/lib/carray/autoload/autoload_io_pg.rb +6 -0
  129. data/lib/carray/autoload/autoload_io_sqlite3.rb +12 -0
  130. data/lib/carray/autoload/autoload_io_table.rb +1 -0
  131. data/lib/carray/autoload/autoload_math_histogram.rb +5 -0
  132. data/lib/carray/autoload/autoload_math_interp.rb +4 -0
  133. data/lib/carray/autoload/autoload_math_recurrence.rb +6 -0
  134. data/lib/carray/autoload/autoload_object_iterator.rb +1 -0
  135. data/lib/carray/autoload/autoload_object_link.rb +1 -0
  136. data/lib/carray/autoload/autoload_object_pack.rb +2 -0
  137. data/lib/carray/base/autoload.rb +94 -0
  138. data/lib/carray/base/basic.rb +1051 -0
  139. data/lib/carray/base/inspect.rb +252 -0
  140. data/lib/carray/base/iterator.rb +367 -0
  141. data/lib/carray/base/math.rb +403 -0
  142. data/lib/carray/base/obsolete.rb +93 -0
  143. data/lib/carray/base/serialize.rb +260 -0
  144. data/lib/carray/base/struct.rb +634 -0
  145. data/lib/carray/graphics/gnuplot.rb +2116 -0
  146. data/lib/carray/info.rb +112 -0
  147. data/lib/carray/io/csv.rb +560 -0
  148. data/lib/carray/io/excel.rb +26 -0
  149. data/lib/carray/io/imagemagick.rb +231 -0
  150. data/lib/carray/io/pg.rb +101 -0
  151. data/lib/carray/io/sqlite3.rb +202 -0
  152. data/lib/carray/io/table.rb +77 -0
  153. data/lib/carray/math/histogram.rb +179 -0
  154. data/lib/carray/math/interp.rb +57 -0
  155. data/lib/carray/math/interp/adapter_gsl_spline.rb +47 -0
  156. data/lib/carray/math/recurrence.rb +95 -0
  157. data/lib/carray/mkmf.rb +145 -0
  158. data/lib/carray/object/ca_obj_iterator.rb +52 -0
  159. data/lib/carray/object/ca_obj_link.rb +52 -0
  160. data/lib/carray/object/ca_obj_pack.rb +101 -0
  161. data/mkmath.rb +731 -0
  162. data/mt19937ar.c +182 -0
  163. data/mt19937ar.h +86 -0
  164. data/rdoc_main.rb +27 -0
  165. data/rdoc_math.rb +5 -0
  166. data/rdoc_stat.rb +31 -0
  167. data/ruby_carray.c +242 -0
  168. data/ruby_ccomplex.c +497 -0
  169. data/ruby_float_func.c +83 -0
  170. data/spec/CABlockIterator/CABlockIterator_spec.rb +113 -0
  171. data/spec/CArray/bug/store_spec.rb +27 -0
  172. data/spec/CArray/index/repeat_spec.rb +10 -0
  173. data/spec/CArray/method/eq_spec.rb +80 -0
  174. data/spec/CArray/method/is_nan_spec.rb +12 -0
  175. data/spec/CArray/method/ne_spec.rb +18 -0
  176. data/spec/CArray/method/round_spec.rb +11 -0
  177. data/spec/CArray/object/_attribute_spec.rb +32 -0
  178. data/spec/CArray/object/s_new_spec.rb +31 -0
  179. data/spec/CArray/serialize/Serialization_spec.rb +89 -0
  180. data/spec/spec_all.rb +11 -0
  181. data/test/test_ALL.rb +50 -0
  182. data/test/test_CABitfield.rb +59 -0
  183. data/test/test_CABlock.rb +208 -0
  184. data/test/test_CAField.rb +40 -0
  185. data/test/test_CAGrid.rb +76 -0
  186. data/test/test_CAMapping.rb +106 -0
  187. data/test/test_CAMmap.rb +11 -0
  188. data/test/test_CARefer.rb +94 -0
  189. data/test/test_CARepeat.rb +66 -0
  190. data/test/test_CASelect.rb +23 -0
  191. data/test/test_CAShift.rb +17 -0
  192. data/test/test_CATranspose.rb +61 -0
  193. data/test/test_CAVirtual.rb +214 -0
  194. data/test/test_CAWindow.rb +55 -0
  195. data/test/test_CAWrap.rb +9 -0
  196. data/test/test_CArray.rb +228 -0
  197. data/test/test_CComplex.rb +83 -0
  198. data/test/test_CScalar.rb +91 -0
  199. data/test/test_attribute.rb +281 -0
  200. data/test/test_block_iterator.rb +17 -0
  201. data/test/test_boolean.rb +99 -0
  202. data/test/test_cast.rb +33 -0
  203. data/test/test_class.rb +85 -0
  204. data/test/test_complex.rb +43 -0
  205. data/test/test_composite.rb +125 -0
  206. data/test/test_convert.rb +79 -0
  207. data/test/test_copy.rb +141 -0
  208. data/test/test_creation.rb +85 -0
  209. data/test/test_element.rb +146 -0
  210. data/test/test_extream.rb +55 -0
  211. data/test/test_generate.rb +75 -0
  212. data/test/test_index.rb +71 -0
  213. data/test/test_mask.rb +578 -0
  214. data/test/test_math.rb +98 -0
  215. data/test/test_narray.rb +64 -0
  216. data/test/test_order.rb +147 -0
  217. data/test/test_random.rb +15 -0
  218. data/test/test_ref_store.rb +211 -0
  219. data/test/test_stat.rb +414 -0
  220. data/test/test_struct.rb +72 -0
  221. data/test/test_virtual.rb +49 -0
  222. data/utils/ca_ase.rb +21 -0
  223. data/utils/ca_methods.rb +15 -0
  224. data/utils/cast_checker.rb +30 -0
  225. data/utils/create_rdoc.sh +9 -0
  226. data/utils/diff_method.rb +52 -0
  227. data/utils/extract_rdoc.rb +27 -0
  228. data/utils/make_tgz.sh +3 -0
  229. data/utils/remove_resource_fork.sh +5 -0
  230. data/version.h +3 -3
  231. metadata +266 -1
@@ -0,0 +1,1798 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ carray_access.c
4
+
5
+ This file is part of Ruby/CArray extension library.
6
+ You can redistribute it and/or modify it under the terms of
7
+ the Ruby Licence.
8
+
9
+ Copyright (C) 2005 Hiroki Motoyoshi
10
+
11
+ ---------------------------------------------------------------------------- */
12
+
13
+ #include "carray.h"
14
+
15
+ #if RUBY_VERSION_CODE >= 190
16
+ #define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
17
+ #define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
18
+ #define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
19
+ #else
20
+ static ID id_beg, id_end, id_excl;
21
+ #define RANGE_BEG(r) (rb_ivar_get(r, id_beg))
22
+ #define RANGE_END(r) (rb_ivar_get(r, id_end))
23
+ #define RANGE_EXCL(r) (rb_ivar_get(r, id_excl))
24
+ #endif
25
+
26
+ static ID id_ca, id_to_ca;
27
+ static VALUE sym_star, sym_perc;
28
+ static VALUE S_CAInfo;
29
+
30
+ VALUE
31
+ rb_ca_store_index (VALUE self, int32_t *idx, VALUE rval)
32
+ {
33
+ CArray *ca;
34
+ boolean8_t zero = 0, one = 1;
35
+
36
+ rb_ca_modify(self);
37
+ Data_Get_Struct(self, CArray, ca);
38
+
39
+ if ( ca_is_empty(ca) ) {
40
+ return rval;
41
+ }
42
+
43
+ if ( rval == CA_UNDEF ) { /* set mask at the element */
44
+ ca_update_mask(ca);
45
+ if ( ! ca->mask ) {
46
+ ca_create_mask(ca);
47
+ }
48
+ ca_store_index(ca->mask, idx, &one);
49
+ }
50
+ else { /* unset mask and set value at the element */
51
+
52
+ /* unset mask */
53
+ ca_update_mask(ca);
54
+ if ( ca->mask ) {
55
+ ca_store_index(ca->mask, idx, &zero);
56
+ }
57
+
58
+ /* store value */
59
+ if ( ca->bytes <= 32) {
60
+ char v[32];
61
+ rb_ca_obj2ptr(self, rval, v);
62
+ ca_store_index(ca, idx, v);
63
+ }
64
+ else {
65
+ char *v = malloc_with_check(ca->bytes);
66
+ rb_ca_obj2ptr(self, rval, v);
67
+ ca_store_index(ca, idx, v);
68
+ free(v);
69
+ }
70
+ }
71
+
72
+ return rval;
73
+ }
74
+
75
+ VALUE
76
+ rb_ca_fetch_index (VALUE self, int32_t *idx)
77
+ {
78
+ volatile VALUE out;
79
+ CArray *ca;
80
+ Data_Get_Struct(self, CArray, ca);
81
+
82
+ if ( ca_is_empty(ca) ) {
83
+ return Qnil;
84
+ }
85
+
86
+ /* fetch value from the element */
87
+ if ( ca->bytes <= 32) {
88
+ char v[32];
89
+ ca_fetch_index(ca, idx, v);
90
+ out = rb_ca_ptr2obj(self, v);
91
+ }
92
+ else {
93
+ char *v = malloc_with_check(ca->bytes);
94
+ ca_fetch_index(ca, idx, v);
95
+ out = rb_ca_ptr2obj(self, v);
96
+ free(v);
97
+ }
98
+
99
+ /* check if the element is masked */
100
+ ca_update_mask(ca);
101
+ if ( ca->mask ) {
102
+ boolean8_t mval;
103
+ ca_fetch_index(ca->mask, idx, &mval);
104
+ if ( mval ) {
105
+ return CA_UNDEF; /* the element is masked */
106
+ }
107
+ }
108
+
109
+ return out;
110
+ }
111
+
112
+ VALUE
113
+ rb_ca_store_addr (VALUE self, int32_t addr, VALUE rval)
114
+ {
115
+ CArray *ca;
116
+ boolean8_t zero = 0, one = 1;
117
+
118
+ rb_ca_modify(self);
119
+ Data_Get_Struct(self, CArray, ca);
120
+
121
+ if ( ca_is_empty(ca) ) {
122
+ return rval;
123
+ }
124
+
125
+ if ( rval == CA_UNDEF ) { /* set mask at the element */
126
+ ca_update_mask(ca);
127
+ if ( ! ca->mask ) {
128
+ ca_create_mask(ca);
129
+ }
130
+ ca_store_addr(ca->mask, addr, &one);
131
+ }
132
+ else { /* set value at the element */
133
+ ca_update_mask(ca);
134
+ if ( ca->mask ) {
135
+ ca_store_addr(ca->mask, addr, &zero); /* unset mask */
136
+ }
137
+
138
+ /* store value */
139
+ if ( ca->bytes <= 32) {
140
+ char v[32];
141
+ rb_ca_obj2ptr(self, rval, v);
142
+ ca_store_addr(ca, addr, v);
143
+ }
144
+ else {
145
+ char *v = malloc_with_check(ca->bytes);
146
+ rb_ca_obj2ptr(self, rval, v);
147
+ ca_store_addr(ca, addr, v);
148
+ free(v);
149
+ }
150
+ }
151
+
152
+ return rval;
153
+ }
154
+
155
+ VALUE
156
+ rb_ca_fetch_addr (VALUE self, int32_t addr)
157
+ {
158
+ volatile VALUE out;
159
+ CArray *ca;
160
+ Data_Get_Struct(self, CArray, ca);
161
+
162
+ if ( ca_is_empty(ca) ) {
163
+ return Qnil;
164
+ }
165
+
166
+ /* fetch value from the element */
167
+ if ( ca->bytes <= 32) {
168
+ char v[32];
169
+ ca_fetch_addr(ca, addr, v);
170
+ out = rb_ca_ptr2obj(self, v);
171
+ }
172
+ else {
173
+ char *v = malloc_with_check(ca->bytes);
174
+ ca_fetch_addr(ca, addr, v);
175
+ out = rb_ca_ptr2obj(self, v);
176
+ free(v);
177
+ }
178
+
179
+ /* check if the element is masked */
180
+ ca_update_mask(ca);
181
+ if ( ca->mask ) {
182
+ boolean8_t mval;
183
+ ca_fetch_addr(ca->mask, addr, &mval);
184
+ if ( mval ) {
185
+ return CA_UNDEF; /* the element is masked */
186
+ }
187
+ }
188
+
189
+ return out;
190
+ }
191
+
192
+ /* rdoc:
193
+ class CArray
194
+ def fill
195
+ end
196
+ def fill_copy
197
+ end
198
+ end
199
+ */
200
+
201
+ VALUE
202
+ rb_ca_fill (VALUE self, VALUE rval)
203
+ {
204
+ CArray *ca;
205
+
206
+ rb_ca_modify(self);
207
+ Data_Get_Struct(self, CArray, ca);
208
+
209
+ if ( ca_is_empty(ca) ) {
210
+ return rval;
211
+ }
212
+
213
+ if ( rval == CA_UNDEF ) {
214
+ boolean8_t one = 1;
215
+ ca_update_mask(ca);
216
+ if ( ! ca->mask ) {
217
+ ca_create_mask(ca);
218
+ }
219
+ ca_fill(ca->mask, &one);
220
+ }
221
+ else {
222
+ char *fval = malloc_with_check(ca->bytes);
223
+ boolean8_t zero = 0;
224
+ rb_ca_obj2ptr(self, rval, fval);
225
+ if ( ca_has_mask(ca) ) {
226
+ ca_fill(ca->mask, &zero);
227
+ }
228
+ ca_fill(ca, fval);
229
+ free(fval);
230
+ }
231
+
232
+ return self;
233
+ }
234
+
235
+ VALUE
236
+ rb_ca_fill_copy (VALUE self, VALUE rval)
237
+ {
238
+ volatile VALUE out = rb_ca_template(self);
239
+ return rb_ca_fill(out, rval);
240
+ }
241
+
242
+ /* -------------------------------------------------------------------- */
243
+
244
+ static void
245
+ ary_guess_shape (VALUE ary, int level, int *max_level, int32_t *dim)
246
+ {
247
+ volatile VALUE ary0;
248
+ if ( level > CA_RANK_MAX ) {
249
+ rb_raise(rb_eRuntimeError, "too deep level array for conversion to carray");
250
+ }
251
+
252
+ if ( TYPE(ary) == T_ARRAY ) {
253
+ if ( RARRAY_LEN(ary) == 0 && level == 0 ) {
254
+ *max_level = level;
255
+ dim[level] = 0;
256
+ }
257
+ else if ( RARRAY_LEN(ary) > 0 ) {
258
+ *max_level = level;
259
+ dim[level] = RARRAY_LEN(ary);
260
+ ary0 = rb_ary_entry(ary, 0);
261
+ if ( TYPE(ary0) == T_ARRAY ) {
262
+ int32_t dim0 = RARRAY_LEN(ary0);
263
+ int32_t i;
264
+ int flag = 0;
265
+ for (i=0; i<dim[level]; i++) {
266
+ VALUE x = rb_ary_entry(ary, i);
267
+ flag = flag || ( TYPE(x) != T_ARRAY ) || ( dim0 != RARRAY_LEN(x) );
268
+ }
269
+ if ( ! flag ) {
270
+ ary_guess_shape(ary0, level+1, max_level, dim);
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+
277
+ /* rdoc:
278
+ def CArray.guess_array_shape (arg)
279
+ end
280
+ */
281
+
282
+ static VALUE
283
+ rb_ca_s_guess_array_shape (VALUE self, VALUE ary)
284
+ {
285
+ volatile VALUE out;
286
+ int32_t dim[CA_RANK_MAX];
287
+ int max_level = -1;
288
+ int i;
289
+ ary_guess_shape(ary, 0, &max_level, dim);
290
+ out = rb_ary_new2(max_level);
291
+ for (i=0; i<max_level+1; i++) {
292
+ rb_ary_store(out, i, INT2NUM(dim[i]));
293
+ }
294
+ return out;
295
+ }
296
+
297
+ static void
298
+ ary_flatten_upto_level (VALUE ary, int max_level, int level,
299
+ VALUE out, int *len)
300
+ {
301
+ int32_t i;
302
+
303
+ if ( TYPE(ary) != T_ARRAY ) {
304
+ rb_raise(rb_eRuntimeError, "invalid shape array for conversion to carray");
305
+ }
306
+
307
+ if ( level == max_level ) {
308
+ *len += RARRAY_LEN(ary);
309
+ for (i=0; i<RARRAY_LEN(ary); i++) {
310
+ rb_ary_push(out, rb_ary_entry(ary, i));
311
+ }
312
+ }
313
+ else {
314
+ for (i=0; i<RARRAY_LEN(ary); i++) {
315
+ VALUE x = rb_ary_entry(ary, i);
316
+ ary_flatten_upto_level(x, max_level, level+1, out, len);
317
+ }
318
+ }
319
+ }
320
+
321
+ static VALUE
322
+ rb_ary_flatten_for_elements (VALUE ary, int32_t elements, void *ap)
323
+ {
324
+ CArray *ca = (CArray *) ap;
325
+ int32_t dim[CA_RANK_MAX];
326
+ int32_t total;
327
+ int max_level = -1, level = -1;
328
+ int same_shape, is_object = ( ca_is_object_type(ca) );
329
+ int i;
330
+
331
+ ary_guess_shape(ary, 0, &max_level, dim);
332
+
333
+ if ( max_level == -1 ) {
334
+ return Qnil;
335
+ }
336
+
337
+ if ( ! ca_is_object_type(ca) ) {
338
+ total = 1;
339
+ for (i=0; i<max_level+1; i++) {
340
+ total *= dim[i];
341
+ level = i;
342
+ if ( is_object && total == elements ) {
343
+ break;
344
+ }
345
+ }
346
+
347
+ if ( total != ca->elements ) {
348
+ rb_raise(rb_eRuntimeError, "invalid shape array for conversion to carray");
349
+ }
350
+ else {
351
+ VALUE out = rb_ary_new2(elements);
352
+ int len = 0;
353
+ ary_flatten_upto_level(ary, max_level, 0, out, &len);
354
+ if ( len != elements ) {
355
+ return Qnil;
356
+ }
357
+ else {
358
+ return out;
359
+ }
360
+ }
361
+ }
362
+ else {
363
+ same_shape = 1;
364
+ if ( max_level+1 < ca->rank ) {
365
+ same_shape = 0;
366
+ }
367
+ else {
368
+ for (i=0; i<ca->rank; i++) {
369
+ if ( ca->dim[i] != dim[i] ) {
370
+ same_shape = 0;
371
+ break;
372
+ }
373
+ }
374
+ }
375
+
376
+ if ( same_shape ) {
377
+ VALUE out = rb_ary_new2(elements);
378
+ int len = 0;
379
+ ary_flatten_upto_level(ary, ca->rank-1, 0, out, &len);
380
+
381
+ if ( len != elements ) {
382
+ return Qnil;
383
+ }
384
+ else {
385
+ return out;
386
+ }
387
+ }
388
+ else {
389
+ total = 1;
390
+ for (i=0; i<max_level+1; i++) {
391
+ total *= dim[i];
392
+ level = i;
393
+ if ( is_object && total == elements ) {
394
+ break;
395
+ }
396
+ }
397
+
398
+ if ( level >= 0 ) {
399
+ VALUE out = rb_ary_new2(elements);
400
+ int len = 0;
401
+ ary_flatten_upto_level(ary, level, 0, out, &len);
402
+ if ( len != elements ) {
403
+ return Qnil;
404
+ }
405
+ else {
406
+ return out;
407
+ }
408
+ }
409
+ else {
410
+ return Qnil;
411
+ }
412
+ }
413
+ }
414
+ }
415
+
416
+ #define CA_CHECK_INDEX_AT(index, dim, i) \
417
+ if ( index < 0 ) { \
418
+ index += (dim); \
419
+ } \
420
+ if ( index < 0 || index >= (dim) ) { \
421
+ rb_raise(rb_eIndexError, \
422
+ "index out of range at %i-dim ( %i <=> 0..%i )", \
423
+ i, index, dim-1); \
424
+ }
425
+
426
+ void
427
+ rb_ca_scan_index (int ca_rank, int32_t *ca_dim, int32_t ca_elements,
428
+ int argc, VALUE *argv, CAIndexInfo *info)
429
+ {
430
+ int32_t i;
431
+
432
+ info->rank = 0;
433
+ info->select = NULL;
434
+
435
+ if ( argc == 0 ) { /* ca[] -> CA_REG_ALL */
436
+ info->type = CA_REG_ALL;
437
+ return;
438
+ }
439
+
440
+ /* ca[:method, ...] -> CA_REG_METHOD_CALL
441
+ ca[:i, ...] -> CA_REG_ITERATOR */
442
+ if ( TYPE(argv[0]) == T_SYMBOL ) {
443
+ const char *symstr = rb_id2name(SYM2ID(argv[0]));
444
+ if ( strlen(symstr) > 1 ) { /* ca[:method, ...] -> CA_REG_METHOD_CALL */
445
+ info->type = CA_REG_METHOD_CALL;
446
+ info->symbol = argv[0];
447
+ return;
448
+ }
449
+ }
450
+
451
+ if ( argc == 1 ) {
452
+
453
+ volatile VALUE arg = argv[0];
454
+
455
+ if ( arg == Qfalse ) { /* ca[false] -> CA_REG_ALL */
456
+ info->type = CA_REG_ALL;
457
+ return;
458
+ }
459
+
460
+ if ( rb_obj_is_carray(arg) ) {
461
+ CArray *cs;
462
+ Data_Get_Struct(arg, CArray, cs);
463
+ if ( ca_is_integer_type(cs) ) {
464
+ #if 0
465
+ if ( ca_rank == 1 && cs->rank == 1 ) { /* ca[g] -> CA_REG_GRID (1d) */
466
+ info->type = CA_REG_GRID;
467
+ }
468
+ else { /* ca[m] -> CA_REG_MAPPER (2d...) */
469
+ info->type = CA_REG_MAPPING;
470
+ }
471
+ #endif
472
+ info->type = CA_REG_MAPPING;
473
+ return;
474
+ }
475
+ else if ( ca_is_boolean_type(cs) ) {
476
+ /* ca[selector] -> CA_REG_SELECT */
477
+ if ( ca_elements != cs->elements ) {
478
+ rb_raise(rb_eRuntimeError,
479
+ "mismatch of # of elements ( %i <=> %i ) in reference by selection",
480
+ cs->elements, ca_elements);
481
+ }
482
+ info->type = CA_REG_SELECT;
483
+ info->select = cs;
484
+ return;
485
+ }
486
+ else {
487
+ rb_raise(rb_eIndexError,
488
+ "data_type %s is invalid for reference by selection/mapping" \
489
+ "(should be boolean or integer)",
490
+ ca_type_name[cs->data_type]);
491
+ }
492
+ }
493
+
494
+ if ( TYPE(arg) == T_STRING ) { /* ca["field"] -> CA_REG_MEMBER */
495
+ info->type = CA_REG_MEMBER;
496
+ info->symbol = ID2SYM(rb_intern(StringValuePtr(arg)));
497
+ return;
498
+ }
499
+
500
+ if ( arg == sym_star ) { /* ca[:*] -> CA_REG_UNBOUND_REPEAT */
501
+ info->type = CA_REG_UNBOUND_REPEAT;
502
+ return;
503
+ }
504
+
505
+ if ( ca_rank > 1 ) { /* ca.rank > 1 */
506
+ if ( rb_obj_is_kind_of(arg, rb_cInteger) ) { /* ca[n] -> CA_REG_ADDRESS */
507
+ int32_t addr;
508
+ info->type = CA_REG_ADDRESS;
509
+ info->rank = 1;
510
+ addr = NUM2INT(arg);
511
+ CA_CHECK_INDEX(addr, ca_elements);
512
+ info->index[0].scalar = addr;
513
+ return;
514
+ }
515
+ else { /* ca[i..j] -> CA_REG_ADDRESS_COMPLEX */
516
+ info->type = CA_REG_ADDRESS_COMPLEX;
517
+ return;
518
+ }
519
+ }
520
+ }
521
+
522
+ /* continue to next section */
523
+
524
+ if ( argc >= 1 ) {
525
+ int32_t is_point = 0, is_all = 0, is_iterator = 0, is_repeat=0, is_grid=0;
526
+ int32_t has_rubber = 0;
527
+ int32_t *index_type = info->index_type;
528
+ CAIndex *index = info->index;
529
+
530
+ for (i=0; i<argc; i++) {
531
+ if ( argv[i] == sym_perc ) {
532
+ is_repeat = 1;
533
+ goto loop_exit; /* ca[--,:%,--] -> CA_REG_REPEAT */
534
+ }
535
+
536
+ if ( argv[i] == sym_star ) {
537
+ is_repeat = 2;
538
+ goto loop_exit; /* ca[--,:*,--] -> CA_REG_UNBOUND_REPEAT */
539
+ }
540
+
541
+ if ( argv[i] == Qfalse ) { /* ca[--,false,--] (rubber dimension) */
542
+ has_rubber = 1;
543
+ if ( argc > ca_rank + 1 ) {
544
+ rb_raise(rb_eIndexError,
545
+ "index specification exceeds the rank of carray (%i)",
546
+ ca_rank);
547
+ }
548
+ }
549
+ }
550
+
551
+ if ( ! has_rubber && ca_rank != argc ) {
552
+ rb_raise(rb_eIndexError,
553
+ "number of indices exceeds the rank of carray (%i > %i)",
554
+ argc, ca_rank);
555
+ }
556
+
557
+ info->rank = argc;
558
+
559
+ for (i=0; i<argc; i++) {
560
+ volatile VALUE arg = argv[i];
561
+
562
+ retry:
563
+
564
+ if ( rb_obj_is_kind_of(arg, rb_cInteger) ) { /* ca[--,i,--] */
565
+ int32_t scalar;
566
+ index_type[i] = CA_IDX_SCALAR;
567
+ scalar = NUM2INT(arg);
568
+ CA_CHECK_INDEX_AT(scalar, ca_dim[i], i);
569
+ index[i].scalar = scalar;
570
+ }
571
+ else if ( NIL_P(arg) ) { /* ca[--,nil,--] */
572
+ index_type[i] = CA_IDX_ALL;
573
+ }
574
+ else if ( arg == Qfalse ) { /* ca[--,false,--] */
575
+ int32_t rrank = ca_rank - argc + 1;
576
+ int32_t j;
577
+ for (j=0; j<rrank; j++) {
578
+ index_type[i+j] = CA_IDX_ALL;
579
+ }
580
+ i += rrank-1;
581
+ argv -= rrank-1;
582
+ argc = ca_rank;
583
+ info->rank = ca_rank;
584
+ }
585
+ else if ( rb_obj_is_kind_of(arg, rb_cRange) ) { /* ca[--,i..j,--] */
586
+ int32_t first, last, excl, count, step;
587
+ volatile VALUE iv_beg, iv_end, iv_excl;
588
+ iv_beg = RANGE_BEG(arg);
589
+ iv_end = RANGE_END(arg);
590
+ iv_excl = RANGE_EXCL(arg);
591
+ index_type[i] = CA_IDX_BLOCK; /* convert to block */
592
+ first = NUM2INT(iv_beg);
593
+ last = NUM2INT(iv_end);
594
+ excl = RTEST(iv_excl);
595
+ CA_CHECK_INDEX_AT(first, ca_dim[i], i);
596
+
597
+ if ( last < 0 ) { /* don't use CA_CHECK_INDEX for excl */
598
+ last += ca_dim[i];
599
+ }
600
+ if ( excl && ( first == last ) ) {
601
+ index[i].block.start = first;
602
+ index[i].block.count = 0;
603
+ index[i].block.step = 1;
604
+ }
605
+ else {
606
+ if ( excl ) {
607
+ last += ( (last>=first) ? -1 : 1 );
608
+ }
609
+ if ( last < 0 || last >= ca_dim[i] ) {
610
+ rb_raise(rb_eIndexError,
611
+ "index %i is out of range (0..%i) at %i-dim",
612
+ last, ca_dim[i]-1, i);
613
+ }
614
+ index[i].block.start = first;
615
+ index[i].block.count = count = abs(last - first) + 1;
616
+ index[i].block.step = step = ( last >= first ) ? 1 : -1;
617
+ }
618
+ }
619
+ else if ( TYPE(arg) == T_ARRAY ) { /* ca[--,[array],--] */
620
+ if ( RARRAY_LEN(arg) == 1 ) {
621
+ VALUE arg0 = rb_ary_entry(arg, 0);
622
+ if ( NIL_P(arg0) ) { /* ca[--,[nil],--]*/
623
+ index_type[i] = CA_IDX_ALL;
624
+ }
625
+ else if ( rb_obj_is_kind_of(arg0, rb_cRange) ) {
626
+ /* ca[--,[i..j],--] */
627
+ arg = arg0;
628
+ goto retry;
629
+ }
630
+ else { /* ca[--,[i],--]*/
631
+ int32_t start;
632
+ start = NUM2INT(arg0);
633
+ CA_CHECK_INDEX_AT(start, ca_dim[i], i);
634
+ index_type[i] = CA_IDX_BLOCK;
635
+ index[i].block.start = start;
636
+ index[i].block.count = 1;
637
+ index[i].block.step = 1;
638
+ }
639
+ }
640
+ else if ( RARRAY_LEN(arg) == 2 ) {
641
+ VALUE arg0 = rb_ary_entry(arg, 0);
642
+ VALUE arg1 = rb_ary_entry(arg, 1);
643
+ if ( NIL_P(arg0) ) { /* ca[--,[nil,k],--]*/
644
+ int32_t start, last, count, step, bound;
645
+ step = NUM2INT(arg1);
646
+ if ( step == 0 ) {
647
+ rb_raise(rb_eRuntimeError,
648
+ "step in index equals to 0 in block reference");
649
+ }
650
+ start = 0;
651
+ last = ca_dim[i]-1;
652
+ if ( step < 0 ) {
653
+ count = 1;
654
+ }
655
+ else {
656
+ count = last/step + 1;
657
+ }
658
+ bound = start + (count - 1)*step;
659
+ CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
660
+ index_type[i] = CA_IDX_BLOCK;
661
+ index[i].block.start = start;
662
+ index[i].block.count = count;
663
+ index[i].block.step = step;
664
+ }
665
+ else if ( rb_obj_is_kind_of(arg0, rb_cRange) ) { /* ca[--,[i..j,k],--]*/
666
+ int32_t start, last, excl, count, step, bound;
667
+ start = NUM2INT(RANGE_BEG(arg0));
668
+ last = NUM2INT(RANGE_END(arg0));
669
+ excl = RTEST(RANGE_EXCL(arg0));
670
+ step = NUM2INT(arg1);
671
+ if ( step == 0 ) {
672
+ rb_raise(rb_eRuntimeError,
673
+ "step in index equals to 0 in block reference");
674
+ }
675
+ index_type[i] = CA_IDX_BLOCK;
676
+ CA_CHECK_INDEX_AT(start, ca_dim[i], i);
677
+ if ( last < 0 ) {
678
+ last += ca_dim[i];
679
+ }
680
+ if ( excl && ( start == last ) ) {
681
+ index[i].block.start = start;
682
+ index[i].block.count = 0;
683
+ index[i].block.step = 1;
684
+ }
685
+ else {
686
+ if ( excl ) {
687
+ last += ( (last>=start) ? -1 : 1 );
688
+ }
689
+ if ( last < 0 || last >= ca_dim[i] ) {
690
+ rb_raise(rb_eIndexError,
691
+ "index %i is out of range (0..%i) at %i-dim",
692
+ last, ca_dim[i]-1, i);
693
+ }
694
+ if ( (last - start) * step < 0 ) {
695
+ count = 1;
696
+ }
697
+ else {
698
+ count = abs(last - start)/abs(step) + 1;
699
+ }
700
+ bound = start + (count - 1)*step;
701
+ CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
702
+ index[i].block.start = start;
703
+ index[i].block.count = count;
704
+ index[i].block.step = step;
705
+ }
706
+ }
707
+ else { /* ca[--,[i,j],--]*/
708
+ int32_t start, count, bound;
709
+ start = NUM2INT(arg0);
710
+ count = NUM2INT(arg1);
711
+ bound = start + (count - 1);
712
+ CA_CHECK_INDEX_AT(start, ca_dim[i], i);
713
+ CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
714
+ index_type[i] = CA_IDX_BLOCK;
715
+ index[i].block.start = start;
716
+ index[i].block.count = count;
717
+ index[i].block.step = 1;
718
+ }
719
+ }
720
+ else if ( RARRAY_LEN(arg) == 3 ) { /* ca[--,[i,j,k],--]*/
721
+ int32_t start, count, step, bound;
722
+ start = NUM2INT(rb_ary_entry(arg, 0));
723
+ count = NUM2INT(rb_ary_entry(arg, 1));
724
+ step = NUM2INT(rb_ary_entry(arg, 2));
725
+ if ( step == 0 ) {
726
+ rb_raise(rb_eRuntimeError,
727
+ "step in index equals to 0 in block reference");
728
+ }
729
+ bound = start + (count - 1)*step;
730
+ CA_CHECK_INDEX_AT(start, ca_dim[i], i);
731
+ CA_CHECK_INDEX_AT(bound, ca_dim[i], i);
732
+ index_type[i] = CA_IDX_BLOCK;
733
+ index[i].block.start = start;
734
+ index[i].block.count = count;
735
+ index[i].block.step = step;
736
+ }
737
+ else {
738
+ rb_raise(rb_eIndexError,
739
+ "invalid form of index range at %i-dim "\
740
+ "(should be [start[,count[,step]]], [range, step])",
741
+ i);
742
+ }
743
+ }
744
+ else if ( rb_obj_is_kind_of(arg, rb_cSymbol) ) { /* ca[--,:i,--] */
745
+ if ( strlen(rb_id2name(SYM2ID(arg))) != 1 ) {
746
+ rb_raise(rb_eIndexError,
747
+ "symbol :%s is invalid as the index for dimension iterator "\
748
+ "(should be :a, :b, ... :z)",
749
+ rb_id2name(SYM2ID(arg)));
750
+ }
751
+ index_type[i] = CA_IDX_SYMBOL;
752
+ index[i].symbol.id = SYM2ID(arg);
753
+ index[i].symbol.spec = Qnil;
754
+ }
755
+ else if ( rb_obj_is_carray(arg) ) { /* ca[--,ca,--] */
756
+ CArray *ci;
757
+ Data_Get_Struct(arg, CArray, ci);
758
+ if ( ca_is_boolean_type(ci) || ca_is_integer_type(ci) ) {
759
+ is_grid = 1;
760
+ goto loop_exit;
761
+ }
762
+ else {
763
+ rb_raise(rb_eIndexError,
764
+ "data_type %s is invalid for reference by gridding at %i-dim "\
765
+ "(should be boolean or integer)",
766
+ ca_type_name[ci->data_type], i);
767
+ }
768
+ }
769
+ else {
770
+ VALUE inspect = rb_inspect(arg);
771
+ rb_raise(rb_eIndexError,
772
+ "object '%s' is invalid for the index for reference at %i-dim",
773
+ StringValuePtr(inspect), i);
774
+ }
775
+ }
776
+
777
+ if ( ca_rank != info->rank ) {
778
+ rb_raise(rb_eIndexError,
779
+ "number of indices does not equal to the rank (%i != %i)",
780
+ info->rank, ca_rank);
781
+ }
782
+
783
+ is_point = 1;
784
+ is_all = 1;
785
+ is_iterator = 0;
786
+ is_grid = 0;
787
+
788
+ for (i=0; i<info->rank; i++) {
789
+ switch ( info->index_type[i] ) {
790
+ case CA_IDX_SCALAR:
791
+ is_all = 0;
792
+ continue;
793
+ case CA_IDX_ALL:
794
+ is_point = 0;
795
+ continue;
796
+ case CA_IDX_SYMBOL:
797
+ is_iterator = 1;
798
+ goto loop_exit;
799
+ default:
800
+ is_point = 0;
801
+ is_all = 0;
802
+ }
803
+ }
804
+
805
+ loop_exit:
806
+
807
+ if ( is_repeat == 1 ) {
808
+ info->type = CA_REG_REPEAT;
809
+ }
810
+ else if ( is_repeat == 2 ) {
811
+ info->type = CA_REG_UNBOUND_REPEAT;
812
+ }
813
+ else if ( is_grid ) {
814
+ info->type = CA_REG_GRID;
815
+ }
816
+ else if ( is_iterator ) {
817
+ info->type = CA_REG_ITERATOR;
818
+ }
819
+ else if ( is_point ) {
820
+ info->type = CA_REG_POINT;
821
+ }
822
+ else if ( is_all ) {
823
+ info->type = CA_REG_BLOCK;
824
+ }
825
+ else {
826
+ info->type = CA_REG_BLOCK;
827
+ }
828
+
829
+ if ( info->type == CA_REG_ITERATOR ) {
830
+ for (i=0; i<info->rank; i++) {
831
+ if ( info->index_type[i] == CA_IDX_SCALAR ) {
832
+ int32_t start = info->index[i].scalar;
833
+ info->index_type[i] = CA_IDX_BLOCK;
834
+ info->index[i].block.start = start;
835
+ info->index[i].block.step = 1;
836
+ info->index[i].block.count = 1;
837
+ }
838
+ }
839
+ }
840
+
841
+ return;
842
+ }
843
+ }
844
+
845
+ /* ----------------------------------------------------------------------- */
846
+
847
+ static VALUE
848
+ rb_ca_ref_address (VALUE self, CAIndexInfo *info)
849
+ {
850
+ CArray *ca;
851
+ int32_t addr;
852
+ Data_Get_Struct(self, CArray, ca);
853
+ addr = info->index[0].scalar;
854
+ return rb_ca_fetch_addr(self, addr);
855
+ }
856
+
857
+ static VALUE
858
+ rb_ca_store_address (VALUE self, CAIndexInfo *info, volatile VALUE rval)
859
+ {
860
+ CArray *ca;
861
+ int32_t addr;
862
+ Data_Get_Struct(self, CArray, ca);
863
+ addr = info->index[0].scalar;
864
+ if ( rb_obj_is_cscalar(rval) ) {
865
+ rval = rb_ca_fetch_addr(rval, 0);
866
+ }
867
+ rb_ca_store_addr(self, addr, rval);
868
+ return rval;
869
+ }
870
+
871
+ static VALUE
872
+ rb_ca_ref_point (VALUE self, CAIndexInfo *info)
873
+ {
874
+ CArray *ca;
875
+ int32_t idx[CA_RANK_MAX];
876
+ int32_t i;
877
+ Data_Get_Struct(self, CArray, ca);
878
+ for (i=0; i<ca->rank; i++) {
879
+ idx[i] = info->index[i].scalar;
880
+ }
881
+ return rb_ca_fetch_index(self, idx);
882
+ }
883
+
884
+ static VALUE
885
+ rb_ca_store_point (VALUE self, CAIndexInfo *info, volatile VALUE val)
886
+ {
887
+ CArray *ca;
888
+ int32_t idx[CA_RANK_MAX];
889
+ int32_t i;
890
+ Data_Get_Struct(self, CArray, ca);
891
+ for (i=0; i<ca->rank; i++) {
892
+ idx[i] = info->index[i].scalar;
893
+ }
894
+ if ( rb_obj_is_cscalar(val) ) {
895
+ val = rb_ca_fetch_addr(val, 0);
896
+ }
897
+ rb_ca_store_index(self, idx, val);
898
+ return val;
899
+ }
900
+
901
+ static VALUE
902
+ rb_ca_ref_all (VALUE self, CAIndexInfo *info)
903
+ {
904
+ return rb_funcall(self, rb_intern("refer"), 0);
905
+ }
906
+
907
+ VALUE
908
+ rb_ca_store_all (VALUE self, VALUE rval)
909
+ {
910
+ CArray *ca;
911
+
912
+ rb_ca_modify(self);
913
+
914
+ if ( self == rval || rb_ca_is_empty(self) ) {
915
+ return rval;
916
+ }
917
+
918
+ if ( rb_obj_is_cscalar(rval) ) {
919
+ rval = rb_ca_fetch_addr(rval, 0);
920
+ }
921
+
922
+ Data_Get_Struct(self, CArray, ca);
923
+
924
+ retry:
925
+
926
+ if ( rb_obj_is_carray(rval) ) {
927
+ CArray *cv;
928
+ Data_Get_Struct(rval, CArray, cv);
929
+
930
+ if ( cv->obj_type == CA_OBJ_UNBOUND_REPEAT ) {
931
+ rval = ca_ubrep_bind_with(rval, self);
932
+ Data_Get_Struct(rval, CArray, cv);
933
+ }
934
+
935
+ if ( ca->elements != cv->elements ) {
936
+ rb_raise(rb_eRuntimeError,
937
+ "mismatch in data size (%i <-> %i) for storing to carray",
938
+ ca->elements, cv->elements);
939
+ }
940
+
941
+ ca_attach(cv);
942
+ if ( ca->data_type != cv->data_type ) {
943
+ ca_allocate(ca);
944
+ ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
945
+ if ( ca->mask ) {
946
+ ca_cast_block_with_mask(ca->elements, cv, cv->ptr, ca, ca->ptr,
947
+ (boolean8_t*)ca->mask->ptr);
948
+ }
949
+ else {
950
+ ca_cast_block(ca->elements, cv, cv->ptr, ca, ca->ptr);
951
+ }
952
+ ca_sync(ca);
953
+ ca_detach(ca);
954
+ }
955
+ else {
956
+ ca_copy_mask_overwrite(ca, ca->elements, 1, cv);
957
+ ca_sync_data(ca, cv->ptr);
958
+ }
959
+ ca_detach(cv);
960
+ }
961
+ else if ( TYPE(rval) == T_ARRAY ) {
962
+ volatile VALUE list =
963
+ rb_ary_flatten_for_elements(rval, ca->elements, ca);
964
+ int32_t i;
965
+ if ( NIL_P(list) ) {
966
+ rb_raise(rb_eRuntimeError,
967
+ "failed to guess data size of given array");
968
+ }
969
+ else {
970
+ int has_mask = 0;
971
+ CArray ico;
972
+ ico.data_type = CA_OBJECT;
973
+ ico.bytes = ca_sizeof[CA_OBJECT];
974
+ for (i=0; i<ca->elements; i++) {
975
+ if ( rb_ary_entry(list,i) == CA_UNDEF ) {
976
+ has_mask = 1;
977
+ ca_create_mask(ca);
978
+ break;
979
+ }
980
+ }
981
+ ca_allocate(ca);
982
+ if ( has_mask ) {
983
+ boolean8_t *m;
984
+ m = (boolean8_t *)ca->mask->ptr;
985
+ for (i=0; i<ca->elements; i++) {
986
+ if ( rb_ary_entry(list,i) == CA_UNDEF ) {
987
+ *m = 1;
988
+ }
989
+ else {
990
+ *m = 0;
991
+ }
992
+ m++;
993
+ }
994
+ ca_cast_block_with_mask(ca->elements, &ico, RARRAY_PTR(list),
995
+ ca, ca->ptr,
996
+ (boolean8_t*)ca->mask->ptr);
997
+ }
998
+ else {
999
+ ca_cast_block(ca->elements, &ico, RARRAY_PTR(list), ca, ca->ptr);
1000
+ }
1001
+ ca_sync(ca);
1002
+ ca_detach(ca);
1003
+ }
1004
+ }
1005
+ else if ( rb_respond_to(rval, id_ca) ) {
1006
+ rval = rb_funcall(rval, id_ca, 0);
1007
+ goto retry;
1008
+ }
1009
+ else if ( rb_respond_to(rval, id_to_ca) ) {
1010
+ rval = rb_funcall(rval, id_to_ca, 0);
1011
+ goto retry;
1012
+ }
1013
+ else {
1014
+ rb_ca_fill(self, rval);
1015
+ }
1016
+
1017
+ return rval;
1018
+ }
1019
+
1020
+ static void
1021
+ rb_ca_index_restruct_block (int16_t *rankp, int32_t *shrink, int32_t *dim,
1022
+ int32_t *start, int32_t *step, int32_t *count,
1023
+ int32_t *offsetp)
1024
+ {
1025
+ int32_t dim0[CA_RANK_MAX];
1026
+ int32_t start0[CA_RANK_MAX];
1027
+ int32_t step0[CA_RANK_MAX];
1028
+ int32_t count0[CA_RANK_MAX];
1029
+ int32_t idx[CA_RANK_MAX];
1030
+ int16_t rank0, rank;
1031
+ int32_t offset0, offset, length;
1032
+ int32_t k, n;
1033
+ int32_t i, j, m;
1034
+
1035
+ rank0 = *rankp;
1036
+ offset0 = *offsetp;
1037
+
1038
+ /* store original start, step, count to start0, step0, count0 */
1039
+ memcpy(dim0, dim, sizeof(int32_t) * rank0);
1040
+ memcpy(start0, start, sizeof(int32_t) * rank0);
1041
+ memcpy(step0, step, sizeof(int32_t) * rank0);
1042
+ memcpy(count0, count, sizeof(int32_t) * rank0);
1043
+
1044
+ /* classify and calc rank */
1045
+ n = -1;
1046
+ for (i=0; i<rank0; i++) {
1047
+ if ( ! shrink[i] ) {
1048
+ n += 1;
1049
+ }
1050
+ idx[i] = n;
1051
+ }
1052
+ rank = n + 1;
1053
+
1054
+ *rankp = rank;
1055
+
1056
+ /* calc offset */
1057
+
1058
+ offset = 0;
1059
+
1060
+ if ( idx[0] == -1 ) {
1061
+ j = 0;
1062
+ while ( idx[++j] ) {
1063
+ ;
1064
+ }
1065
+
1066
+ offset = start0[0];
1067
+ for (i=1; i<j; i++) {
1068
+ offset = offset * dim0[i] + start0[i];
1069
+ }
1070
+
1071
+ length = 1;
1072
+ for (i=j; i<rank0; i++) {
1073
+ length *= dim0[i];
1074
+ }
1075
+
1076
+ offset *= length;
1077
+ }
1078
+
1079
+ *offsetp = offset0 + offset;
1080
+
1081
+ /* calc dim, start, step, count */
1082
+
1083
+ for (i=0; i<rank0; i++) {
1084
+ n = idx[i];
1085
+ if ( n == -1) {
1086
+ continue;
1087
+ }
1088
+
1089
+ for (j=i+1, m=i; j<rank0 && (idx[j] == n); j++) {
1090
+ ;
1091
+ }
1092
+
1093
+ dim[n] = 1;
1094
+ for (k=m; k<j; k++) {
1095
+ dim[n] *= dim0[k];
1096
+ }
1097
+
1098
+ start[n] = start0[m];
1099
+ step[n] = step0[m];
1100
+ count[n] = count0[m];
1101
+ for (k=m+1; k<j; k++) {
1102
+ start[n] = start[n] * dim0[k] + start0[k];
1103
+ step[n] = step[n] * dim0[k];
1104
+ count[n] = count[n] * count0[k];
1105
+ }
1106
+
1107
+ i = j - 1;
1108
+ }
1109
+
1110
+ }
1111
+
1112
+ VALUE
1113
+ rb_ca_ref_block (VALUE self, CAIndexInfo *info)
1114
+ {
1115
+ volatile VALUE refer;
1116
+ CArray *ca;
1117
+ int32_t dim[CA_RANK_MAX];
1118
+ int32_t start[CA_RANK_MAX];
1119
+ int32_t step[CA_RANK_MAX];
1120
+ int32_t count[CA_RANK_MAX];
1121
+ int32_t shrink[CA_RANK_MAX];
1122
+ int16_t rank = 0;
1123
+ int32_t offset = 0;
1124
+ int32_t flag = 0;
1125
+ int32_t elements;
1126
+ int32_t i;
1127
+
1128
+ Data_Get_Struct(self, CArray, ca);
1129
+
1130
+ rank = info->rank;
1131
+
1132
+ elements = 1;
1133
+ for (i=0; i<info->rank; i++) {
1134
+ dim[i] = ca->dim[i];
1135
+ switch ( info->index_type[i] ) {
1136
+ case CA_IDX_SCALAR:
1137
+ elements *= 1;
1138
+ break;
1139
+ case CA_IDX_ALL:
1140
+ elements *= ca->dim[i];
1141
+ break;
1142
+ case CA_IDX_BLOCK:
1143
+ elements *= info->index[i].block.count;
1144
+ break;
1145
+ default:
1146
+ rb_raise(rb_eIndexError, "invalid index for block reference");
1147
+ }
1148
+ }
1149
+
1150
+ for (i=0; i<info->rank; i++) {
1151
+ switch ( info->index_type[i] ) {
1152
+ case CA_IDX_SCALAR:
1153
+ start[i] = info->index[i].scalar;
1154
+ step[i] = 1;
1155
+ count[i] = 1;
1156
+ shrink[i] = 1;
1157
+ break;
1158
+ case CA_IDX_ALL:
1159
+ start[i] = 0;
1160
+ step[i] = 1;
1161
+ count[i] = ca->dim[i];
1162
+ shrink[i] = 0;
1163
+ break;
1164
+ case CA_IDX_BLOCK:
1165
+ start[i] = info->index[i].block.start;
1166
+ step[i] = info->index[i].block.step;
1167
+ count[i] = info->index[i].block.count;
1168
+ shrink[i] = 0;
1169
+ break;
1170
+ }
1171
+ }
1172
+
1173
+ for (i=0; i<rank; i++) {
1174
+ if ( shrink[i] ) {
1175
+ flag = 1;
1176
+ break;
1177
+ }
1178
+ }
1179
+
1180
+ refer = self;
1181
+ rank = ca->rank;
1182
+
1183
+ offset = 0;
1184
+
1185
+ if ( flag ) {
1186
+ rb_ca_index_restruct_block(&rank, shrink,
1187
+ dim, start, step, count, &offset);
1188
+ }
1189
+
1190
+ return rb_ca_block_new(refer, rank, dim, start, step, count, offset);
1191
+ }
1192
+
1193
+ static VALUE
1194
+ rb_ca_refer_new_flatten (VALUE self)
1195
+ {
1196
+ CArray *ca;
1197
+ int32_t dim0;
1198
+
1199
+ Data_Get_Struct(self, CArray, ca);
1200
+ dim0 = ca->elements;
1201
+ return rb_ca_refer_new(self, ca->data_type, 1, &dim0, ca->bytes, 0);
1202
+ }
1203
+
1204
+ /* rdoc:
1205
+ class CArray
1206
+ def [] (*spec)
1207
+ end
1208
+ end
1209
+ */
1210
+
1211
+ static VALUE
1212
+ rb_ca_fetch_method (int argc, VALUE *argv, VALUE self)
1213
+ {
1214
+ volatile VALUE obj = Qnil;
1215
+ CArray *ca;
1216
+ CAIndexInfo info;
1217
+
1218
+ retry:
1219
+
1220
+ Data_Get_Struct(self, CArray, ca);
1221
+ rb_ca_scan_index(ca->rank, ca->dim, ca->elements, argc, argv, &info);
1222
+
1223
+ switch ( info.type ) {
1224
+ case CA_REG_ADDRESS_COMPLEX:
1225
+ self = rb_ca_refer_new_flatten(self);
1226
+ goto retry;
1227
+ case CA_REG_ADDRESS:
1228
+ obj = rb_ca_ref_address(self, &info);
1229
+ break;
1230
+ case CA_REG_POINT:
1231
+ obj = rb_ca_ref_point(self, &info);
1232
+ break;
1233
+ case CA_REG_ALL:
1234
+ obj = rb_ca_ref_all(self, &info);
1235
+ break;
1236
+ case CA_REG_BLOCK:
1237
+ obj = rb_ca_ref_block(self, &info);
1238
+ break;
1239
+ case CA_REG_SELECT:
1240
+ obj = rb_ca_select_new(self, argv[0]);
1241
+ break;
1242
+ case CA_REG_ITERATOR:
1243
+ obj = rb_dim_iter_new(self, &info);
1244
+ break;
1245
+ case CA_REG_REPEAT:
1246
+ obj = rb_ca_repeat(argc, argv, self);
1247
+ break;
1248
+ case CA_REG_UNBOUND_REPEAT:
1249
+ obj = rb_funcall2(self, rb_intern("unbound_repeat"), argc, argv);
1250
+ break;
1251
+ case CA_REG_MAPPING:
1252
+ obj = rb_ca_mapping(argc, argv, self);
1253
+ break;
1254
+ case CA_REG_GRID:
1255
+ obj = rb_ca_grid(argc, argv, self);
1256
+ break;
1257
+ case CA_REG_METHOD_CALL: {
1258
+ volatile VALUE idx;
1259
+ idx = rb_funcall2(self, SYM2ID(info.symbol), argc-1, argv+1);
1260
+ obj = rb_ca_fetch(self, idx);
1261
+ break;
1262
+ }
1263
+ case CA_REG_MEMBER: {
1264
+ volatile VALUE data_class = rb_ca_data_class(self);
1265
+ if ( ! NIL_P(data_class) ) {
1266
+ obj = rb_ca_field_as_member(self, info.symbol);
1267
+ break;
1268
+ }
1269
+ else {
1270
+ rb_raise(rb_eIndexError,
1271
+ "can't refer member of carray doesn't have data_class");
1272
+ }
1273
+ break;
1274
+ }
1275
+ default:
1276
+ rb_raise(rb_eIndexError, "invalid index specified");
1277
+ }
1278
+
1279
+ return obj;
1280
+ }
1281
+
1282
+ /* rdoc:
1283
+ class CArray
1284
+ def []= (*spec)
1285
+ end
1286
+ end
1287
+ */
1288
+
1289
+ static VALUE
1290
+ rb_ca_store_method (int argc, VALUE *argv, VALUE self)
1291
+ {
1292
+ volatile VALUE obj = Qnil, rval;
1293
+ CArray *ca;
1294
+ CAIndexInfo info;
1295
+
1296
+ rb_ca_modify(self);
1297
+
1298
+ obj = rval = argv[argc-1];
1299
+ argc -= 1;
1300
+
1301
+ retry:
1302
+
1303
+ Data_Get_Struct(self, CArray, ca);
1304
+
1305
+ rb_ca_scan_index(ca->rank, ca->dim, ca->elements, argc, argv, &info);
1306
+
1307
+ switch ( info.type ) {
1308
+ case CA_REG_ADDRESS_COMPLEX:
1309
+ self = rb_ca_refer_new_flatten(self);
1310
+ goto retry;
1311
+ case CA_REG_ADDRESS:
1312
+ obj = rb_ca_store_address(self, &info, rval);
1313
+ break;
1314
+ case CA_REG_POINT:
1315
+ obj = rb_ca_store_point(self, &info, rval);
1316
+ break;
1317
+ case CA_REG_ALL:
1318
+ obj = rb_ca_store_all(self, rval);
1319
+ break;
1320
+ case CA_REG_BLOCK: {
1321
+ volatile VALUE block;
1322
+ block = rb_ca_ref_block(self, &info);
1323
+ obj = rb_ca_store_all(block, rval);
1324
+ break;
1325
+ }
1326
+ case CA_REG_SELECT: {
1327
+ obj = rb_ca_select_new(self, argv[0]);
1328
+ obj = rb_ca_store_all(obj, rval);
1329
+ break;
1330
+ }
1331
+ case CA_REG_ITERATOR: {
1332
+ obj = rb_dim_iter_new(self, &info);
1333
+ obj = rb_funcall(obj, rb_intern("asign!"), 1, rval);
1334
+ break;
1335
+ }
1336
+ case CA_REG_REPEAT: {
1337
+ obj = rb_ca_repeat(argc, argv, self);
1338
+ obj = rb_ca_store_all(obj, rval);
1339
+ break;
1340
+ }
1341
+ case CA_REG_UNBOUND_REPEAT:
1342
+ obj = rb_funcall2(self, rb_intern("unbound_repeat"), argc, argv);
1343
+ obj = rb_ca_store_all(obj, rval);
1344
+ break;
1345
+ case CA_REG_MAPPING: {
1346
+ obj = rb_ca_mapping(argc, argv, self);
1347
+ obj = rb_ca_store_all(obj, rval);
1348
+ break;
1349
+ }
1350
+ case CA_REG_GRID: {
1351
+ obj = rb_ca_grid(argc, argv, self);
1352
+ obj = rb_ca_store_all(obj, rval);
1353
+ break;
1354
+ }
1355
+ case CA_REG_METHOD_CALL: {
1356
+ volatile VALUE idx;
1357
+ Data_Get_Struct(self, CArray, ca);
1358
+ ca_attach(ca);
1359
+ idx = rb_funcall2(self, SYM2ID(info.symbol), argc-1, argv+1);
1360
+ obj = rb_ca_store(self, idx, rval);
1361
+ ca_detach(ca);
1362
+ break;
1363
+ }
1364
+ case CA_REG_MEMBER: {
1365
+ volatile VALUE data_class = rb_ca_data_class(self);
1366
+ if ( ! NIL_P(data_class) ) {
1367
+ obj = rb_ca_field_as_member(self, info.symbol);
1368
+ obj = rb_ca_store_all(obj, rval);
1369
+ }
1370
+ else {
1371
+ rb_raise(rb_eIndexError,
1372
+ "can't store member of carray doesn't have data_class");
1373
+ }
1374
+ break;
1375
+ }
1376
+ }
1377
+ return obj;
1378
+ }
1379
+
1380
+ VALUE
1381
+ rb_ca_fetch (VALUE self, VALUE index)
1382
+ {
1383
+ switch ( TYPE(index) ) {
1384
+ case T_ARRAY:
1385
+ return rb_ca_fetch_method(RARRAY_LEN(index), RARRAY_PTR(index), self);
1386
+ default:
1387
+ return rb_ca_fetch_method(1, &index, self);
1388
+ }
1389
+ }
1390
+
1391
+ VALUE
1392
+ rb_ca_fetch2 (VALUE self, int n, VALUE *rindex)
1393
+ {
1394
+ return rb_ca_fetch_method(n, rindex, self);
1395
+ }
1396
+
1397
+ VALUE
1398
+ rb_ca_store (VALUE self, VALUE index, VALUE rval)
1399
+ {
1400
+ switch ( TYPE(index) ) {
1401
+ case T_ARRAY:
1402
+ index = rb_obj_clone(index);
1403
+ rb_ary_push(index, rval);
1404
+ return rb_ca_store_method(RARRAY_LEN(index), RARRAY_PTR(index), self);
1405
+ default: {
1406
+ VALUE rindex[2] = { index, rval };
1407
+ return rb_ca_store_method(2, rindex, self);
1408
+ }
1409
+ }
1410
+ }
1411
+
1412
+ VALUE
1413
+ rb_ca_store2 (VALUE self, int n, VALUE *rindex, VALUE rval)
1414
+ {
1415
+ VALUE index = rb_ary_new4(n, rindex);
1416
+ rb_ary_push(index, rval);
1417
+ return rb_ca_store_method(RARRAY_LEN(index), RARRAY_PTR(index), self);
1418
+ }
1419
+
1420
+ /* rdoc:
1421
+ def CArray.scan_index(dim, idx)
1422
+ end
1423
+ */
1424
+
1425
+ static VALUE
1426
+ rb_ca_s_scan_index (VALUE self, VALUE rdim, VALUE ridx)
1427
+ {
1428
+ volatile VALUE rtype, rrank, rindex;
1429
+ CAIndexInfo info;
1430
+ int rank;
1431
+ int32_t dim[CA_RANK_MAX];
1432
+ int32_t elements;
1433
+ int i;
1434
+
1435
+ Check_Type(rdim, T_ARRAY);
1436
+ Check_Type(ridx, T_ARRAY);
1437
+
1438
+ elements = 1;
1439
+ rank = RARRAY_LEN(rdim);
1440
+ for (i=0; i<rank; i++) {
1441
+ dim[i] = NUM2LONG(rb_ary_entry(rdim, i));
1442
+ elements *= dim[i];
1443
+ }
1444
+
1445
+ CA_CHECK_RANK(rank);
1446
+ CA_CHECK_DIM(rank, dim);
1447
+
1448
+ rb_ca_scan_index(rank, dim, elements,
1449
+ RARRAY_LEN(ridx), RARRAY_PTR(ridx), &info);
1450
+
1451
+ rtype = INT2NUM(info.type);
1452
+ rrank = INT2NUM(info.rank);
1453
+ rindex = rb_ary_new2(info.rank);
1454
+
1455
+ switch ( info.type ) {
1456
+ case CA_REG_NONE:
1457
+ case CA_REG_ALL:
1458
+ break;
1459
+ case CA_REG_ADDRESS:
1460
+ rb_ary_store(rindex, 0, LONG2NUM(info.index[0].scalar));
1461
+ break;
1462
+ case CA_REG_ADDRESS_COMPLEX: {
1463
+ volatile VALUE rinfo;
1464
+ int32_t elements = 1;
1465
+ for (i=0; i<rank; i++) {
1466
+ elements *= dim[i];
1467
+ }
1468
+ rinfo = rb_ca_s_scan_index(self, rb_ary_new3(1, LONG2NUM(elements)), ridx);
1469
+ rtype = LONG2NUM(CA_REG_ADDRESS_COMPLEX);
1470
+ rindex = rb_struct_aref(rinfo, rb_str_new2("index"));
1471
+ break;
1472
+ }
1473
+ case CA_REG_POINT:
1474
+ for (i=0; i<rank; i++) {
1475
+ rb_ary_store(rindex, i, LONG2NUM(info.index[i].scalar));
1476
+ }
1477
+ break;
1478
+ case CA_REG_SELECT:
1479
+ break;
1480
+ case CA_REG_BLOCK:
1481
+ case CA_REG_ITERATOR:
1482
+ for (i=0; i<rank; i++) {
1483
+ switch ( info.index_type[i] ) {
1484
+ case CA_IDX_SCALAR:
1485
+ rb_ary_store(rindex, i, LONG2NUM(info.index[i].scalar));
1486
+ break;
1487
+ case CA_IDX_ALL:
1488
+ rb_ary_store(rindex, i,
1489
+ rb_ary_new3(3,
1490
+ LONG2NUM(0),
1491
+ rb_ary_entry(rdim, i),
1492
+ LONG2NUM(1)));
1493
+ break;
1494
+ case CA_IDX_BLOCK:
1495
+ rb_ary_store(rindex, i,
1496
+ rb_ary_new3(3,
1497
+ LONG2NUM(info.index[i].block.start),
1498
+ LONG2NUM(info.index[i].block.count),
1499
+ LONG2NUM(info.index[i].block.step)));
1500
+ break;
1501
+ case CA_IDX_SYMBOL:
1502
+ rb_ary_store(rindex, i,
1503
+ rb_ary_new3(2,
1504
+ ID2SYM(info.index[i].symbol.id),
1505
+ info.index[i].symbol.spec));
1506
+ break;
1507
+ default:
1508
+ rb_raise(rb_eRuntimeError, "unknown index spec");
1509
+ }
1510
+ }
1511
+ break;
1512
+ case CA_REG_REPEAT:
1513
+ case CA_REG_GRID:
1514
+ case CA_REG_MAPPING:
1515
+ case CA_REG_METHOD_CALL:
1516
+ case CA_REG_UNBOUND_REPEAT:
1517
+ case CA_REG_MEMBER:
1518
+ break;
1519
+ default:
1520
+ rb_raise(rb_eArgError, "unknown index specification");
1521
+ }
1522
+
1523
+ return rb_struct_new(S_CAInfo, rtype, rindex);
1524
+ }
1525
+
1526
+ /* rdoc:
1527
+ class CArray
1528
+ def normalize_index (idx)
1529
+ end
1530
+ end
1531
+ */
1532
+
1533
+ static VALUE
1534
+ rb_ca_normalize_index (VALUE self, VALUE ridx)
1535
+ {
1536
+ volatile VALUE rindex;
1537
+ CArray *ca;
1538
+ CAIndexInfo info;
1539
+ int i;
1540
+
1541
+ Data_Get_Struct(self, CArray, ca);
1542
+ Check_Type(ridx, T_ARRAY);
1543
+
1544
+ rb_ca_scan_index(ca->rank, ca->dim, ca->elements,
1545
+ RARRAY_LEN(ridx), RARRAY_PTR(ridx), &info);
1546
+
1547
+ switch ( info.type ) {
1548
+ case CA_REG_ALL:
1549
+ case CA_REG_SELECT:
1550
+ case CA_REG_ADDRESS:
1551
+ rindex = rb_ary_new2(info.rank);
1552
+ rb_ary_store(rindex, 0, LONG2NUM(info.index[0].scalar));
1553
+ return rindex;
1554
+ case CA_REG_POINT:
1555
+ rindex = rb_ary_new2(info.rank);
1556
+ for (i=0; i<ca->rank; i++) {
1557
+ rb_ary_store(rindex, i, LONG2NUM(info.index[i].scalar));
1558
+ }
1559
+ return rindex;
1560
+ case CA_REG_BLOCK:
1561
+ case CA_REG_ITERATOR:
1562
+ rindex = rb_ary_new2(info.rank);
1563
+ for (i=0; i<ca->rank; i++) {
1564
+ switch ( info.index_type[i] ) {
1565
+ case CA_IDX_SCALAR:
1566
+ rb_ary_store(rindex, i, LONG2NUM(info.index[i].scalar));
1567
+ break;
1568
+ case CA_IDX_ALL:
1569
+ rb_ary_store(rindex, i, Qnil);
1570
+ break;
1571
+ case CA_IDX_BLOCK:
1572
+ rb_ary_store(rindex, i,
1573
+ rb_ary_new3(3,
1574
+ LONG2NUM(info.index[i].block.start),
1575
+ LONG2NUM(info.index[i].block.count),
1576
+ LONG2NUM(info.index[i].block.step)));
1577
+ break;
1578
+ case CA_IDX_SYMBOL:
1579
+ rb_ary_store(rindex, i, ID2SYM(info.index[i].symbol.id));
1580
+ break;
1581
+ default:
1582
+ rb_raise(rb_eRuntimeError, "unknown index spec");
1583
+ }
1584
+ }
1585
+ return rindex;
1586
+ case CA_REG_ADDRESS_COMPLEX:
1587
+ self = rb_ca_refer_new_flatten(self);
1588
+ return rb_ca_normalize_index(self, ridx);
1589
+ default:
1590
+ rb_raise(rb_eArgError, "unknown index specification");
1591
+ }
1592
+ rb_raise(rb_eArgError, "fail to normalize index");
1593
+ }
1594
+
1595
+ /* ------------------------------------------------------------------- */
1596
+
1597
+ /* rdoc:
1598
+ class CArray
1599
+ # converts addr to index
1600
+ def addr2index (addr)
1601
+ end
1602
+ end
1603
+ */
1604
+
1605
+ VALUE
1606
+ rb_ca_addr2index (VALUE self, VALUE raddr)
1607
+ {
1608
+ volatile VALUE out;
1609
+ CArray *ca;
1610
+ int32_t *dim;
1611
+ int32_t addr;
1612
+ int i;
1613
+
1614
+ Data_Get_Struct(self, CArray, ca);
1615
+
1616
+ addr = NUM2INT(raddr);
1617
+ if ( addr < 0 || addr >= ca->elements ) {
1618
+ rb_raise(rb_eArgError,
1619
+ "address %i is out of range (0..%i)",
1620
+ addr, ca->elements-1);
1621
+ }
1622
+ dim = ca->dim;
1623
+ out = rb_ary_new2(ca->rank);
1624
+ for (i=ca->rank-1; i>=0; i--) { /* in descending order */
1625
+ rb_ary_store(out, i, LONG2NUM(addr % dim[i]));
1626
+ addr /= dim[i];
1627
+ }
1628
+
1629
+ return out;
1630
+ }
1631
+
1632
+ /* rdoc:
1633
+ class CArray
1634
+ def index2addr (*index)
1635
+ end
1636
+ end
1637
+ */
1638
+
1639
+ VALUE
1640
+ rb_ca_index2addr (int argc, VALUE *argv, VALUE self)
1641
+ {
1642
+ volatile VALUE obj;
1643
+ CArray *ca, *co, *cidx[CA_RANK_MAX];
1644
+ int32_t *q, *p[CA_RANK_MAX], s[CA_RANK_MAX];
1645
+ int32_t *dim;
1646
+ int32_t addr, elements = 0;
1647
+ int32_t i, k, n;
1648
+ boolean8_t *m;
1649
+ int all_number = 1;
1650
+
1651
+ Data_Get_Struct(self, CArray, ca);
1652
+
1653
+ if ( argc != ca->rank ) {
1654
+ rb_raise(rb_eRuntimeError, "invalid rank of index");
1655
+ }
1656
+
1657
+ for (i=0; i<ca->rank; i++) {
1658
+ if ( ! rb_obj_is_kind_of(argv[i], rb_cInteger) ) {
1659
+ all_number = 0;
1660
+ break;
1661
+ }
1662
+ }
1663
+
1664
+ if ( all_number ) {
1665
+ dim = ca->dim;
1666
+ addr = 0;
1667
+ for (i=0; i<ca->rank; i++) {
1668
+ k = NUM2INT(argv[i]);
1669
+ CA_CHECK_INDEX(k, dim[i]);
1670
+ addr = dim[i] * addr + k;
1671
+ }
1672
+ return LONG2NUM(addr);
1673
+ }
1674
+
1675
+ elements = 1;
1676
+ for (i=0; i<ca->rank; i++) {
1677
+ cidx[i] = ca_wrap_readonly(argv[i], CA_INT32);
1678
+ if ( ! ca_is_scalar(cidx[i]) ) {
1679
+ if ( elements == 1 ) {
1680
+ elements = cidx[i]->elements;
1681
+ }
1682
+ else if ( elements != cidx[i]->elements ) {
1683
+ rb_raise(rb_eRuntimeError, "mismatch in # of elements");
1684
+ }
1685
+ }
1686
+ }
1687
+
1688
+ for (i=0; i<ca->rank; i++) {
1689
+ ca_attach(cidx[i]);
1690
+ ca_set_iterator(1, cidx[i], &p[i], &s[i]);
1691
+ }
1692
+
1693
+ obj = rb_carray_new(CA_INT32, 1, &elements, 0, NULL);
1694
+ Data_Get_Struct(obj, CArray, co);
1695
+
1696
+ q = (int32_t *) co->ptr;
1697
+
1698
+ ca_copy_mask_overwrite_n(co, elements, ca->rank, cidx);
1699
+ m = ( co->mask ) ? (boolean8_t *) co->mask->ptr : NULL;
1700
+
1701
+ dim = ca->dim;
1702
+
1703
+ if ( m ) {
1704
+ n = elements;
1705
+ while ( n-- ) {
1706
+ if ( !*m ) {
1707
+ addr = 0;
1708
+ for (i=0; i<ca->rank; i++) {
1709
+ k = *(p[i]);
1710
+ p[i]+=s[i];
1711
+ CA_CHECK_INDEX(k, dim[i]);
1712
+ addr = dim[i] * addr + k;
1713
+ }
1714
+ *q = addr;
1715
+ }
1716
+ else {
1717
+ for (i=0; i<ca->rank; i++) {
1718
+ p[i]+=s[i];
1719
+ }
1720
+ }
1721
+ m++; q++;
1722
+ }
1723
+ }
1724
+ else {
1725
+ n = elements;
1726
+ while ( n-- ) {
1727
+ addr = 0;
1728
+ for (i=0; i<ca->rank; i++) {
1729
+ k = *(p[i]);
1730
+ p[i]+=s[i];
1731
+ CA_CHECK_INDEX(k, dim[i]);
1732
+ addr = dim[i] * addr + k;
1733
+ }
1734
+ *q = addr;
1735
+ q++;
1736
+ }
1737
+ }
1738
+
1739
+ for (i=0; i<ca->rank; i++) {
1740
+ ca_detach(cidx[i]);
1741
+ }
1742
+
1743
+ return obj;
1744
+ }
1745
+
1746
+
1747
+ void
1748
+ Init_carray_access ()
1749
+ {
1750
+
1751
+ #if RUBY_VERSION_CODE >= 190
1752
+ #else
1753
+ id_beg = rb_intern("begin");
1754
+ id_end = rb_intern("end");
1755
+ id_excl = rb_intern("excl");
1756
+ #endif
1757
+
1758
+ id_ca = rb_intern("ca");
1759
+ id_to_ca = rb_intern("to_ca");
1760
+ sym_star = ID2SYM(rb_intern("*"));
1761
+ sym_perc = ID2SYM(rb_intern("%"));
1762
+
1763
+ rb_define_method(rb_cCArray, "[]", rb_ca_fetch_method, -1);
1764
+ rb_define_method(rb_cCArray, "[]=", rb_ca_store_method, -1);
1765
+
1766
+ rb_define_method(rb_cCArray, "fill", rb_ca_fill, 1);
1767
+ rb_define_method(rb_cCArray, "fill_copy", rb_ca_fill_copy, 1);
1768
+
1769
+ S_CAInfo = rb_struct_define("CAIndexInfo", "type", "index", NULL);
1770
+
1771
+ rb_define_singleton_method(rb_cCArray, "guess_array_shape",
1772
+ rb_ca_s_guess_array_shape, 1);
1773
+ rb_define_singleton_method(rb_cCArray, "scan_index", rb_ca_s_scan_index, 2);
1774
+ rb_define_method(rb_cCArray, "normalize_index", rb_ca_normalize_index, 1);
1775
+
1776
+ rb_define_method(rb_cCArray, "index2addr", rb_ca_index2addr, -1);
1777
+ rb_define_method(rb_cCArray, "addr2index", rb_ca_addr2index, 1);
1778
+
1779
+ rb_define_const(rb_cObject, "CA_REG_NONE", INT2NUM(CA_REG_NONE));
1780
+ rb_define_const(rb_cObject, "CA_REG_ALL", INT2NUM(CA_REG_ALL));
1781
+ rb_define_const(rb_cObject, "CA_REG_ADDRESS", INT2NUM(CA_REG_ADDRESS));
1782
+ rb_define_const(rb_cObject, "CA_REG_ADDRESS_COMPLEX",
1783
+ INT2NUM(CA_REG_ADDRESS_COMPLEX));
1784
+ rb_define_const(rb_cObject, "CA_REG_POINT", INT2NUM(CA_REG_POINT));
1785
+ rb_define_const(rb_cObject, "CA_REG_BLOCK", INT2NUM(CA_REG_BLOCK));
1786
+ rb_define_const(rb_cObject, "CA_REG_SELECT", INT2NUM(CA_REG_SELECT));
1787
+ rb_define_const(rb_cObject, "CA_REG_ITERATOR", INT2NUM(CA_REG_ITERATOR));
1788
+ rb_define_const(rb_cObject, "CA_REG_REPEAT", INT2NUM(CA_REG_REPEAT));
1789
+ rb_define_const(rb_cObject, "CA_REG_GRID", INT2NUM(CA_REG_GRID));
1790
+ rb_define_const(rb_cObject, "CA_REG_MAPPING", INT2NUM(CA_REG_MAPPING));
1791
+ rb_define_const(rb_cObject, "CA_REG_METHOD_CALL",
1792
+ INT2NUM(CA_REG_METHOD_CALL));
1793
+ rb_define_const(rb_cObject, "CA_REG_UNBOUND_REPEAT",
1794
+ INT2NUM(CA_REG_UNBOUND_REPEAT));
1795
+ rb_define_const(rb_cObject, "CA_REG_MEMBER", INT2NUM(CA_REG_MEMBER));
1796
+
1797
+ }
1798
+