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,261 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ carray_sort_addr.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 "ruby.h"
14
+ #include "carray.h"
15
+ #include <math.h>
16
+
17
+ /* ----------------------------------------------------------------- */
18
+
19
+ typedef int (*ca_qsort_cmp_func)();
20
+
21
+ #define qcmp_type(type) \
22
+ static int \
23
+ qcmp_## type (type *a, type *b) \
24
+ { \
25
+ if ( *a > *b ) return 1; \
26
+ if ( *a < *b ) return -1; \
27
+ return 0; \
28
+ }
29
+
30
+ #define qcmp_f_type(type) \
31
+ static int \
32
+ qcmp_## type (type *a, type *b) \
33
+ { \
34
+ if ( isnan(*a) && ( ! isnan(*b) ) ) return 1; \
35
+ if ( isnan(*b) && ( ! isnan(*a) ) ) return -1; \
36
+ if ( *a > *b ) return 1; \
37
+ if ( *a < *b ) return -1; \
38
+ return 0; \
39
+ }
40
+
41
+ static int
42
+ qcmp_data (char *a, char *b, int32_t bytes)
43
+ {
44
+ int cmp;
45
+ cmp = memcmp(a, b, bytes);
46
+ if ( cmp != 0 ) return cmp;
47
+ return 0;
48
+ }
49
+
50
+ static int
51
+ qcmp_VALUE (VALUE *a, VALUE *b)
52
+ {
53
+ int cmp;
54
+ cmp = NUM2INT(rb_funcall(*a, rb_intern("<=>"), 1, *b));
55
+ if ( cmp != 0 ) return cmp;
56
+ return 0;
57
+ }
58
+
59
+ qcmp_type(boolean8_t)
60
+ qcmp_type(int8_t)
61
+ qcmp_type(uint8_t)
62
+ qcmp_type(int16_t)
63
+ qcmp_type(uint16_t)
64
+ qcmp_type(int32_t)
65
+ qcmp_type(uint32_t)
66
+ qcmp_type(int64_t)
67
+ qcmp_type(uint64_t)
68
+ qcmp_f_type(float32_t)
69
+ qcmp_f_type(float64_t)
70
+ qcmp_f_type(float128_t)
71
+
72
+ static int
73
+ qcmp_not_implement (void *a, void *b)
74
+ {
75
+ rb_raise(rb_eNotImpError,
76
+ "compare function is not implemented for the data type");
77
+ }
78
+
79
+ static ca_qsort_cmp_func
80
+ ca_qsort_cmp[CA_NTYPE] = {
81
+ qcmp_data,
82
+ qcmp_boolean8_t,
83
+ qcmp_int8_t,
84
+ qcmp_uint8_t,
85
+ qcmp_int16_t,
86
+ qcmp_uint16_t,
87
+ qcmp_int32_t,
88
+ qcmp_uint32_t,
89
+ qcmp_int64_t,
90
+ qcmp_uint64_t,
91
+ qcmp_float32_t,
92
+ qcmp_float64_t,
93
+ qcmp_float128_t,
94
+ qcmp_not_implement,
95
+ qcmp_not_implement,
96
+ qcmp_not_implement,
97
+ qcmp_VALUE,
98
+ };
99
+
100
+ /* ----------------------------------------------------------------- */
101
+
102
+ struct cmp_base {
103
+ int n;
104
+ CArray **ca;
105
+ };
106
+
107
+ struct cmp_data {
108
+ int32_t i;
109
+ struct cmp_base *base;
110
+ };
111
+
112
+ static int
113
+ qcmp_func (struct cmp_data *a, struct cmp_data *b)
114
+ {
115
+ struct cmp_base *base = a->base;
116
+ int n = base->n;
117
+ CArray **ca = base->ca;
118
+ int32_t ia = a->i;
119
+ int32_t ib = b->i;
120
+ int result;
121
+ int i;
122
+ for (i=0; i<n; i++) {
123
+ int8_t data_type = ca[i]->data_type;
124
+ char *ptr = ca[i]->ptr;
125
+ boolean8_t *m = ( ca[i]->mask ) ? (boolean8_t *) ca[i]->mask->ptr : NULL;
126
+ int32_t bytes = ca[i]->bytes;
127
+ if ( ( ! m ) ||
128
+ ( ( ! m[ia] ) && ( ! m[ib] ) ) ) {
129
+ if ( data_type == CA_FIXLEN ) {
130
+ result = ca_qsort_cmp[CA_FIXLEN](ptr + ia*bytes,
131
+ ptr + ib*bytes, bytes);
132
+ }
133
+ else {
134
+ result = ca_qsort_cmp[data_type](ptr + ia*bytes,
135
+ ptr + ib*bytes);
136
+ }
137
+ }
138
+ else if ( ( ! m[ia] ) && ( m[ib] ) ) {
139
+ result = -1;
140
+ }
141
+ else if ( ( m[ia] ) && ( ! m[ib] ) ) {
142
+ result = 1;
143
+ }
144
+ else {
145
+ result = 0;
146
+ }
147
+ if ( result ) {
148
+ return result;
149
+ }
150
+ }
151
+ return ( ia > ib ) ? 1 : -1; /* for stable sort */
152
+ }
153
+
154
+ /* rdoc:
155
+ # returns index table for index sort
156
+ #
157
+ # idx = CA.sort_addr(a, b, c) ### priority a > b > c
158
+ # a[idx]
159
+ # b[idx]
160
+ # c[idx]
161
+
162
+ def CA.sort_addr (*args)
163
+ end
164
+ */
165
+
166
+ static VALUE
167
+ rb_ca_s_sort_addr (int argc, VALUE *argv, VALUE self)
168
+ {
169
+ volatile VALUE out;
170
+ CArray *co;
171
+ struct cmp_base *base;
172
+ struct cmp_data *data;
173
+ int32_t elements;
174
+ int32_t *q;
175
+ int j;
176
+ int32_t i;
177
+
178
+ if ( argc <= 0 ) {
179
+ rb_raise(rb_eArgError, "no arg given");
180
+ }
181
+
182
+ rb_check_carray_object(argv[0]);
183
+ elements = NUM2LONG(rb_ca_elements(argv[0]));
184
+
185
+ for (j=0; j<argc; j++) {
186
+ rb_check_carray_object(argv[j]);
187
+ if ( elements != NUM2LONG(rb_ca_elements(argv[j])) ) {
188
+ rb_raise(rb_eArgError, "elements mismatch");
189
+ }
190
+ }
191
+
192
+ base = malloc_with_check(sizeof(struct cmp_base));
193
+ base->n = argc;
194
+ base->ca = malloc_with_check(sizeof(CArray *)*base->n);
195
+
196
+ for (j=0; j<argc; j++) {
197
+ CArray *ca;
198
+ Data_Get_Struct(argv[j], CArray, ca);
199
+ base->ca[j] = ca;
200
+ ca_attach(ca);
201
+ }
202
+
203
+ data = malloc_with_check(sizeof(struct cmp_data)*elements);
204
+ for (i=0; i<elements; i++) {
205
+ data[i].i = i;
206
+ data[i].base = base;
207
+ }
208
+
209
+ #ifdef HAVE_MERGESORT
210
+ mergesort(data, elements, sizeof(struct cmp_data),
211
+ (int (*)(const void*,const void*)) qcmp_func);
212
+ #else
213
+ qsort(data, elements, sizeof(struct cmp_data),
214
+ (int (*)(const void*,const void*)) qcmp_func);
215
+ #endif
216
+
217
+ out = rb_ca_template_with_type(argv[0], INT2FIX(CA_INT32), INT2FIX(0));
218
+ Data_Get_Struct(out, CArray, co);
219
+ q = (int32_t *) co->ptr;
220
+
221
+ for (i=0; i<elements; i++) {
222
+ *q = data[i].i;
223
+ q++;
224
+ }
225
+
226
+ for (j=0; j<argc; j++) {
227
+ ca_detach(base->ca[j]);
228
+ }
229
+
230
+ free(data);
231
+ free(base->ca);
232
+ free(base);
233
+
234
+ return out;
235
+ }
236
+
237
+ /* rdoc:
238
+ class CArray
239
+ # returns index table for index sort
240
+ # This method same as,
241
+ #
242
+ # idx = CA.sort_addr(self, *args)
243
+ def sort_addr (*args)
244
+ end
245
+ end
246
+ */
247
+
248
+ static VALUE
249
+ rb_ca_sort_addr (int argc, VALUE *argv, VALUE self)
250
+ {
251
+ VALUE list = rb_ary_new4(argc, argv);
252
+ rb_ary_unshift(list, self);
253
+ return rb_apply(rb_mCA, rb_intern("sort_addr"), list);
254
+ }
255
+
256
+ void
257
+ Init_carray_sort_addr ()
258
+ {
259
+ rb_define_singleton_method(rb_mCA, "sort_addr", rb_ca_s_sort_addr, -1);
260
+ rb_define_method(rb_cCArray, "sort_addr", rb_ca_sort_addr, -1);
261
+ }
@@ -0,0 +1,2102 @@
1
+ /* ---------------------------------------------------------------------------
2
+
3
+ carray_stat.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 "ruby.h"
14
+ #include "carray.h"
15
+ #include <math.h>
16
+ #include <float.h>
17
+ #include <stdarg.h>
18
+
19
+ #define MIN(x,y) ((x) < (y) ? (x) : (y))
20
+ #define MAX(x,y) ((x) > (y) ? (x) : (y))
21
+
22
+ /* ----------------------------------------------------------------- */
23
+
24
+ #define proc_cummin(type, from, conv) \
25
+ { \
26
+ type *ptr = (type *) ca->ptr; \
27
+ type *q = (type *) co->ptr; \
28
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
29
+ boolean8_t *n = NULL; \
30
+ type fval = ( ! NIL_P(rfval) ) ? from(rfval) : (type)(0.0); \
31
+ type min = *ptr; \
32
+ type val; \
33
+ int32_t count = 0; \
34
+ int32_t i; \
35
+ if ( m ) { \
36
+ count = 0; \
37
+ ca_create_mask(co); \
38
+ n = (boolean8_t*) co->mask->ptr; \
39
+ for (i=ca->elements; i; i--, ptr++) { \
40
+ if ( ! *m++ ) { \
41
+ min = *ptr; \
42
+ break; \
43
+ } \
44
+ } \
45
+ ptr = (type *) ca->ptr; \
46
+ m = (boolean8_t*) ca->mask->ptr; \
47
+ count = 0; \
48
+ for (i=ca->elements; i; i--, ptr++, q++, m++, n++) { \
49
+ if ( ! *m ) { \
50
+ val = *ptr; \
51
+ if ( min > val ) { \
52
+ min = val; \
53
+ } \
54
+ } \
55
+ else { \
56
+ count++; \
57
+ } \
58
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
59
+ if ( NIL_P(rfval) ) { \
60
+ *n = 1; \
61
+ } \
62
+ else {\
63
+ *q = fval; \
64
+ }\
65
+ } \
66
+ else { \
67
+ *q = min; \
68
+ } \
69
+ } \
70
+ } \
71
+ else { \
72
+ for (i=ca->elements; i; i--, ptr++, q++) {\
73
+ val = *ptr; \
74
+ if ( min > val ) { \
75
+ min = val; \
76
+ } \
77
+ *q = min; \
78
+ } \
79
+ } \
80
+ }
81
+
82
+
83
+ static VALUE
84
+ rb_ca_cummin (int argc, VALUE *argv, VALUE self)
85
+ {
86
+ volatile VALUE rmin_count = Qnil, rfval = Qnil, obj;
87
+ CArray *ca, *co;
88
+ int min_count;
89
+
90
+ if ( argc > 0 ) {
91
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
92
+ }
93
+
94
+ Data_Get_Struct(self, CArray, ca);
95
+
96
+ co = ca_template(ca);
97
+ obj = ca_wrap_struct(co);
98
+
99
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
100
+ ca->elements - 1 : NUM2INT(rmin_count);
101
+
102
+ if ( min_count < 0 ) {
103
+ min_count += ca->elements;
104
+ }
105
+
106
+ ca_attach(ca);
107
+
108
+ switch ( ca->data_type ) {
109
+ case CA_BOOLEAN:
110
+ case CA_INT8: proc_cummin(int8_t, NUM2LONG,); break;
111
+ case CA_UINT8: proc_cummin(uint8_t, NUM2ULONG,); break;
112
+ case CA_INT16: proc_cummin(int16_t, NUM2LONG,); break;
113
+ case CA_UINT16: proc_cummin(uint16_t, NUM2ULONG,); break;
114
+ case CA_INT32: proc_cummin(int32_t, NUM2LONG,); break;
115
+ case CA_UINT32: proc_cummin(uint32_t, NUM2ULONG,); break;
116
+ case CA_INT64: proc_cummin(int64_t, NUM2LL,); break;
117
+ case CA_UINT64: proc_cummin(uint64_t, NUM2ULL,); break;
118
+ case CA_FLOAT32: proc_cummin(float32_t, NUM2DBL,); break;
119
+ case CA_FLOAT64: proc_cummin(float64_t, NUM2DBL,); break;
120
+ case CA_FLOAT128: proc_cummin(float128_t, NUM2DBL,); break;
121
+ case CA_OBJECT: proc_cummin(VALUE, NUM2DBL, NUM2DBL); break;
122
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
123
+ }
124
+
125
+ ca_detach(ca);
126
+
127
+ return obj;
128
+ }
129
+
130
+ /* ------------------------------------------------------------------- */
131
+
132
+ #define proc_cummax(type, from, conv) \
133
+ { \
134
+ type *ptr = (type *) ca->ptr; \
135
+ type *q = (type *) co->ptr; \
136
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
137
+ boolean8_t *n = NULL; \
138
+ type fval = ( ! NIL_P(rfval) ) ? from(rfval) : (type)(0.0); \
139
+ type max = *ptr; \
140
+ type val; \
141
+ int32_t count = 0; \
142
+ int32_t i; \
143
+ if ( m ) { \
144
+ count = 0; \
145
+ ca_create_mask(co); \
146
+ n = (boolean8_t*) co->mask->ptr; \
147
+ for (i=ca->elements; i; i--, ptr++) { \
148
+ if ( ! *m++ ) { \
149
+ max = *ptr; \
150
+ break; \
151
+ } \
152
+ } \
153
+ ptr = (type *) ca->ptr; \
154
+ m = (boolean8_t*) ca->mask->ptr; \
155
+ count = 0; \
156
+ for (i=ca->elements; i; i--, ptr++, q++, m++, n++) { \
157
+ if ( ! *m ) { \
158
+ val = *ptr; \
159
+ if ( max < val ) { \
160
+ max = val; \
161
+ } \
162
+ } \
163
+ else { \
164
+ count++; \
165
+ } \
166
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
167
+ if ( NIL_P(rfval) ) { \
168
+ *n = 1; \
169
+ } \
170
+ else {\
171
+ *q = fval; \
172
+ }\
173
+ } \
174
+ else { \
175
+ *q = max; \
176
+ } \
177
+ } \
178
+ } \
179
+ else { \
180
+ for (i=ca->elements; i; i--, ptr++, q++) {\
181
+ val = *ptr; \
182
+ if ( max < val ) { \
183
+ max = val; \
184
+ } \
185
+ *q = max; \
186
+ } \
187
+ } \
188
+ }
189
+
190
+ static VALUE
191
+ rb_ca_cummax (int argc, VALUE *argv, VALUE self)
192
+ {
193
+ volatile VALUE rmin_count = Qnil, rfval = Qnil, obj;
194
+ CArray *ca, *co;
195
+ int min_count;
196
+
197
+ if ( argc > 0 ) {
198
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
199
+ }
200
+
201
+ Data_Get_Struct(self, CArray, ca);
202
+
203
+ co = ca_template(ca);
204
+ obj = ca_wrap_struct(co);
205
+
206
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
207
+ ca->elements - 1 : NUM2INT(rmin_count);
208
+
209
+ if ( min_count < 0 ) {
210
+ min_count += ca->elements;
211
+ }
212
+
213
+ ca_attach(ca);
214
+
215
+ switch ( ca->data_type ) {
216
+ case CA_BOOLEAN:
217
+ case CA_INT8: proc_cummax(int8_t, NUM2LONG,); break;
218
+ case CA_UINT8: proc_cummax(uint8_t, NUM2ULONG,); break;
219
+ case CA_INT16: proc_cummax(int16_t, NUM2LONG,); break;
220
+ case CA_UINT16: proc_cummax(uint16_t, NUM2ULONG,); break;
221
+ case CA_INT32: proc_cummax(int32_t, NUM2LONG,); break;
222
+ case CA_UINT32: proc_cummax(uint32_t, NUM2ULONG,); break;
223
+ case CA_INT64: proc_cummax(int64_t, NUM2LL,); break;
224
+ case CA_UINT64: proc_cummax(uint64_t, NUM2ULL,); break;
225
+ case CA_FLOAT32: proc_cummax(float32_t, NUM2DBL,); break;
226
+ case CA_FLOAT64: proc_cummax(float64_t, NUM2DBL,); break;
227
+ case CA_FLOAT128: proc_cummax(float128_t, NUM2DBL,); break;
228
+ case CA_OBJECT: proc_cummax(VALUE, NUM2DBL, NUM2DBL); break;
229
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
230
+ }
231
+
232
+ ca_detach(ca);
233
+
234
+ return obj;
235
+ }
236
+
237
+
238
+ /* ------------------------------------------------------------------- */
239
+
240
+ #define proc_cumprod(type, atype, from, conv) \
241
+ { \
242
+ type *ptr = (type *) ca->ptr; \
243
+ atype *q = (atype *) co->ptr; \
244
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
245
+ boolean8_t *n = NULL; \
246
+ atype fval = ( ! NIL_P(rfval) ) ? from(rfval) : (atype)(0.0); \
247
+ atype prod = (atype)(1.0); \
248
+ int32_t count = 0; \
249
+ int32_t i; \
250
+ if ( m ) { \
251
+ count = 0; \
252
+ ca_create_mask(co); \
253
+ n = (boolean8_t*) co->mask->ptr; \
254
+ for (i=ca->elements; i; i--, ptr++, q++, m++, n++) { \
255
+ if ( ! *m ) { \
256
+ prod *= (atype)conv(*ptr); \
257
+ } \
258
+ else { \
259
+ count++; \
260
+ } \
261
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
262
+ if ( NIL_P(rfval) ) { \
263
+ *n = 1; \
264
+ } \
265
+ else {\
266
+ *q = fval; \
267
+ }\
268
+ } \
269
+ else { \
270
+ *q = prod; \
271
+ } \
272
+ } \
273
+ } \
274
+ else { \
275
+ for (i=ca->elements; i; i--, ptr++, q++) {\
276
+ prod *= (atype)conv(*ptr); \
277
+ *q = prod; \
278
+ } \
279
+ } \
280
+ }
281
+
282
+ static VALUE
283
+ rb_ca_cumprod (int argc, VALUE *argv, VALUE self)
284
+ {
285
+ volatile VALUE rmin_count = Qnil, rfval = Qnil;
286
+ CArray *ca, *co;
287
+ int min_count;
288
+
289
+ if ( argc > 0 ) {
290
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
291
+ }
292
+
293
+ Data_Get_Struct(self, CArray, ca);
294
+
295
+ if ( ca_is_complex_type(ca) ) {
296
+ co = carray_new(CA_CMPLX128, ca->rank, ca->dim, 0, NULL);
297
+ }
298
+ else {
299
+ co = carray_new(CA_FLOAT64, ca->rank, ca->dim, 0, NULL);
300
+ }
301
+
302
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
303
+ ca->elements - 1 : NUM2INT(rmin_count);
304
+
305
+ if ( min_count < 0 ) {
306
+ min_count += ca->elements;
307
+ }
308
+
309
+ ca_attach(ca);
310
+
311
+ switch ( ca->data_type ) {
312
+ case CA_BOOLEAN:
313
+ case CA_INT8: proc_cumprod(int8_t, double, NUM2DBL,); break;
314
+ case CA_UINT8: proc_cumprod(uint8_t, double, NUM2DBL,); break;
315
+ case CA_INT16: proc_cumprod(int16_t, double, NUM2DBL,); break;
316
+ case CA_UINT16: proc_cumprod(uint16_t, double, NUM2DBL,); break;
317
+ case CA_INT32: proc_cumprod(int32_t, double, NUM2DBL,); break;
318
+ case CA_UINT32: proc_cumprod(uint32_t, double, NUM2DBL,); break;
319
+ case CA_INT64: proc_cumprod(int64_t, double, NUM2DBL,); break;
320
+ case CA_UINT64: proc_cumprod(uint64_t, double, NUM2DBL,); break;
321
+ case CA_FLOAT32: proc_cumprod(float32_t, double, NUM2DBL,); break;
322
+ case CA_FLOAT64: proc_cumprod(float64_t, double, NUM2DBL,); break;
323
+ case CA_FLOAT128: proc_cumprod(float128_t, double, NUM2DBL,); break;
324
+ #ifdef HAVE_COMPLEX_H
325
+ case CA_CMPLX64: proc_cumprod(cmplx64_t, cmplx128_t, NUM2CC,); break;
326
+ case CA_CMPLX128: proc_cumprod(cmplx128_t, cmplx128_t, NUM2CC,); break;
327
+ case CA_CMPLX256: proc_cumprod(cmplx256_t, cmplx128_t, NUM2CC,); break;
328
+ #endif
329
+ case CA_OBJECT: proc_cumprod(VALUE, double, NUM2DBL, NUM2DBL); break;
330
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
331
+ }
332
+
333
+ ca_detach(ca);
334
+
335
+ return ca_wrap_struct(co);
336
+ }
337
+
338
+
339
+ /* ----------------------------------------------------------------- */
340
+
341
+ #define proc_wsum(type, atype, conv, to) \
342
+ { \
343
+ type *p1 = (type*)ca->ptr; \
344
+ type *p2; \
345
+ int s2; \
346
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
347
+ atype sum = 0.0; \
348
+ int32_t count = 0; \
349
+ int32_t i; \
350
+ ca_set_iterator(1, cw, &p2, &s2); \
351
+ if ( m ) { \
352
+ count = 0; \
353
+ for (i=ca->elements; i; i--, p1++, p2+=s2) { \
354
+ if ( ! *m++ ) { \
355
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
356
+ } \
357
+ else { \
358
+ count++; \
359
+ } \
360
+ } \
361
+ } \
362
+ else { \
363
+ for (i=ca->elements; i; i--, p1++, p2+=s2) { \
364
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
365
+ } \
366
+ } \
367
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
368
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval;\
369
+ } \
370
+ else { \
371
+ out = to(sum); \
372
+ } \
373
+ }
374
+
375
+ static VALUE
376
+ rb_ca_wsum (int argc, VALUE *argv, VALUE self)
377
+ {
378
+ volatile VALUE out, weight = argv[0], rmin_count = Qnil, rfval = Qnil, tmp;
379
+ CArray *ca, *cw;
380
+ int min_count;
381
+
382
+ if ( argc > 1 ) {
383
+ rb_scan_args(argc, argv, "12", &weight, &rmin_count, &rfval);
384
+ }
385
+
386
+ Data_Get_Struct(self, CArray, ca);
387
+ cw = ca_wrap_readonly(weight, ca->data_type);
388
+
389
+ ca_check_same_elements(ca, cw);
390
+
391
+ if ( ca->elements == 0 ) {
392
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
393
+ }
394
+
395
+ if ( ca_has_mask(cw) ) {
396
+ ca = ca_copy(ca);
397
+ tmp = ca_wrap_struct(ca);
398
+ ca_copy_mask_overlay(ca, ca->elements, 1, cw);
399
+ }
400
+
401
+ min_count = ( NIL_P(rmin_count) || ( ! ca_has_mask(ca) ) ) ?
402
+ ca->elements - 1 : NUM2INT(rmin_count);
403
+
404
+ if ( min_count < 0 ) {
405
+ min_count += ca->elements;
406
+ }
407
+
408
+ ca_attach_n(2, ca, cw);
409
+
410
+ switch ( ca->data_type ) {
411
+ case CA_BOOLEAN:
412
+ case CA_INT8: proc_wsum(int8_t, double,,rb_float_new); break;
413
+ case CA_UINT8: proc_wsum(uint8_t,double,,rb_float_new); break;
414
+ case CA_INT16: proc_wsum(int16_t,double,,rb_float_new); break;
415
+ case CA_UINT16: proc_wsum(uint16_t,double,,rb_float_new); break;
416
+ case CA_INT32: proc_wsum(int32_t,double,,rb_float_new); break;
417
+ case CA_UINT32: proc_wsum(uint32_t,double,,rb_float_new); break;
418
+ case CA_INT64: proc_wsum(int64_t,double,,rb_float_new); break;
419
+ case CA_UINT64: proc_wsum(uint64_t,double,,rb_float_new); break;
420
+ case CA_FLOAT32: proc_wsum(float32_t,double,,rb_float_new); break;
421
+ case CA_FLOAT64: proc_wsum(float64_t,double,,rb_float_new); break;
422
+ case CA_FLOAT128: proc_wsum(float128_t,double,,rb_float_new); break;
423
+ #ifdef HAVE_COMPLEX_H
424
+ case CA_CMPLX64: proc_wsum(cmplx64_t,cmplx128_t,,rb_ccomplex_new); break;
425
+ case CA_CMPLX128: proc_wsum(cmplx128_t,cmplx128_t,,rb_ccomplex_new); break;
426
+ case CA_CMPLX256: proc_wsum(cmplx256_t,cmplx128_t,,rb_ccomplex_new); break;
427
+ #endif
428
+ case CA_OBJECT: proc_wsum(VALUE,double,NUM2DBL,rb_float_new); break;
429
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
430
+ }
431
+
432
+ ca_detach_n(2, ca, cw);
433
+
434
+ return out;
435
+ }
436
+
437
+ /* ------------------------------------------------------------------- */
438
+
439
+ #define proc_cumwsum(type, atype, from, conv) \
440
+ { \
441
+ type *p1 = (type *) ca->ptr; \
442
+ type *p2; \
443
+ int s2; \
444
+ atype *q = (atype *) co->ptr; \
445
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
446
+ boolean8_t *n = NULL; \
447
+ atype fval = ( ! NIL_P(rfval) ) ? from(rfval) : (atype)(0.0); \
448
+ atype sum = 0.0; \
449
+ int32_t count = 0; \
450
+ int32_t i; \
451
+ ca_set_iterator(1, cw, &p2, &s2); \
452
+ if ( m ) { \
453
+ count = 0; \
454
+ ca_create_mask(co); \
455
+ n = (boolean8_t*) co->mask->ptr; \
456
+ for (i=ca->elements; i; i--, p1++, p2+=s2, q++, m++, n++) {\
457
+ if ( ! *m ) { \
458
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
459
+ } \
460
+ else { \
461
+ count++; \
462
+ } \
463
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
464
+ if ( NIL_P(rfval) ) { \
465
+ *n = 1; \
466
+ } \
467
+ else {\
468
+ *q = fval; \
469
+ }\
470
+ } \
471
+ else { \
472
+ *q = sum; \
473
+ } \
474
+ } \
475
+ } \
476
+ else { \
477
+ for (i=ca->elements; i; i--, p1++, p2+=s2, q++) { \
478
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
479
+ *q = sum; \
480
+ } \
481
+ } \
482
+ }
483
+
484
+ static VALUE
485
+ rb_ca_cumwsum (int argc, VALUE *argv, VALUE self)
486
+ {
487
+ volatile VALUE weight = argv[0], rmin_count = Qnil, rfval = Qnil, tmp;
488
+ CArray *ca, *cw, *co;
489
+ int min_count;
490
+
491
+ if ( argc > 1 ) {
492
+ rb_scan_args(argc, argv, "12", &weight, &rmin_count, &rfval);
493
+ }
494
+
495
+ Data_Get_Struct(self, CArray, ca);
496
+ cw = ca_wrap_readonly(weight, ca->data_type);
497
+
498
+ ca_check_same_elements(ca, cw);
499
+
500
+ if ( ca_has_mask(cw) ) {
501
+ ca = ca_copy(ca);
502
+ tmp = ca_wrap_struct(ca);
503
+ ca_copy_mask_overlay(ca, ca->elements, 1, cw);
504
+ }
505
+
506
+ if ( ca_is_complex_type(ca) ) {
507
+ co = carray_new(CA_CMPLX128, ca->rank, ca->dim, 0, NULL);
508
+ }
509
+ else {
510
+ co = carray_new(CA_FLOAT64, ca->rank, ca->dim, 0, NULL);
511
+ }
512
+
513
+ min_count = ( NIL_P(rmin_count) || ( ! ca_has_mask(ca) ) ) ?
514
+ ca->elements - 1 : NUM2INT(rmin_count);
515
+
516
+ if ( min_count < 0 ) {
517
+ min_count += ca->elements;
518
+ }
519
+
520
+ ca_attach(ca);
521
+
522
+ switch ( ca->data_type ) {
523
+ case CA_BOOLEAN:
524
+ case CA_INT8: proc_cumwsum(int8_t, double, NUM2DBL,); break;
525
+ case CA_UINT8: proc_cumwsum(uint8_t, double, NUM2DBL,); break;
526
+ case CA_INT16: proc_cumwsum(int16_t, double, NUM2DBL,); break;
527
+ case CA_UINT16: proc_cumwsum(uint16_t, double, NUM2DBL,); break;
528
+ case CA_INT32: proc_cumwsum(int32_t, double, NUM2DBL,); break;
529
+ case CA_UINT32: proc_cumwsum(uint32_t, double, NUM2DBL,); break;
530
+ case CA_INT64: proc_cumwsum(int64_t, double, NUM2DBL,); break;
531
+ case CA_UINT64: proc_cumwsum(uint64_t, double, NUM2DBL,); break;
532
+ case CA_FLOAT32: proc_cumwsum(float32_t, double, NUM2DBL,); break;
533
+ case CA_FLOAT64: proc_cumwsum(float64_t, double, NUM2DBL,); break;
534
+ case CA_FLOAT128: proc_cumwsum(float128_t, double, NUM2DBL,); break;
535
+ #ifdef HAVE_COMPLEX_H
536
+ case CA_CMPLX64: proc_cumwsum(cmplx64_t, cmplx128_t, NUM2CC,); break;
537
+ case CA_CMPLX128: proc_cumwsum(cmplx128_t, cmplx128_t, NUM2CC,); break;
538
+ case CA_CMPLX256: proc_cumwsum(cmplx256_t, cmplx128_t, NUM2CC,); break;
539
+ #endif
540
+ case CA_OBJECT: proc_cumwsum(VALUE, double, NUM2DBL, NUM2DBL); break;
541
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
542
+ }
543
+
544
+ ca_detach(ca);
545
+
546
+ return ca_wrap_struct(co);
547
+ }
548
+
549
+ /* ----------------------------------------------------------------- */
550
+
551
+ #define proc_wmean(type, atype, conv, to) \
552
+ { \
553
+ type *p1 = (type*)ca->ptr; \
554
+ type *p2 = (type*)cw->ptr; \
555
+ int s2; \
556
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
557
+ atype sum = 0.0; \
558
+ atype den = 0.0; \
559
+ atype ave; \
560
+ int32_t count = 0; \
561
+ int32_t i; \
562
+ ca_set_iterator(1, cw, &p2, &s2); \
563
+ if ( m ) { \
564
+ count = 0; \
565
+ for (i=ca->elements; i; i--, p1++, p2+=s2) { \
566
+ if ( ! *m++ ) { \
567
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
568
+ den += (atype)conv(*p2); \
569
+ } \
570
+ else { \
571
+ count++; \
572
+ } \
573
+ } \
574
+ } \
575
+ else { \
576
+ for (i=ca->elements; i; i--, p1++, p2+=s2) { \
577
+ sum += (atype)conv(*p1) * (atype)conv(*p2); \
578
+ den += (atype)conv(*p2); \
579
+ } \
580
+ } \
581
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) \
582
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
583
+ else { \
584
+ ave = sum / den; \
585
+ out = to(ave); \
586
+ } \
587
+ }
588
+
589
+ static VALUE
590
+ rb_ca_wmean (int argc, VALUE *argv, VALUE self)
591
+ {
592
+ volatile VALUE out, weight = argv[0], rmin_count = Qnil, rfval = Qnil, tmp;
593
+ CArray *ca, *cw;
594
+ int min_count;
595
+
596
+ if ( argc > 1 ) {
597
+ rb_scan_args(argc, argv, "12", &weight, &rmin_count, &rfval);
598
+ }
599
+
600
+ Data_Get_Struct(self, CArray, ca);
601
+ cw = ca_wrap_readonly(weight, ca->data_type);
602
+
603
+ ca_check_same_elements(ca, cw);
604
+
605
+ if ( ca->elements == 0 ) {
606
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
607
+ }
608
+
609
+ if ( ca_has_mask(cw) ) {
610
+ ca = ca_copy(ca);
611
+ tmp = ca_wrap_struct(ca);
612
+ ca_copy_mask_overlay(ca, ca->elements, 1, cw);
613
+ }
614
+
615
+ min_count = ( NIL_P(rmin_count) || ( ! ca_has_mask(ca) ) ) ?
616
+ ca->elements - 1 : NUM2INT(rmin_count);
617
+
618
+ if ( min_count < 0 ) {
619
+ min_count += ca->elements;
620
+ }
621
+
622
+ ca_attach_n(2, ca, cw);
623
+
624
+ switch ( ca->data_type ) {
625
+ case CA_BOOLEAN:
626
+ case CA_INT8: proc_wmean(int8_t, double,,rb_float_new); break;
627
+ case CA_UINT8: proc_wmean(uint8_t,double,,rb_float_new); break;
628
+ case CA_INT16: proc_wmean(int16_t,double,,rb_float_new); break;
629
+ case CA_UINT16: proc_wmean(uint16_t,double,,rb_float_new); break;
630
+ case CA_INT32: proc_wmean(int32_t,double,,rb_float_new); break;
631
+ case CA_UINT32: proc_wmean(uint32_t,double,,rb_float_new); break;
632
+ case CA_INT64: proc_wmean(int64_t,double,,rb_float_new); break;
633
+ case CA_UINT64: proc_wmean(uint64_t,double,,rb_float_new); break;
634
+ case CA_FLOAT32: proc_wmean(float32_t,double,,rb_float_new); break;
635
+ case CA_FLOAT64: proc_wmean(float64_t,double,,rb_float_new); break;
636
+ case CA_FLOAT128: proc_wmean(float128_t,double,,rb_float_new); break;
637
+ #ifdef HAVE_COMPLEX_H
638
+ case CA_CMPLX64: proc_wmean(cmplx64_t,cmplx128_t,,rb_ccomplex_new); break;
639
+ case CA_CMPLX128: proc_wmean(cmplx128_t,cmplx128_t,,rb_ccomplex_new); break;
640
+ case CA_CMPLX256: proc_wmean(cmplx256_t,cmplx128_t,,rb_ccomplex_new); break;
641
+ #endif
642
+ case CA_OBJECT: proc_wmean(VALUE,double,NUM2DBL,rb_float_new); break;
643
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
644
+ }
645
+
646
+ ca_detach_n(2, ca, cw);
647
+
648
+ return out;
649
+ }
650
+
651
+ /* ----------------------------------------------------------------- */
652
+
653
+ #define proc_variancep(type,from) \
654
+ { \
655
+ type *ptr = (type *) ca->ptr; \
656
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
657
+ double sum = 0.0; \
658
+ double sum2 = 0.0; \
659
+ double del, var, ave; \
660
+ int32_t count = 0; \
661
+ int32_t nvalid; \
662
+ int32_t i; \
663
+ if ( m ) { \
664
+ count = 0; \
665
+ for (i=ca->elements; i; i--, ptr++) { \
666
+ if ( ! *m++ ) { \
667
+ sum += (double)from(*ptr); \
668
+ } \
669
+ else { \
670
+ count++; \
671
+ } \
672
+ } \
673
+ nvalid = ca->elements - count; \
674
+ } \
675
+ else { \
676
+ for (i=ca->elements; i; i--, ptr++) { \
677
+ sum += (double)from(*ptr); \
678
+ } \
679
+ nvalid = ca->elements; \
680
+ } \
681
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
682
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
683
+ break; \
684
+ } \
685
+ ave = sum / ((double) nvalid); \
686
+ ptr = (type *) ca->ptr; \
687
+ m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
688
+ if ( m ) { \
689
+ for (i=ca->elements; i; i--, ptr++) { \
690
+ if ( ! *m++ ) { \
691
+ del = ((double)from(*ptr)) - ave; \
692
+ sum2 += del*del; \
693
+ } \
694
+ } \
695
+ } \
696
+ else { \
697
+ for (i=ca->elements; i; i--, ptr++) { \
698
+ del = ((double)from(*ptr)) - ave; \
699
+ sum2 += del*del; \
700
+ } \
701
+ } \
702
+ var = sum2 / ((double) nvalid); \
703
+ out = rb_float_new(var); \
704
+ }
705
+
706
+ static VALUE
707
+ rb_ca_variancep (int argc, VALUE *argv, VALUE self)
708
+ {
709
+ volatile VALUE out, rmin_count = Qnil, rfval = Qnil;
710
+ CArray *ca;
711
+ int min_count;
712
+
713
+ if ( argc > 0 ) {
714
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
715
+ }
716
+
717
+ Data_Get_Struct(self, CArray, ca);
718
+
719
+ if ( ca->elements == 0 ) {
720
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
721
+ }
722
+
723
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
724
+ ca->elements - 1 : NUM2INT(rmin_count);
725
+
726
+ if ( min_count < 0 ) {
727
+ min_count += ca->elements;
728
+ }
729
+
730
+ ca_attach(ca);
731
+
732
+ switch ( ca->data_type ) {
733
+ case CA_BOOLEAN:
734
+ case CA_INT8: proc_variancep(int8_t,); break;
735
+ case CA_UINT8: proc_variancep(uint8_t,); break;
736
+ case CA_INT16: proc_variancep(int16_t,); break;
737
+ case CA_UINT16: proc_variancep(uint16_t,); break;
738
+ case CA_INT32: proc_variancep(int32_t,); break;
739
+ case CA_UINT32: proc_variancep(uint32_t,); break;
740
+ case CA_INT64: proc_variancep(int64_t,); break;
741
+ case CA_UINT64: proc_variancep(uint64_t,); break;
742
+ case CA_FLOAT32: proc_variancep(float32_t,); break;
743
+ case CA_FLOAT64: proc_variancep(float64_t,); break;
744
+ case CA_FLOAT128: proc_variancep(float128_t,); break;
745
+ case CA_OBJECT: proc_variancep(VALUE,NUM2DBL); break;
746
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
747
+ }
748
+
749
+ ca_detach(ca);
750
+
751
+ return out;
752
+ }
753
+
754
+ /* ----------------------------------------------------------------- */
755
+
756
+ #define proc_variance(type,from) \
757
+ { \
758
+ type *ptr = (type *) ca->ptr; \
759
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
760
+ double sum = 0.0; \
761
+ double sum2 = 0.0; \
762
+ double del, var, ave; \
763
+ int32_t count = 0; \
764
+ int32_t nvalid; \
765
+ int32_t i; \
766
+ if ( m ) { \
767
+ count = 0; \
768
+ for (i=ca->elements; i; i--, ptr++) { \
769
+ if ( ! *m++ ) { \
770
+ sum += (double)from(*ptr); \
771
+ } \
772
+ else { \
773
+ count++; \
774
+ } \
775
+ } \
776
+ nvalid = ca->elements - count; \
777
+ } \
778
+ else { \
779
+ for (i=ca->elements; i; i--, ptr++) { \
780
+ sum += (double)from(*ptr); \
781
+ } \
782
+ nvalid = ca->elements; \
783
+ } \
784
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
785
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
786
+ break; \
787
+ } \
788
+ ave = sum / ((double) nvalid); \
789
+ ptr = (type *) ca->ptr; \
790
+ m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
791
+ if ( m ) { \
792
+ for (i=ca->elements; i; i--, ptr++) { \
793
+ if ( ! *m++ ) { \
794
+ del = ((double)from(*ptr)) - ave; \
795
+ sum2 += del*del; \
796
+ } \
797
+ } \
798
+ } \
799
+ else { \
800
+ for (i=ca->elements; i; i--, ptr++) { \
801
+ del = ((double)from(*ptr)) - ave; \
802
+ sum2 += del*del; \
803
+ } \
804
+ } \
805
+ var = sum2 / ((double) nvalid - 1); \
806
+ out = rb_float_new(var); \
807
+ }
808
+
809
+ static VALUE
810
+ rb_ca_variance (int argc, VALUE *argv, VALUE self)
811
+ {
812
+ volatile VALUE out, rmin_count = Qnil, rfval = Qnil;
813
+ CArray *ca;
814
+ int min_count;
815
+
816
+ if ( argc > 0 ) {
817
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
818
+ }
819
+
820
+ Data_Get_Struct(self, CArray, ca);
821
+
822
+ if ( ca->elements == 0 ) {
823
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
824
+ }
825
+
826
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
827
+ ca->elements - 1 : NUM2INT(rmin_count);
828
+
829
+ if ( min_count < 0 ) {
830
+ min_count += ca->elements;
831
+ }
832
+
833
+ ca_attach(ca);
834
+
835
+ switch ( ca->data_type ) {
836
+ case CA_BOOLEAN:
837
+ case CA_INT8: proc_variance(int8_t,); break;
838
+ case CA_UINT8: proc_variance(uint8_t,); break;
839
+ case CA_INT16: proc_variance(int16_t,); break;
840
+ case CA_UINT16: proc_variance(uint16_t,); break;
841
+ case CA_INT32: proc_variance(int32_t,); break;
842
+ case CA_UINT32: proc_variance(uint32_t,); break;
843
+ case CA_INT64: proc_variance(int64_t,); break;
844
+ case CA_UINT64: proc_variance(uint64_t,); break;
845
+ case CA_FLOAT32: proc_variance(float32_t,); break;
846
+ case CA_FLOAT64: proc_variance(float64_t,); break;
847
+ case CA_FLOAT128: proc_variance(float128_t,); break;
848
+ case CA_OBJECT: proc_variance(VALUE,NUM2DBL); break;
849
+ default: rb_raise(rb_eRuntimeError, "invalid data type");
850
+ }
851
+
852
+ ca_detach(ca);
853
+
854
+ return out;
855
+ }
856
+
857
+ static VALUE
858
+ rb_ca_count_true (int argc, VALUE *argv, VALUE self)
859
+ {
860
+ volatile VALUE out, rmin_count = Qnil, rfval = Qnil;
861
+ CArray *ca;
862
+ int min_count;
863
+
864
+ if ( argc > 1 ) {
865
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
866
+ }
867
+
868
+ Data_Get_Struct(self, CArray, ca);
869
+
870
+ if ( ! ca_is_boolean_type(ca) ) {
871
+ rb_raise(rb_eCADataTypeError,
872
+ "data_type should be CA_BOOLEAN for this method");
873
+ }
874
+
875
+ if ( ca->elements == 0 ) {
876
+ return INT2NUM(0);
877
+ }
878
+
879
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
880
+ ca->elements - 1 : NUM2INT(rmin_count);
881
+
882
+ if ( min_count < 0 ) {
883
+ min_count += ca->elements;
884
+ }
885
+
886
+ ca_attach(ca);
887
+
888
+ {
889
+ boolean8_t *ptr = (boolean8_t *) ca->ptr;
890
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL;
891
+ int32_t count = 0;
892
+ int32_t value_count = 0;
893
+ int32_t i;
894
+ if ( m ) {
895
+ for (i=0; i<ca->elements; i++) {
896
+ if ( *m ) {
897
+ count++;
898
+ }
899
+ else if ( *ptr ) {
900
+ value_count++;
901
+ }
902
+ ptr++; m++;
903
+ }
904
+ }
905
+ else {
906
+ for (i=0; i<ca->elements; i++) {
907
+ if ( *ptr ) {
908
+ value_count++;
909
+ }
910
+ ptr++;
911
+ }
912
+ }
913
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) {
914
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
915
+ }
916
+ else {
917
+ out = LONG2NUM(value_count);
918
+ }
919
+ }
920
+
921
+ ca_detach(ca);
922
+
923
+ return out;
924
+ }
925
+
926
+ static VALUE
927
+ rb_ca_count_false (int argc, VALUE *argv, VALUE self)
928
+ {
929
+ volatile VALUE out, rmin_count = Qnil, rfval = Qnil;
930
+ CArray *ca;
931
+ int min_count;
932
+
933
+ if ( argc > 1 ) {
934
+ rb_scan_args(argc, argv, "02", &rmin_count, &rfval);
935
+ }
936
+
937
+ Data_Get_Struct(self, CArray, ca);
938
+
939
+ if ( ! ca_is_boolean_type(ca) ) {
940
+ rb_raise(rb_eCADataTypeError,
941
+ "data_type should be CA_BOOLEAN for this method");
942
+ }
943
+
944
+ if ( ca->elements == 0 ) {
945
+ return INT2NUM(0);
946
+ }
947
+
948
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
949
+ ca->elements - 1 : NUM2INT(rmin_count);
950
+
951
+ if ( min_count < 0 ) {
952
+ min_count += ca->elements;
953
+ }
954
+
955
+ ca_attach(ca);
956
+
957
+ {
958
+ boolean8_t *ptr = (boolean8_t *) ca->ptr;
959
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL;
960
+ int32_t count = 0;
961
+ int32_t value_count = 0;
962
+ int32_t i;
963
+ if ( m ) {
964
+ for (i=0; i<ca->elements; i++) {
965
+ if ( *m ) {
966
+ count++;
967
+ }
968
+ else if ( !(*ptr) ) {
969
+ value_count++;
970
+ }
971
+ ptr++; m++;
972
+ }
973
+ }
974
+ else {
975
+ for (i=0; i<ca->elements; i++) {
976
+ if ( !(*ptr) ) {
977
+ value_count++;
978
+ }
979
+ ptr++;
980
+ }
981
+ }
982
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) {
983
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
984
+ }
985
+ else {
986
+ out = LONG2NUM(value_count);
987
+ }
988
+ }
989
+
990
+ ca_detach(ca);
991
+
992
+ return out;
993
+ }
994
+
995
+ /* ----------------------------------------------------------------- */
996
+
997
+ #define proc_count_equal(type,from) \
998
+ { \
999
+ type *ptr = (type *) ca->ptr; \
1000
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1001
+ type val = (type) from(value); \
1002
+ int32_t count = 0; \
1003
+ int32_t value_count = 0; \
1004
+ int32_t i; \
1005
+ if ( m ) { \
1006
+ for (i=ca->elements; i; i--, ptr++) { \
1007
+ if ( ! *m++ ) { \
1008
+ if (*ptr == val ) { \
1009
+ value_count++; \
1010
+ } \
1011
+ } \
1012
+ else { \
1013
+ count++; \
1014
+ } \
1015
+ } \
1016
+ } \
1017
+ else { \
1018
+ for (i=ca->elements; i; i--, ptr++) { \
1019
+ if ( *ptr == val ) { \
1020
+ value_count++; \
1021
+ } \
1022
+ } \
1023
+ } \
1024
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
1025
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
1026
+ } \
1027
+ else { \
1028
+ out = LONG2NUM(value_count); \
1029
+ } \
1030
+ }
1031
+
1032
+ #define proc_count_equal_data() \
1033
+ { \
1034
+ char *ptr = ca->ptr; \
1035
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1036
+ char *val = ALLOCA_N(char, ca->bytes); \
1037
+ int32_t count = 0; \
1038
+ int32_t value_count = 0; \
1039
+ int32_t i; \
1040
+ rb_ca_obj2ptr(self, value, val); \
1041
+ if ( m ) { \
1042
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) {\
1043
+ if ( ! *m++ ) { \
1044
+ if ( !memcmp(ptr, val, ca->bytes) ) { \
1045
+ value_count++; \
1046
+ } \
1047
+ } \
1048
+ else { \
1049
+ count++; \
1050
+ } \
1051
+ } \
1052
+ } \
1053
+ else { \
1054
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) { \
1055
+ if ( !memcmp(ptr, val, ca->bytes) ) { \
1056
+ value_count++; \
1057
+ } \
1058
+ } \
1059
+ } \
1060
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
1061
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
1062
+ } \
1063
+ else { \
1064
+ out = LONG2NUM(value_count); \
1065
+ } \
1066
+ }
1067
+
1068
+ #define proc_count_equal_object() \
1069
+ { \
1070
+ VALUE *ptr = (VALUE *)ca->ptr; \
1071
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1072
+ VALUE val = value; \
1073
+ int32_t count = 0; \
1074
+ int32_t value_count = 0; \
1075
+ int32_t i; \
1076
+ if ( m ) { \
1077
+ for (i=ca->elements; i; i--) {\
1078
+ if ( ! *m++ ) { \
1079
+ if ( rb_equal(*ptr, val) ) { \
1080
+ value_count++; \
1081
+ } \
1082
+ } \
1083
+ else { \
1084
+ count++; \
1085
+ } \
1086
+ ptr++; \
1087
+ } \
1088
+ } \
1089
+ else { \
1090
+ for (i=ca->elements; i; i--) { \
1091
+ if ( rb_equal(*ptr, val) ) { \
1092
+ value_count++; \
1093
+ } \
1094
+ ptr++; \
1095
+ } \
1096
+ } \
1097
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
1098
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
1099
+ } \
1100
+ else { \
1101
+ out = LONG2NUM(value_count); \
1102
+ } \
1103
+ }
1104
+
1105
+ static VALUE
1106
+ rb_ca_count_equal (int argc, VALUE *argv, VALUE self)
1107
+ {
1108
+ volatile VALUE out, value, rmin_count = Qnil, rfval = Qnil;
1109
+ CArray *ca;
1110
+ int min_count;
1111
+
1112
+ rb_scan_args(argc, argv, "12", &value, &rmin_count, &rfval);
1113
+
1114
+ Data_Get_Struct(self, CArray, ca);
1115
+
1116
+ if ( ca->elements == 0 ) {
1117
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
1118
+ }
1119
+
1120
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
1121
+ ca->elements - 1 : NUM2INT(rmin_count);
1122
+
1123
+ if ( min_count < 0 ) {
1124
+ min_count += ca->elements;
1125
+ }
1126
+
1127
+ ca_attach(ca);
1128
+
1129
+ switch ( ca->data_type ) {
1130
+ case CA_FIXLEN: proc_count_equal_data(); break;
1131
+ case CA_BOOLEAN:
1132
+ case CA_INT8: proc_count_equal(int8_t,NUM2LONG); break;
1133
+ case CA_UINT8: proc_count_equal(uint8_t,NUM2ULONG); break;
1134
+ case CA_INT16: proc_count_equal(int16_t,NUM2LONG); break;
1135
+ case CA_UINT16: proc_count_equal(uint16_t,NUM2ULONG); break;
1136
+ case CA_INT32: proc_count_equal(int32_t,NUM2LONG); break;
1137
+ case CA_UINT32: proc_count_equal(uint32_t,NUM2LONG); break;
1138
+ case CA_INT64: proc_count_equal(int64_t,NUM2LL); break;
1139
+ case CA_UINT64: proc_count_equal(uint64_t,NUM2LL); break;
1140
+ case CA_FLOAT32: proc_count_equal(float32_t,NUM2DBL); break;
1141
+ case CA_FLOAT64: proc_count_equal(float64_t,NUM2DBL); break;
1142
+ case CA_FLOAT128: proc_count_equal(float128_t,NUM2DBL); break;
1143
+ #ifdef HAVE_COMPLEX_H
1144
+ case CA_CMPLX64: proc_count_equal(cmplx64_t,NUM2CC); break;
1145
+ case CA_CMPLX128: proc_count_equal(cmplx128_t,NUM2CC); break;
1146
+ case CA_CMPLX256: proc_count_equal(cmplx256_t,NUM2CC); break;
1147
+ #endif
1148
+ case CA_OBJECT: proc_count_equal_object(); break;
1149
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1150
+ }
1151
+
1152
+ ca_detach(ca);
1153
+
1154
+ return out;
1155
+ }
1156
+
1157
+ /* ----------------------------------------------------------------- */
1158
+
1159
+ #define proc_count_equiv(type,from,nabs) \
1160
+ { \
1161
+ type *ptr = (type *) ca->ptr; \
1162
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1163
+ type val = (type) from(value); \
1164
+ double rtol = fabs(NUM2DBL(reps)); \
1165
+ double vabs = nabs(val); \
1166
+ int32_t count = 0; \
1167
+ int32_t value_count = 0; \
1168
+ int32_t i; \
1169
+ if ( m ) { \
1170
+ for (i=ca->elements; i; i--, ptr++) { \
1171
+ if ( ! *m++ ) { \
1172
+ if ( *ptr == val || \
1173
+ nabs(*ptr - val)/(MAX(nabs(*ptr), vabs)) <= rtol )\
1174
+ value_count++; \
1175
+ } \
1176
+ else { \
1177
+ count++; \
1178
+ } \
1179
+ } \
1180
+ } \
1181
+ else { \
1182
+ for (i=ca->elements; i; i--, ptr++) { \
1183
+ if ( *ptr == val || \
1184
+ nabs(*ptr - val)/MAX(nabs(*ptr), vabs) <= rtol ) { \
1185
+ value_count++; \
1186
+ } \
1187
+ } \
1188
+ } \
1189
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
1190
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
1191
+ } \
1192
+ else { \
1193
+ out = LONG2NUM(value_count); \
1194
+ } \
1195
+ }
1196
+
1197
+ static VALUE
1198
+ rb_ca_count_equiv (int argc, VALUE *argv, VALUE self)
1199
+ {
1200
+ volatile VALUE out, value = argv[0], reps = argv[1],
1201
+ rmin_count = Qnil, rfval = Qnil;
1202
+ CArray *ca;
1203
+ int min_count;
1204
+
1205
+ if ( argc > 2 ) {
1206
+ rb_scan_args(argc, argv, "22", &value, &reps, &rmin_count, &rfval);
1207
+ }
1208
+
1209
+ Data_Get_Struct(self, CArray, ca);
1210
+
1211
+ if ( ca->elements == 0 ) {
1212
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
1213
+ }
1214
+
1215
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
1216
+ ca->elements - 1 : NUM2INT(rmin_count);
1217
+
1218
+ if ( min_count < 0 ) {
1219
+ min_count += ca->elements;
1220
+ }
1221
+
1222
+ ca_attach(ca);
1223
+
1224
+ switch ( ca->data_type ) {
1225
+ case CA_BOOLEAN:
1226
+ case CA_INT8: proc_count_equiv(int8_t,NUM2LONG,fabs); break;
1227
+ case CA_UINT8: proc_count_equiv(uint8_t,NUM2ULONG,fabs); break;
1228
+ case CA_INT16: proc_count_equiv(int16_t,NUM2LONG,fabs); break;
1229
+ case CA_UINT16: proc_count_equiv(uint16_t,NUM2ULONG,fabs); break;
1230
+ case CA_INT32: proc_count_equiv(int32_t,NUM2LONG,fabs); break;
1231
+ case CA_UINT32: proc_count_equiv(uint32_t,NUM2LONG,fabs); break;
1232
+ case CA_INT64: proc_count_equiv(int64_t,NUM2LL,fabs); break;
1233
+ case CA_UINT64: proc_count_equiv(uint64_t,NUM2LL,fabs); break;
1234
+ case CA_FLOAT32: proc_count_equiv(float32_t,NUM2DBL,fabs); break;
1235
+ case CA_FLOAT64: proc_count_equiv(float64_t,NUM2DBL,fabs); break;
1236
+ case CA_FLOAT128: proc_count_equiv(float128_t,NUM2DBL,fabs); break;
1237
+ #ifdef HAVE_COMPLEX_H
1238
+ case CA_CMPLX64: proc_count_equiv(cmplx64_t,NUM2CC,cabs); break;
1239
+ case CA_CMPLX128: proc_count_equiv(cmplx128_t,NUM2CC,cabs); break;
1240
+ case CA_CMPLX256: proc_count_equiv(cmplx256_t,NUM2CC,cabs); break;
1241
+ #endif
1242
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1243
+ }
1244
+
1245
+ ca_detach(ca);
1246
+
1247
+ return out;
1248
+ }
1249
+
1250
+ /* ----------------------------------------------------------------- */
1251
+
1252
+ #define proc_count_close(type,from,nabs) \
1253
+ { \
1254
+ type *ptr = (type *) ca->ptr; \
1255
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1256
+ type val = (type) from(value); \
1257
+ double atol = fabs(NUM2DBL(aeps)); \
1258
+ int32_t count = 0; \
1259
+ int32_t value_count = 0; \
1260
+ int32_t i; \
1261
+ if ( m ) { \
1262
+ for (i=ca->elements; i; i--, ptr++) { \
1263
+ if ( ! *m++ ) { \
1264
+ if ( nabs(*ptr - val) <= atol ) { \
1265
+ value_count++; \
1266
+ } \
1267
+ } \
1268
+ else { \
1269
+ count++; \
1270
+ } \
1271
+ } \
1272
+ } \
1273
+ else { \
1274
+ for (i=ca->elements; i; i--, ptr++) { \
1275
+ if ( nabs(*ptr - val) <= atol ) { \
1276
+ value_count++; \
1277
+ } \
1278
+ } \
1279
+ } \
1280
+ if ( ( ! NIL_P(rmin_count) ) && count > min_count ) { \
1281
+ out = ( NIL_P(rfval) ) ? CA_UNDEF : rfval; \
1282
+ } \
1283
+ else { \
1284
+ out = LONG2NUM(value_count); \
1285
+ } \
1286
+ }
1287
+
1288
+ static VALUE
1289
+ rb_ca_count_close (int argc, VALUE *argv, VALUE self)
1290
+ {
1291
+ volatile VALUE out, value = argv[0], aeps = argv[1],
1292
+ rmin_count = Qnil, rfval = Qnil;
1293
+ CArray *ca;
1294
+ int min_count;
1295
+
1296
+ if ( argc > 2 ) {
1297
+ rb_scan_args(argc, argv, "22", &value, &aeps, &rmin_count, &rfval);
1298
+ }
1299
+
1300
+ Data_Get_Struct(self, CArray, ca);
1301
+
1302
+ if ( ca->elements == 0 ) {
1303
+ return ( NIL_P(rfval) ) ? CA_UNDEF : rfval;
1304
+ }
1305
+
1306
+ min_count = ( NIL_P(rmin_count) || ! ca_has_mask(ca) ) ?
1307
+ ca->elements - 1 : NUM2INT(rmin_count);
1308
+
1309
+ if ( min_count < 0 ) {
1310
+ min_count += ca->elements;
1311
+ }
1312
+
1313
+ ca_attach(ca);
1314
+
1315
+ switch ( ca->data_type ) {
1316
+ case CA_BOOLEAN:
1317
+ case CA_INT8: proc_count_close(int8_t,NUM2LONG,fabs); break;
1318
+ case CA_UINT8: proc_count_close(uint8_t,NUM2ULONG,fabs); break;
1319
+ case CA_INT16: proc_count_close(int16_t,NUM2LONG,fabs); break;
1320
+ case CA_UINT16: proc_count_close(uint16_t,NUM2ULONG,fabs); break;
1321
+ case CA_INT32: proc_count_close(int32_t,NUM2LONG,fabs); break;
1322
+ case CA_UINT32: proc_count_close(uint32_t,NUM2LONG,fabs); break;
1323
+ case CA_INT64: proc_count_close(int64_t,NUM2LL,fabs); break;
1324
+ case CA_UINT64: proc_count_close(uint64_t,NUM2LL,fabs); break;
1325
+ case CA_FLOAT32: proc_count_close(float32_t,NUM2DBL,fabs); break;
1326
+ case CA_FLOAT64: proc_count_close(float64_t,NUM2DBL,fabs); break;
1327
+ case CA_FLOAT128: proc_count_close(float128_t,NUM2DBL,fabs); break;
1328
+ #ifdef HAVE_COMPLEX_H
1329
+ case CA_CMPLX64: proc_count_close(cmplx64_t,NUM2CC,cabs); break;
1330
+ case CA_CMPLX128: proc_count_close(cmplx128_t,NUM2CC,cabs); break;
1331
+ case CA_CMPLX256: proc_count_close(cmplx256_t,NUM2CC,cabs); break;
1332
+ #endif
1333
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1334
+ }
1335
+
1336
+ ca_detach(ca);
1337
+
1338
+ return out;
1339
+ }
1340
+
1341
+ /* ----------------------------------------------------------------- */
1342
+
1343
+ #define proc_all_equal(type,from) \
1344
+ { \
1345
+ type *ptr = (type *) ca->ptr; \
1346
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1347
+ type val = (type) from(value); \
1348
+ int32_t i; \
1349
+ if ( m ) { \
1350
+ for (i=ca->elements; i; i--, ptr++) { \
1351
+ if ( ( ! *m++ ) && *ptr != val ) { \
1352
+ flag = Qfalse; \
1353
+ break; \
1354
+ } \
1355
+ } \
1356
+ } \
1357
+ else { \
1358
+ for (i=ca->elements; i; i--, ptr++) { \
1359
+ if ( *ptr != val ) { \
1360
+ flag = Qfalse; \
1361
+ break; \
1362
+ } \
1363
+ } \
1364
+ } \
1365
+ }
1366
+
1367
+ #define proc_all_equal_object() \
1368
+ { \
1369
+ VALUE *ptr = (VALUE *) ca->ptr; \
1370
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1371
+ VALUE val = value; \
1372
+ int32_t i; \
1373
+ if ( m ) { \
1374
+ for (i=ca->elements; i; i--, ptr++) { \
1375
+ if ( ( ! *m++ ) && ! rb_equal(*ptr,val) ) { \
1376
+ flag = Qfalse; \
1377
+ break; \
1378
+ } \
1379
+ } \
1380
+ } \
1381
+ else { \
1382
+ for (i=ca->elements; i; i--, ptr++) { \
1383
+ if ( ! rb_equal(*ptr, val) ) { \
1384
+ flag = Qfalse; \
1385
+ break; \
1386
+ } \
1387
+ } \
1388
+ } \
1389
+ }
1390
+
1391
+ #define proc_all_equal_data() \
1392
+ { \
1393
+ char *ptr = ca->ptr; \
1394
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1395
+ char *val = ALLOCA_N(char, ca->bytes); \
1396
+ int32_t i; \
1397
+ rb_ca_obj2ptr(self, value, val); \
1398
+ if ( m ) { \
1399
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) { \
1400
+ if ( ( ! *m++ ) && memcmp(ptr, val, ca->bytes) ) { \
1401
+ flag = Qfalse; \
1402
+ break; \
1403
+ } \
1404
+ } \
1405
+ } \
1406
+ else { \
1407
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) { \
1408
+ if ( memcmp(ptr, val, ca->bytes) ) { \
1409
+ flag = Qfalse; \
1410
+ break; \
1411
+ } \
1412
+ } \
1413
+ } \
1414
+ }
1415
+
1416
+ static VALUE
1417
+ rb_ca_all_equal_p (int argc, VALUE *argv, VALUE self)
1418
+ {
1419
+ volatile VALUE value;
1420
+ volatile VALUE flag = Qtrue;
1421
+ CArray *ca;
1422
+
1423
+ rb_scan_args(argc, argv, "1", &value);
1424
+
1425
+ Data_Get_Struct(self, CArray, ca);
1426
+
1427
+ ca_attach(ca);
1428
+
1429
+ switch ( ca->data_type ) {
1430
+ case CA_FIXLEN: proc_all_equal_data(); break;
1431
+ case CA_BOOLEAN:
1432
+ case CA_INT8: proc_all_equal(int8_t,NUM2LONG); break;
1433
+ case CA_UINT8: proc_all_equal(uint8_t,NUM2ULONG); break;
1434
+ case CA_INT16: proc_all_equal(int16_t,NUM2LONG); break;
1435
+ case CA_UINT16: proc_all_equal(uint16_t,NUM2ULONG); break;
1436
+ case CA_INT32: proc_all_equal(int32_t,NUM2LONG); break;
1437
+ case CA_UINT32: proc_all_equal(uint32_t,NUM2ULONG); break;
1438
+ case CA_INT64: proc_all_equal(int64_t,NUM2LL); break;
1439
+ case CA_UINT64: proc_all_equal(uint64_t,NUM2ULL); break;
1440
+ case CA_FLOAT32: proc_all_equal(float32_t,NUM2DBL); break;
1441
+ case CA_FLOAT64: proc_all_equal(float64_t,NUM2DBL); break;
1442
+ case CA_FLOAT128: proc_all_equal(float128_t,NUM2DBL); break;
1443
+ #ifdef HAVE_COMPLEX_H
1444
+ case CA_CMPLX64: proc_all_equal(cmplx64_t,NUM2CC); break;
1445
+ case CA_CMPLX128: proc_all_equal(cmplx128_t,NUM2CC); break;
1446
+ case CA_CMPLX256: proc_all_equal(cmplx256_t,NUM2CC); break;
1447
+ #endif
1448
+ case CA_OBJECT: proc_all_equal_object(); break;
1449
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1450
+ }
1451
+
1452
+ ca_detach(ca);
1453
+
1454
+ return flag;
1455
+ }
1456
+
1457
+ /* ----------------------------------------------------------------- */
1458
+
1459
+ #define proc_all_equiv(type,from,nabs) \
1460
+ { \
1461
+ type *ptr = (type *) ca->ptr; \
1462
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1463
+ type val = (type) from(value); \
1464
+ double rtol = fabs(NUM2DBL(reps)); \
1465
+ double vabs = nabs(val); \
1466
+ int32_t i; \
1467
+ if ( m ) { \
1468
+ for (i=ca->elements; i; i--, ptr++) { \
1469
+ if ( ! *m++ ) { \
1470
+ if ( *ptr != val && \
1471
+ nabs(*ptr - val)/MAX(nabs(*ptr), vabs) > rtol ) {\
1472
+ flag = Qfalse; \
1473
+ break; \
1474
+ } \
1475
+ } \
1476
+ } \
1477
+ } \
1478
+ else { \
1479
+ for (i=ca->elements; i; i--, ptr++) { \
1480
+ if ( *ptr != val && \
1481
+ nabs(*ptr - val)/MAX(nabs(*ptr), vabs) > rtol ) {\
1482
+ flag = Qfalse; \
1483
+ break; \
1484
+ } \
1485
+ } \
1486
+ } \
1487
+ }
1488
+
1489
+ static VALUE
1490
+ rb_ca_all_equiv_p (int argc, VALUE *argv, VALUE self)
1491
+ {
1492
+ volatile VALUE value, reps;
1493
+ volatile VALUE flag = Qtrue;
1494
+ CArray *ca;
1495
+
1496
+ rb_scan_args(argc, argv, "2", &value, &reps);
1497
+
1498
+ Data_Get_Struct(self, CArray, ca);
1499
+
1500
+ ca_attach(ca);
1501
+
1502
+ switch ( ca->data_type ) {
1503
+ case CA_BOOLEAN:
1504
+ case CA_INT8: proc_all_equiv(int8_t,NUM2LONG,fabs); break;
1505
+ case CA_UINT8: proc_all_equiv(uint8_t,NUM2ULONG,fabs); break;
1506
+ case CA_INT16: proc_all_equiv(int16_t,NUM2LONG,fabs); break;
1507
+ case CA_UINT16: proc_all_equiv(uint16_t,NUM2ULONG,fabs); break;
1508
+ case CA_INT32: proc_all_equiv(int32_t,NUM2LONG,fabs); break;
1509
+ case CA_UINT32: proc_all_equiv(uint32_t,NUM2ULONG,fabs); break;
1510
+ case CA_INT64: proc_all_equiv(int64_t,NUM2LL,fabs); break;
1511
+ case CA_UINT64: proc_all_equiv(uint64_t,NUM2ULL,fabs); break;
1512
+ case CA_FLOAT32: proc_all_equiv(float32_t,NUM2DBL,fabs); break;
1513
+ case CA_FLOAT64: proc_all_equiv(float64_t,NUM2DBL,fabs); break;
1514
+ case CA_FLOAT128: proc_all_equiv(float128_t,NUM2DBL,fabs); break;
1515
+ #ifdef HAVE_COMPLEX_H
1516
+ case CA_CMPLX64: proc_all_equiv(cmplx64_t,NUM2CC,cabs); break;
1517
+ case CA_CMPLX128: proc_all_equiv(cmplx128_t,NUM2CC,cabs); break;
1518
+ case CA_CMPLX256: proc_all_equiv(cmplx256_t,NUM2CC,cabs); break;
1519
+ #endif
1520
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1521
+ }
1522
+
1523
+ ca_detach(ca);
1524
+
1525
+ return flag;
1526
+ }
1527
+
1528
+ /* ----------------------------------------------------------------- */
1529
+
1530
+ #define proc_all_close(type,from,nabs) \
1531
+ { \
1532
+ type *ptr = (type *) ca->ptr; \
1533
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1534
+ type val = (type) from(value); \
1535
+ double atol = fabs(NUM2DBL(aeps)); \
1536
+ int32_t i; \
1537
+ if ( m ) { \
1538
+ for (i=ca->elements; i; i--, ptr++) { \
1539
+ if ( ! *m++ ) { \
1540
+ if ( nabs(*ptr - val) > atol ) {\
1541
+ flag = Qfalse; \
1542
+ break; \
1543
+ } \
1544
+ } \
1545
+ } \
1546
+ } \
1547
+ else { \
1548
+ for (i=ca->elements; i; i--, ptr++) { \
1549
+ if ( nabs(*ptr - val) > atol ) {\
1550
+ flag = Qfalse; \
1551
+ break; \
1552
+ } \
1553
+ } \
1554
+ } \
1555
+ }
1556
+
1557
+ static VALUE
1558
+ rb_ca_all_close_p (int argc, VALUE *argv, VALUE self)
1559
+ {
1560
+ volatile VALUE value, aeps;
1561
+ volatile VALUE flag = Qtrue;
1562
+ CArray *ca;
1563
+
1564
+ rb_scan_args(argc, argv, "2", &value, &aeps);
1565
+
1566
+ Data_Get_Struct(self, CArray, ca);
1567
+
1568
+ ca_attach(ca);
1569
+
1570
+ switch ( ca->data_type ) {
1571
+ case CA_BOOLEAN:
1572
+ case CA_INT8: proc_all_close(int8_t,NUM2LONG,fabs); break;
1573
+ case CA_UINT8: proc_all_close(uint8_t,NUM2ULONG,fabs); break;
1574
+ case CA_INT16: proc_all_close(int16_t,NUM2LONG,fabs); break;
1575
+ case CA_UINT16: proc_all_close(uint16_t,NUM2ULONG,fabs); break;
1576
+ case CA_INT32: proc_all_close(int32_t,NUM2LONG,fabs); break;
1577
+ case CA_UINT32: proc_all_close(uint32_t,NUM2ULONG,fabs); break;
1578
+ case CA_INT64: proc_all_close(int64_t,NUM2LL,fabs); break;
1579
+ case CA_UINT64: proc_all_close(uint64_t,NUM2ULL,fabs); break;
1580
+ case CA_FLOAT32: proc_all_close(float32_t,NUM2DBL,fabs); break;
1581
+ case CA_FLOAT64: proc_all_close(float64_t,NUM2DBL,fabs); break;
1582
+ case CA_FLOAT128: proc_all_close(float128_t,NUM2DBL,fabs); break;
1583
+ #ifdef HAVE_COMPLEX_H
1584
+ case CA_CMPLX64: proc_all_close(cmplx64_t,NUM2CC,cabs); break;
1585
+ case CA_CMPLX128: proc_all_close(cmplx128_t,NUM2CC,cabs); break;
1586
+ case CA_CMPLX256: proc_all_close(cmplx256_t,NUM2CC,cabs); break;
1587
+ #endif
1588
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1589
+ }
1590
+
1591
+ ca_detach(ca);
1592
+
1593
+ return flag;
1594
+ }
1595
+
1596
+ /* ----------------------------------------------------------------- */
1597
+
1598
+ #define proc_any_equal(type,from) \
1599
+ { \
1600
+ type *ptr = (type *) ca->ptr; \
1601
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1602
+ type val = (type) from(value); \
1603
+ int32_t i; \
1604
+ if ( m ) { \
1605
+ for (i=ca->elements; i; i--, ptr++) { \
1606
+ if ( ( ! *m++ ) && *ptr == val ) { \
1607
+ flag = Qtrue; \
1608
+ break; \
1609
+ } \
1610
+ } \
1611
+ } \
1612
+ else { \
1613
+ for (i=ca->elements; i; i--, ptr++) { \
1614
+ if ( *ptr == val ) { \
1615
+ flag = Qtrue; \
1616
+ break; \
1617
+ } \
1618
+ } \
1619
+ } \
1620
+ }
1621
+
1622
+ #define proc_any_equal_object() \
1623
+ { \
1624
+ VALUE *ptr = (VALUE *) ca->ptr; \
1625
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1626
+ VALUE val = value; \
1627
+ int32_t i; \
1628
+ if ( m ) { \
1629
+ for (i=ca->elements; i; i--, ptr++) { \
1630
+ if ( ( ! *m++ ) && rb_equal(*ptr,val) ) { \
1631
+ flag = Qtrue; \
1632
+ break; \
1633
+ } \
1634
+ } \
1635
+ } \
1636
+ else { \
1637
+ for (i=ca->elements; i; i--, ptr++) { \
1638
+ if ( rb_equal(*ptr, val) ) { \
1639
+ flag = Qtrue; \
1640
+ break; \
1641
+ } \
1642
+ } \
1643
+ } \
1644
+ }
1645
+
1646
+ #define proc_any_equal_data() \
1647
+ { \
1648
+ char *ptr = ca->ptr; \
1649
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1650
+ char *val = ALLOCA_N(char, ca->bytes); \
1651
+ int32_t i; \
1652
+ rb_ca_obj2ptr(self, value, val); \
1653
+ if ( m ) { \
1654
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) \
1655
+ if ( ( ! *m++ ) && ! memcmp(ptr, val, ca->bytes) ) { \
1656
+ flag = Qtrue; \
1657
+ break; \
1658
+ } \
1659
+ } \
1660
+ else { \
1661
+ for (i=ca->elements; i; i--, ptr+=ca->bytes) \
1662
+ if ( ! memcmp(ptr, val, ca->bytes) ) { \
1663
+ flag = Qtrue; \
1664
+ break; \
1665
+ } \
1666
+ } \
1667
+ }
1668
+
1669
+ static VALUE
1670
+ rb_ca_any_equal_p (int argc, VALUE *argv, VALUE self)
1671
+ {
1672
+ volatile VALUE value;
1673
+ volatile VALUE flag = Qfalse;
1674
+ CArray *ca;
1675
+
1676
+ rb_scan_args(argc, argv, "1", &value);
1677
+
1678
+ Data_Get_Struct(self, CArray, ca);
1679
+
1680
+ ca_attach(ca);
1681
+
1682
+ switch ( ca->data_type ) {
1683
+ case CA_FIXLEN: proc_any_equal_data(); break;
1684
+ case CA_BOOLEAN:
1685
+ case CA_INT8: proc_any_equal(int8_t,NUM2LONG); break;
1686
+ case CA_UINT8: proc_any_equal(uint8_t,NUM2ULONG); break;
1687
+ case CA_INT16: proc_any_equal(int16_t,NUM2LONG); break;
1688
+ case CA_UINT16: proc_any_equal(uint16_t,NUM2ULONG); break;
1689
+ case CA_INT32: proc_any_equal(int32_t,NUM2LONG); break;
1690
+ case CA_UINT32: proc_any_equal(uint32_t,NUM2ULONG); break;
1691
+ case CA_INT64: proc_any_equal(int64_t,NUM2LL); break;
1692
+ case CA_UINT64: proc_any_equal(uint64_t,NUM2ULL); break;
1693
+ case CA_FLOAT32: proc_any_equal(float32_t,NUM2DBL); break;
1694
+ case CA_FLOAT64: proc_any_equal(float64_t,NUM2DBL); break;
1695
+ case CA_FLOAT128: proc_any_equal(float128_t,NUM2DBL); break;
1696
+ #ifdef HAVE_COMPLEX_H
1697
+ case CA_CMPLX64: proc_any_equal(cmplx64_t,NUM2CC); break;
1698
+ case CA_CMPLX128: proc_any_equal(cmplx128_t,NUM2CC); break;
1699
+ case CA_CMPLX256: proc_any_equal(cmplx256_t,NUM2CC); break;
1700
+ #endif
1701
+ case CA_OBJECT: proc_any_equal_object(); break;
1702
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1703
+ }
1704
+
1705
+ ca_detach(ca);
1706
+
1707
+ return flag;
1708
+ }
1709
+
1710
+ /* ----------------------------------------------------------------- */
1711
+
1712
+ #define proc_any_equiv(type,from,nabs) \
1713
+ { \
1714
+ type *ptr = (type *) ca->ptr; \
1715
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1716
+ type val = (type) from(value); \
1717
+ double rtol = fabs(NUM2DBL(reps)); \
1718
+ double vabs = nabs(val); \
1719
+ int32_t i; \
1720
+ if ( m ) { \
1721
+ for (i=ca->elements; i; i--, ptr++) { \
1722
+ if ( ! *m++ ) { \
1723
+ if ( *ptr == val || \
1724
+ nabs(*ptr - val)/MAX(nabs(*ptr), vabs) <= rtol ) {\
1725
+ flag = Qtrue; \
1726
+ break; \
1727
+ } \
1728
+ } \
1729
+ } \
1730
+ } \
1731
+ else { \
1732
+ for (i=ca->elements; i; i--, ptr++) { \
1733
+ if ( *ptr == val || \
1734
+ nabs(*ptr - val)/MAX(nabs(*ptr), vabs) <= rtol ) {\
1735
+ flag = Qtrue; \
1736
+ break; \
1737
+ } \
1738
+ } \
1739
+ } \
1740
+ }
1741
+
1742
+ static VALUE
1743
+ rb_ca_any_equiv_p (int argc, VALUE *argv, VALUE self)
1744
+ {
1745
+ volatile VALUE value, reps;
1746
+ volatile VALUE flag = Qfalse;
1747
+ CArray *ca;
1748
+
1749
+ rb_scan_args(argc, argv, "2", &value, &reps);
1750
+
1751
+ Data_Get_Struct(self, CArray, ca);
1752
+
1753
+ ca_attach(ca);
1754
+
1755
+ switch ( ca->data_type ) {
1756
+ case CA_BOOLEAN:
1757
+ case CA_INT8: proc_any_equiv(int8_t,NUM2LONG,fabs); break;
1758
+ case CA_UINT8: proc_any_equiv(uint8_t,NUM2ULONG,fabs); break;
1759
+ case CA_INT16: proc_any_equiv(int16_t,NUM2LONG,fabs); break;
1760
+ case CA_UINT16: proc_any_equiv(uint16_t,NUM2ULONG,fabs); break;
1761
+ case CA_INT32: proc_any_equiv(int32_t,NUM2LONG,fabs); break;
1762
+ case CA_UINT32: proc_any_equiv(uint32_t,NUM2ULONG,fabs); break;
1763
+ case CA_INT64: proc_any_equiv(int64_t,NUM2LL,fabs); break;
1764
+ case CA_UINT64: proc_any_equiv(uint64_t,NUM2ULL,fabs); break;
1765
+ case CA_FLOAT32: proc_any_equiv(float32_t,NUM2DBL,fabs); break;
1766
+ case CA_FLOAT64: proc_any_equiv(float64_t,NUM2DBL,fabs); break;
1767
+ case CA_FLOAT128: proc_any_equiv(float128_t,NUM2DBL,fabs); break;
1768
+ #ifdef HAVE_COMPLEX_H
1769
+ case CA_CMPLX64: proc_any_equiv(cmplx64_t,NUM2CC,cabs); break;
1770
+ case CA_CMPLX128: proc_any_equiv(cmplx128_t,NUM2CC,cabs); break;
1771
+ case CA_CMPLX256: proc_any_equiv(cmplx256_t,NUM2CC,cabs); break;
1772
+ #endif
1773
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1774
+ }
1775
+
1776
+ ca_detach(ca);
1777
+
1778
+ return flag;
1779
+ }
1780
+
1781
+ /* ----------------------------------------------------------------- */
1782
+
1783
+ #define proc_any_close(type,from,nabs) \
1784
+ { \
1785
+ type *ptr = (type *) ca->ptr; \
1786
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1787
+ type val = (type) from(value); \
1788
+ double atol = fabs(NUM2DBL(aeps)); \
1789
+ int32_t i; \
1790
+ if ( m ) { \
1791
+ for (i=ca->elements; i; i--, ptr++) { \
1792
+ if ( ! *m++ ) { \
1793
+ if ( nabs(*ptr - val) <= atol ) {\
1794
+ flag = Qtrue; \
1795
+ break; \
1796
+ } \
1797
+ } \
1798
+ } \
1799
+ } \
1800
+ else { \
1801
+ for (i=ca->elements; i; i--, ptr++) { \
1802
+ if ( nabs(*ptr - val) <= atol ) {\
1803
+ flag = Qtrue; \
1804
+ break; \
1805
+ } \
1806
+ } \
1807
+ } \
1808
+ }
1809
+
1810
+ static VALUE
1811
+ rb_ca_any_close_p (int argc, VALUE *argv, VALUE self)
1812
+ {
1813
+ volatile VALUE value, aeps;
1814
+ volatile VALUE flag = Qfalse;
1815
+ CArray *ca;
1816
+
1817
+ rb_scan_args(argc, argv, "2", &value, &aeps);
1818
+
1819
+ Data_Get_Struct(self, CArray, ca);
1820
+
1821
+ ca_attach(ca);
1822
+
1823
+ switch ( ca->data_type ) {
1824
+ case CA_BOOLEAN:
1825
+ case CA_INT8: proc_any_close(int8_t,NUM2LONG,fabs); break;
1826
+ case CA_UINT8: proc_any_close(uint8_t,NUM2ULONG,fabs); break;
1827
+ case CA_INT16: proc_any_close(int16_t,NUM2LONG,fabs); break;
1828
+ case CA_UINT16: proc_any_close(uint16_t,NUM2ULONG,fabs); break;
1829
+ case CA_INT32: proc_any_close(int32_t,NUM2LONG,fabs); break;
1830
+ case CA_UINT32: proc_any_close(uint32_t,NUM2ULONG,fabs); break;
1831
+ case CA_INT64: proc_any_close(int64_t,NUM2LL,fabs); break;
1832
+ case CA_UINT64: proc_any_close(uint64_t,NUM2ULL,fabs); break;
1833
+ case CA_FLOAT32: proc_any_close(float32_t,NUM2DBL,fabs); break;
1834
+ case CA_FLOAT64: proc_any_close(float64_t,NUM2DBL,fabs); break;
1835
+ case CA_FLOAT128: proc_any_close(float128_t,NUM2DBL,fabs); break;
1836
+ #ifdef HAVE_COMPLEX_H
1837
+ case CA_CMPLX64: proc_any_close(cmplx64_t,NUM2CC,cabs); break;
1838
+ case CA_CMPLX128: proc_any_close(cmplx128_t,NUM2CC,cabs); break;
1839
+ case CA_CMPLX256: proc_any_close(cmplx256_t,NUM2CC,cabs); break;
1840
+ #endif
1841
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1842
+ }
1843
+
1844
+ ca_detach(ca);
1845
+
1846
+ return flag;
1847
+ }
1848
+
1849
+ static VALUE
1850
+ rb_ca_none_equal_p (int argc, VALUE *argv, VALUE self)
1851
+ {
1852
+ return rb_ca_any_equal_p(argc, argv, self) ? Qfalse : Qtrue;
1853
+ }
1854
+
1855
+ static VALUE
1856
+ rb_ca_none_equiv_p (int argc, VALUE *argv, VALUE self)
1857
+ {
1858
+ return rb_ca_any_equiv_p(argc, argv, self) ? Qfalse : Qtrue;
1859
+ }
1860
+
1861
+ static VALUE
1862
+ rb_ca_none_close_p (int argc, VALUE *argv, VALUE self)
1863
+ {
1864
+ return rb_ca_any_close_p(argc, argv, self) ? Qfalse : Qtrue;
1865
+ }
1866
+
1867
+ /* ----------------------------------------------------------------- */
1868
+
1869
+ #define proc_histogram(type, from) \
1870
+ { \
1871
+ type *ptr = (type *) ca->ptr; \
1872
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1873
+ double min = NUM2DBL(vmin); \
1874
+ double max = NUM2DBL(vmax); \
1875
+ double diff = (max - min)/icls; \
1876
+ double trial; \
1877
+ int32_t i; \
1878
+ for (i=0; i<=icls+1; i++) \
1879
+ cls[i] = diff*i + min; \
1880
+ for (i=0; i<ca->elements; i++, ptr++) { \
1881
+ if ( m && *m++ ) continue; \
1882
+ trial = (double)from(*ptr); \
1883
+ if ( diff > 0 && trial >= min && trial <= max ) { \
1884
+ idx = (int32_t) ( (trial - min)/diff ); \
1885
+ hist[idx]++; \
1886
+ } \
1887
+ else if ( diff < 0 && trial >= max && trial <= min ) { \
1888
+ idx = (int32_t) ( (trial - min)/diff ); \
1889
+ hist[idx]++; \
1890
+ } \
1891
+ } \
1892
+ }
1893
+
1894
+ /*
1895
+ static VALUE
1896
+ rb_ca_histogram (int argc, VALUE *argv, VALUE self)
1897
+ {
1898
+ volatile VALUE vnum, vmin, vmax;
1899
+ CArray *ca, *co;
1900
+ int32_t i, idx, icls;
1901
+ int32_t *hist;
1902
+ int32_t dim[2] = {0, 3};
1903
+ double *cls, *p;
1904
+
1905
+ rb_scan_args(argc, argv, "3", &vnum, &vmin, &vmax);
1906
+
1907
+ Data_Get_Struct(self, CArray, ca);
1908
+
1909
+ icls = NUM2LONG(vnum);
1910
+
1911
+ if ( icls < 1 ) {
1912
+ rb_raise(rb_eArgError, "bin number must be larger than 1");
1913
+ }
1914
+
1915
+ hist = ALLOC_N(int32_t, icls+1);
1916
+ cls = ALLOC_N(double, icls+2);
1917
+
1918
+ MEMZERO(hist, int32_t, icls+1);
1919
+ MEMZERO(cls, double, icls+2);
1920
+
1921
+ ca_attach(ca);
1922
+
1923
+ switch ( ca->data_type ) {
1924
+ case CA_BOOLEAN:
1925
+ case CA_INT8: proc_histogram(int8_t,); break;
1926
+ case CA_UINT8: proc_histogram(uint8_t,); break;
1927
+ case CA_INT16: proc_histogram(int16_t,); break;
1928
+ case CA_UINT16: proc_histogram(uint16_t,); break;
1929
+ case CA_INT32: proc_histogram(int32_t,); break;
1930
+ case CA_UINT32: proc_histogram(uint32_t,); break;
1931
+ case CA_INT64: proc_histogram(int64_t,); break;
1932
+ case CA_UINT64: proc_histogram(uint64_t,); break;
1933
+ case CA_FLOAT32: proc_histogram(float32_t,); break;
1934
+ case CA_FLOAT64: proc_histogram(float64_t,); break;
1935
+ case CA_FLOAT128: proc_histogram(float128_t,); break;
1936
+ case CA_OBJECT: proc_histogram(VALUE,NUM2DBL); break;
1937
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
1938
+ }
1939
+
1940
+ ca_detach(ca);
1941
+
1942
+ dim[0] = icls+1;
1943
+
1944
+ co = carray_new(CA_FLOAT64, 2, dim, 0, NULL);
1945
+
1946
+ p = (double *) co->ptr;
1947
+
1948
+ for (i=0; i<icls+1; i++) {
1949
+ *p++ = cls[i];
1950
+ *p++ = cls[i+1];
1951
+ *p++ = (double) hist[i];
1952
+ }
1953
+
1954
+ free(hist);
1955
+ free(cls);
1956
+
1957
+ return ca_wrap_struct(co);
1958
+ }
1959
+ */
1960
+
1961
+ /* ----------------------------------------------------------------- */
1962
+
1963
+ #define proc_grade(type, from) \
1964
+ { \
1965
+ int32_t *dst = (int32_t *) sa->ptr; \
1966
+ boolean8_t *m = (ca->mask) ? (boolean8_t*) ca->mask->ptr : NULL; \
1967
+ boolean8_t *dm = (sa->mask) ? (boolean8_t*) sa->mask->ptr : NULL; \
1968
+ type *ptr = (type *) ca->ptr; \
1969
+ double min = NUM2DBL(vmin); \
1970
+ double max = min + (NUM2DBL(vmax)-min)*(((double)icls)/(icls-1)); \
1971
+ type miss = 0; \
1972
+ double diff = max - min; \
1973
+ double trial; \
1974
+ int32_t i; \
1975
+ if ( min > max ) { \
1976
+ rb_raise(rb_eRuntimeError, "invalid (min, max) range"); \
1977
+ } \
1978
+ if ( min != max ) { \
1979
+ for (i=0; i<ca->elements; i++, ptr++) { \
1980
+ if ( m ) { \
1981
+ miss = *m++; \
1982
+ } \
1983
+ trial = from(*ptr); \
1984
+ if ( miss ) { \
1985
+ *dm = 1; \
1986
+ } \
1987
+ else if ( isnan(trial) ) { \
1988
+ if ( ! dm ) { \
1989
+ ca_create_mask(sa); \
1990
+ dm = (boolean8_t*) sa->mask->ptr; \
1991
+ dm += i; \
1992
+ *dm = 1; \
1993
+ } \
1994
+ *dm = 1; \
1995
+ } \
1996
+ else { \
1997
+ *dst = (int32_t) floor( ((trial-min)/diff) * icls ); \
1998
+ } \
1999
+ dst++; \
2000
+ if ( dm ) { \
2001
+ dm++; \
2002
+ } \
2003
+ } \
2004
+ } \
2005
+ }
2006
+
2007
+ static VALUE
2008
+ rb_ca_grade (int argc, VALUE *argv, VALUE self)
2009
+ {
2010
+ volatile VALUE out, vnum, vmin, vmax;
2011
+ CArray *ca, *sa;
2012
+ int32_t icls;
2013
+
2014
+ rb_scan_args(argc, argv, "12", &vnum, &vmin, &vmax);
2015
+
2016
+ if ( NIL_P(vmin) ) {
2017
+ vmin = rb_funcall(self, rb_intern("min"), 0);
2018
+ }
2019
+
2020
+ if ( NIL_P(vmax) ) {
2021
+ vmax = rb_funcall(self, rb_intern("max"), 0);
2022
+ }
2023
+
2024
+ Data_Get_Struct(self, CArray, ca);
2025
+
2026
+ icls = NUM2LONG(vnum);
2027
+
2028
+ if ( icls < 1 ) {
2029
+ rb_raise(rb_eArgError, "bin number must be larger than 1");
2030
+ }
2031
+
2032
+ out = rb_carray_new_safe(CA_INT32, ca->rank, ca->dim, 0, NULL);
2033
+ Data_Get_Struct(out, CArray, sa);
2034
+
2035
+ ca_attach(ca);
2036
+
2037
+ if ( ca_has_mask(ca) ) {
2038
+ ca_create_mask(sa);
2039
+ ca_setup_mask(sa, ca->mask);
2040
+ }
2041
+
2042
+ switch ( ca->data_type ) {
2043
+ case CA_BOOLEAN:
2044
+ case CA_INT8: proc_grade(int8_t, ); break;
2045
+ case CA_UINT8: proc_grade(uint8_t, ); break;
2046
+ case CA_INT16: proc_grade(int16_t, ); break;
2047
+ case CA_UINT16: proc_grade(uint16_t, ); break;
2048
+ case CA_INT32: proc_grade(int32_t, ); break;
2049
+ case CA_UINT32: proc_grade(uint32_t, ); break;
2050
+ case CA_INT64: proc_grade(int64_t, ); break;
2051
+ case CA_UINT64: proc_grade(uint64_t, ); break;
2052
+ case CA_FLOAT32: proc_grade(float32_t, ); break;
2053
+ case CA_FLOAT64: proc_grade(float64_t, ); break;
2054
+ case CA_FLOAT128: proc_grade(float128_t, ); break;
2055
+ case CA_OBJECT: proc_grade(VALUE,NUM2DBL); break;
2056
+ default: rb_raise(rb_eCADataTypeError, "invalid data type");
2057
+ }
2058
+
2059
+ ca_detach(ca);
2060
+
2061
+ return out;
2062
+ }
2063
+
2064
+ void
2065
+ Init_carray_stat ()
2066
+ {
2067
+ rb_define_method(rb_cCArray, "wsum", rb_ca_wsum, -1);
2068
+ rb_define_method(rb_cCArray, "wmean", rb_ca_wmean, -1);
2069
+ rb_define_method(rb_cCArray, "variancep", rb_ca_variancep, -1);
2070
+ rb_define_method(rb_cCArray, "variance", rb_ca_variance, -1);
2071
+
2072
+ rb_define_method(rb_cCArray, "cummin", rb_ca_cummin, -1);
2073
+ rb_define_method(rb_cCArray, "cummax", rb_ca_cummax, -1);
2074
+ rb_define_method(rb_cCArray, "cumprod", rb_ca_cumprod, -1);
2075
+ rb_define_method(rb_cCArray, "cumwsum", rb_ca_cumwsum, -1);
2076
+
2077
+ rb_define_method(rb_cCArray, "count_true", rb_ca_count_true, -1);
2078
+ rb_define_method(rb_cCArray, "count_false", rb_ca_count_false, -1);
2079
+ rb_define_method(rb_cCArray, "count", rb_ca_count_equal, -1);
2080
+ rb_define_method(rb_cCArray, "count_equal", rb_ca_count_equal, -1);
2081
+ rb_define_method(rb_cCArray, "count_equiv", rb_ca_count_equiv, -1);
2082
+ rb_define_method(rb_cCArray, "count_close", rb_ca_count_close, -1);
2083
+
2084
+ rb_define_method(rb_cCArray, "all_equal?", rb_ca_all_equal_p, -1);
2085
+ rb_define_method(rb_cCArray, "all_equiv?", rb_ca_all_equiv_p, -1);
2086
+ rb_define_method(rb_cCArray, "all_close?", rb_ca_all_close_p, -1);
2087
+
2088
+ rb_define_method(rb_cCArray, "any_equal?", rb_ca_any_equal_p, -1);
2089
+ rb_define_method(rb_cCArray, "any_equiv?", rb_ca_any_equiv_p, -1);
2090
+ rb_define_method(rb_cCArray, "any_close?", rb_ca_any_close_p, -1);
2091
+ rb_define_method(rb_cCArray, "none_equal?", rb_ca_none_equal_p, -1);
2092
+ rb_define_method(rb_cCArray, "none_equiv?", rb_ca_none_equiv_p, -1);
2093
+ rb_define_method(rb_cCArray, "none_close?", rb_ca_none_close_p, -1);
2094
+
2095
+ /* rb_define_method(rb_cCArray, "histogram", rb_ca_histogram, -1); */
2096
+ rb_define_method(rb_cCArray, "grade", rb_ca_grade, -1);
2097
+ rb_define_method(rb_cCArray, "gradate", rb_ca_grade, -1);
2098
+ rb_define_method(rb_cCArray, "quantize", rb_ca_grade, -1);
2099
+
2100
+ }
2101
+
2102
+