numo-narray-alt 0.10.7 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9897dbc5b94aa16af082880fe4085b341b628664ae6abc27e2ffa9e989e88451
4
- data.tar.gz: d1d53a63934a8a51ee74cf64093b2b3869e03e75bea6070830230e14d9e91b91
3
+ metadata.gz: 9b2e2bc7cc99b7ef2b868b588360ff66299a6570b4d6ea98c45bbb357eed661b
4
+ data.tar.gz: '0887ab3061ad5add393ecd99921ca88e3a06545c9617ffc9686550cb87b3e843'
5
5
  SHA512:
6
- metadata.gz: 165941e9d06b5cd9e59ae591ab5666f9cb9924786d5253ce889da809de69b72c1893faef2a4c1e8f2d875021596415496802b8fb1bcf0b523b82c4cde231fb32
7
- data.tar.gz: fd52d794a7c41344534a07e726b1f13bf0af8003d8e428a0c4f133a17efd5c9721e029a2365fc4a0f4cc04b21f9255897d4927f19500eeaeb51e2cdeb94018f1
6
+ metadata.gz: '09f47d21922f7e24e7915222eb9ddacadf4392156e53a15aee05d4f2fc6ebdafce244c3624de375b10411768d7f1a38de7d081504ef0fe21b6b1b82156ef9410'
7
+ data.tar.gz: 4cc3900b5631971fc76195eee5ecf66a6c1647a604d19997b0bcece1d1341f9245ace1c405c3f5e9dbc493389f456c4c9c817ea145a1c3a47f2180edea52ae36
data/README.md CHANGED
@@ -24,6 +24,15 @@ This project is in no way intended to adversely affect the development of the or
24
24
  $ gem install numo-narray-alt
25
25
  ```
26
26
 
27
+ ### Build options
28
+
29
+ By default, the floating-point classes (`Numo::SFloat` / `Numo::DFloat`) use SIMD instructions
30
+ (SSE2 / AVX / NEON) when the target CPU supports them. To build without SIMD, pass `--with-no-simd`:
31
+
32
+ ```shell
33
+ $ gem install numo-narray-alt -- --with-no-simd
34
+ ```
35
+
27
36
  ## Usage
28
37
 
29
38
  The usage is exactly the same as Numo::NArray.
@@ -325,17 +325,9 @@ static void na_check_reshape(int argc, VALUE* argv, VALUE self, size_t* shape) {
325
325
  /* get shape from argument */
326
326
  for (i = 0; i < argc; ++i) {
327
327
  switch (TYPE(argv[i])) {
328
- case T_FIXNUM: {
329
- ssize_t x = NUM2SSIZET(argv[i]);
330
- if (x < 0) {
331
- rb_raise(rb_eArgError, "size must be non-negative");
332
- }
333
- if (x != 0 && total > SIZE_MAX / (size_t)x) {
334
- rb_raise(rb_eArgError, "total size is too large");
335
- }
336
- total *= shape[i] = (size_t)x;
328
+ case T_FIXNUM:
329
+ total *= shape[i] = NUM2INT(argv[i]);
337
330
  break;
338
- }
339
331
  case T_NIL:
340
332
  case T_TRUE:
341
333
  if (unfixed >= 0) {
@@ -349,9 +341,6 @@ static void na_check_reshape(int argc, VALUE* argv, VALUE self, size_t* shape) {
349
341
  }
350
342
 
351
343
  if (unfixed >= 0) {
352
- if (total == 0) {
353
- rb_raise(rb_eArgError, "cannot determine unfixed dimension when total size is zero");
354
- }
355
344
  if (NA_SIZE(na) % total != 0) {
356
345
  rb_raise(rb_eArgError, "Total size size must be divisor");
357
346
  }
@@ -66,6 +66,8 @@ have_func('RTYPEDDATA_GET_DATA')
66
66
 
67
67
  have_var('rb_cComplex')
68
68
 
69
+ $defs << '-DNUMO_NO_SIMD' if with_config('no-simd', false)
70
+
69
71
  $objs = srcs.collect { |i| "#{i}.o" }
70
72
 
71
73
  create_header d('numo/extconf.h')
@@ -126,7 +126,7 @@ static void na_parse_narray_index(VALUE a, int orig_dim, ssize_t size, na_index_
126
126
  GetNArray(idx, nidx);
127
127
  n = NA_SIZE(nidx);
128
128
  q->idx = ALLOC_N(size_t, n);
129
- if (nidx->type != NARRAY_DATA_T) {
129
+ if (na->type != NARRAY_DATA_T) {
130
130
  rb_bug("NArray#where returned wrong type of NArray");
131
131
  }
132
132
  if (rb_obj_class(idx) == numo_cInt32) {
@@ -183,13 +183,7 @@ na_parse_range(VALUE range, ssize_t step, int orig_dim, ssize_t size, na_index_a
183
183
 
184
184
  rb_arithmetic_sequence_components_t x;
185
185
  rb_arithmetic_sequence_extract(range, &x);
186
- if (!RB_INTEGER_TYPE_P(x.step)) {
187
- rb_raise(rb_eArgError, "step must be an Integer");
188
- }
189
186
  step = NUM2SSIZET(x.step);
190
- if (step == 0) {
191
- rb_raise(rb_eArgError, "step must not be zero");
192
- }
193
187
 
194
188
  beg = beg_orig = NUM2SSIZET(x.begin);
195
189
  if (beg < 0) {
@@ -481,17 +475,13 @@ static void na_index_aref_nadata(
481
475
  na_get_strides_nadata(na1, strides_na1, elmsz);
482
476
 
483
477
  for (i = j = 0; i < ndim; i++) {
484
- const int qi_orig_dim = q[i].orig_dim;
485
- stride1 = 0;
486
- if (qi_orig_dim < na1->base.ndim) {
487
- stride1 = strides_na1[qi_orig_dim];
478
+ stride1 = strides_na1[q[i].orig_dim];
488
479
 
489
- // numeric index -- trim dimension
490
- if (!keep_dim && q[i].n == 1 && q[i].step == 0) {
491
- beg = q[i].beg;
492
- na2->offset += stride1 * beg;
493
- continue;
494
- }
480
+ // numeric index -- trim dimension
481
+ if (!keep_dim && q[i].n == 1 && q[i].step == 0) {
482
+ beg = q[i].beg;
483
+ na2->offset += stride1 * beg;
484
+ continue;
495
485
  }
496
486
 
497
487
  na2->base.shape[j] = size = q[i].n;
@@ -501,11 +491,8 @@ static void na_index_aref_nadata(
501
491
  na2->base.reduce = rb_funcall(m, '|', 1, na2->base.reduce);
502
492
  }
503
493
 
504
- if (qi_orig_dim >= na1->base.ndim) {
505
- // new dimension
506
- SDX_SET_STRIDE(na2->stridx[j], elmsz);
507
- } else if (q[i].idx != NULL) {
508
- // array index
494
+ // array index
495
+ if (q[i].idx != NULL) {
509
496
  index = q[i].idx;
510
497
  SDX_SET_INDEX(na2->stridx[j], index);
511
498
  q[i].idx = NULL;
@@ -1322,7 +1322,6 @@ static VALUE nary_store_binary(int argc, VALUE* argv, VALUE self) {
1322
1322
  narray_t* na;
1323
1323
 
1324
1324
  narg = rb_scan_args(argc, argv, "11", &vstr, &voffset);
1325
- Check_Type(vstr, T_STRING);
1326
1325
  str_len = RSTRING_LEN(vstr);
1327
1326
  if (narg == 2) {
1328
1327
  offset = NUM2SIZET(voffset);
@@ -13,10 +13,10 @@ extern "C" {
13
13
  #endif
14
14
  #endif
15
15
 
16
- #define NARRAY_VERSION "0.10.7"
16
+ #define NARRAY_VERSION "0.11.0"
17
17
  #define NARRAY_VERSION_MAJOR 0
18
- #define NARRAY_VERSION_MINOR 10
19
- #define NARRAY_VERSION_PATCH 7
18
+ #define NARRAY_VERSION_MINOR 11
19
+ #define NARRAY_VERSION_PATCH 0
20
20
  #define NARRAY_VERSION_CODE \
21
21
  (NARRAY_VERSION_MAJOR * 10000 + NARRAY_VERSION_MINOR * 100 + NARRAY_VERSION_PATCH)
22
22
 
@@ -68,6 +68,13 @@
68
68
 
69
69
  #define m_mulsum_init INT2FIX(0)
70
70
 
71
+ #define m_sprintf(s, x) robj_sprintf(s, x)
72
+
73
+ static inline int robj_sprintf(char* s, VALUE x) {
74
+ VALUE v = rb_funcall(x, rb_intern("to_s"), 0);
75
+ return sprintf(s, "%s", StringValuePtr(v));
76
+ }
77
+
71
78
  #define m_sqrt(x) \
72
79
  rb_funcall(rb_const_get(rb_mKernel, rb_intern("Math")), rb_intern("sqrt"), 1, x);
73
80
 
@@ -1,7 +1,7 @@
1
1
  #ifndef NUMO_NARRAY_MH_FORMAT_H
2
2
  #define NUMO_NARRAY_MH_FORMAT_H 1
3
3
 
4
- #define DEF_NARRAY_FORMAT_ELEMENT_FUNC(tDType) \
4
+ #define DEF_NARRAY_FORMAT_METHOD_FUNC(tDType) \
5
5
  static VALUE format_##tDType(VALUE fmt, tDType* x) { \
6
6
  if (NIL_P(fmt)) { \
7
7
  char s[48]; \
@@ -9,22 +9,8 @@
9
9
  return rb_str_new(s, n); \
10
10
  } \
11
11
  return rb_funcall(fmt, '%', 1, m_data_to_num(*x)); \
12
- }
13
-
14
- /* robject formats its element without the fixed buffer above: the element is an
15
- arbitrary Ruby object, so the length of its to_s is not bounded by anything
16
- this side controls. */
17
- #define DEF_NARRAY_ROBJ_FORMAT_ELEMENT_FUNC() \
18
- static VALUE format_robject(VALUE fmt, robject* x) { \
19
- if (NIL_P(fmt)) { \
20
- VALUE v = rb_funcall(*x, id_to_s, 0); \
21
- StringValue(v); \
22
- return rb_str_new(RSTRING_PTR(v), RSTRING_LEN(v)); \
23
- } \
24
- return rb_funcall(fmt, '%', 1, m_data_to_num(*x)); \
25
- }
26
-
27
- #define DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(tDType) \
12
+ } \
13
+ \
28
14
  static void iter_##tDType##_format(na_loop_t* const lp) { \
29
15
  size_t n; \
30
16
  char* p1; \
@@ -66,12 +52,4 @@
66
52
  return na_ndloop(&ndf, 2, self, fmt); \
67
53
  }
68
54
 
69
- #define DEF_NARRAY_FORMAT_METHOD_FUNC(tDType) \
70
- DEF_NARRAY_FORMAT_ELEMENT_FUNC(tDType) \
71
- DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(tDType)
72
-
73
- #define DEF_NARRAY_ROBJ_FORMAT_METHOD_FUNC() \
74
- DEF_NARRAY_ROBJ_FORMAT_ELEMENT_FUNC() \
75
- DEF_NARRAY_FORMAT_LOOP_METHOD_FUNC(robject)
76
-
77
55
  #endif /* NUMO_NARRAY_MH_FORMAT_H */
@@ -200,4 +200,376 @@
200
200
  return na_ndloop(&ndf, 1, a1); \
201
201
  }
202
202
 
203
+ #define DEF_NARRAY_FLT_SQRT_AVX_SGL_METHOD_FUNC(tDType, tNAryClass) \
204
+ static void iter_##tDType##_math_s_sqrt(na_loop_t* const lp) { \
205
+ size_t i = 0; \
206
+ size_t n; \
207
+ char *p1, *p2; \
208
+ ssize_t s1, s2; \
209
+ size_t *idx1, *idx2; \
210
+ tDType x; \
211
+ size_t cnt; \
212
+ size_t cnt_simd_loop = -1; \
213
+ __m256 a; \
214
+ size_t num_pack; \
215
+ num_pack = AVX_ALIGNMENT_SIZE / sizeof(tDType); \
216
+ \
217
+ INIT_COUNTER(lp, n); \
218
+ INIT_PTR_IDX(lp, 0, p1, s1, idx1); \
219
+ INIT_PTR_IDX(lp, 1, p2, s2, idx2); \
220
+ \
221
+ if (idx1) { \
222
+ if (idx2) { \
223
+ for (i = 0; i < n; i++) { \
224
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
225
+ x = m_sqrt(x); \
226
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
227
+ } \
228
+ } else { \
229
+ for (i = 0; i < n; i++) { \
230
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
231
+ x = m_sqrt(x); \
232
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
233
+ } \
234
+ } \
235
+ } else { \
236
+ if (idx2) { \
237
+ for (i = 0; i < n; i++) { \
238
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
239
+ x = m_sqrt(x); \
240
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
241
+ } \
242
+ } else { \
243
+ if (is_aligned(p1, sizeof(tDType)) && is_aligned(p2, sizeof(tDType))) { \
244
+ if (s1 == sizeof(tDType) && s2 == sizeof(tDType)) { \
245
+ if ((n >= num_pack) && \
246
+ is_same_aligned2(&((tDType*)p1)[i], &((tDType*)p2)[i], AVX_ALIGNMENT_SIZE)) { \
247
+ cnt = get_count_of_elements_not_aligned_to_simd_size( \
248
+ &((tDType*)p1)[i], AVX_ALIGNMENT_SIZE, sizeof(tDType) \
249
+ ); \
250
+ for (i = 0; i < cnt; i++) { \
251
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
252
+ } \
253
+ cnt_simd_loop = (n - i) % num_pack; \
254
+ if (p1 == p2) { \
255
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
256
+ a = _mm256_load_ps(&((tDType*)p1)[i]); \
257
+ a = _mm256_sqrt_ps(a); \
258
+ _mm256_store_ps(&((tDType*)p1)[i], a); \
259
+ } \
260
+ } else { \
261
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
262
+ a = _mm256_load_ps(&((tDType*)p1)[i]); \
263
+ a = _mm256_sqrt_ps(a); \
264
+ _mm256_stream_ps(&((tDType*)p2)[i], a); \
265
+ } \
266
+ } \
267
+ } \
268
+ if (cnt_simd_loop != 0) { \
269
+ for (; i < n; i++) { \
270
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
271
+ } \
272
+ } \
273
+ return; \
274
+ } \
275
+ if (is_aligned_step(s1, sizeof(tDType)) && is_aligned_step(s2, sizeof(tDType))) { \
276
+ for (i = 0; i < n; i++) { \
277
+ *(tDType*)p2 = m_sqrt(*(tDType*)p1); \
278
+ p1 += s1; \
279
+ p2 += s2; \
280
+ } \
281
+ return; \
282
+ } \
283
+ } \
284
+ for (i = 0; i < n; i++) { \
285
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
286
+ x = m_sqrt(x); \
287
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
288
+ } \
289
+ } \
290
+ } \
291
+ } \
292
+ \
293
+ static VALUE tDType##_math_s_sqrt(VALUE mod, VALUE a1) { \
294
+ ndfunc_arg_in_t ain[1] = { { tNAryClass, 0 } }; \
295
+ ndfunc_arg_out_t aout[1] = { { tNAryClass, 0 } }; \
296
+ ndfunc_t ndf = { iter_##tDType##_math_s_sqrt, FULL_LOOP, 1, 1, ain, aout }; \
297
+ return na_ndloop(&ndf, 1, a1); \
298
+ }
299
+
300
+ #define DEF_NARRAY_FLT_SQRT_AVX_DBL_METHOD_FUNC(tDType, tNAryClass) \
301
+ static void iter_##tDType##_math_s_sqrt(na_loop_t* const lp) { \
302
+ size_t i = 0; \
303
+ size_t n; \
304
+ char *p1, *p2; \
305
+ ssize_t s1, s2; \
306
+ size_t *idx1, *idx2; \
307
+ tDType x; \
308
+ size_t cnt; \
309
+ size_t cnt_simd_loop = -1; \
310
+ __m256d a; \
311
+ size_t num_pack; \
312
+ num_pack = AVX_ALIGNMENT_SIZE / sizeof(tDType); \
313
+ \
314
+ INIT_COUNTER(lp, n); \
315
+ INIT_PTR_IDX(lp, 0, p1, s1, idx1); \
316
+ INIT_PTR_IDX(lp, 1, p2, s2, idx2); \
317
+ \
318
+ if (idx1) { \
319
+ if (idx2) { \
320
+ for (i = 0; i < n; i++) { \
321
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
322
+ x = m_sqrt(x); \
323
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
324
+ } \
325
+ } else { \
326
+ for (i = 0; i < n; i++) { \
327
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
328
+ x = m_sqrt(x); \
329
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
330
+ } \
331
+ } \
332
+ } else { \
333
+ if (idx2) { \
334
+ for (i = 0; i < n; i++) { \
335
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
336
+ x = m_sqrt(x); \
337
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
338
+ } \
339
+ } else { \
340
+ if (is_aligned(p1, sizeof(tDType)) && is_aligned(p2, sizeof(tDType))) { \
341
+ if (s1 == sizeof(tDType) && s2 == sizeof(tDType)) { \
342
+ if ((n >= num_pack) && \
343
+ is_same_aligned2(&((tDType*)p1)[i], &((tDType*)p2)[i], AVX_ALIGNMENT_SIZE)) { \
344
+ cnt = get_count_of_elements_not_aligned_to_simd_size( \
345
+ &((tDType*)p1)[i], AVX_ALIGNMENT_SIZE, sizeof(tDType) \
346
+ ); \
347
+ for (i = 0; i < cnt; i++) { \
348
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
349
+ } \
350
+ cnt_simd_loop = (n - i) % num_pack; \
351
+ if (p1 == p2) { \
352
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
353
+ a = _mm256_load_pd(&((tDType*)p1)[i]); \
354
+ a = _mm256_sqrt_pd(a); \
355
+ _mm256_store_pd(&((tDType*)p1)[i], a); \
356
+ } \
357
+ } else { \
358
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
359
+ a = _mm256_load_pd(&((tDType*)p1)[i]); \
360
+ a = _mm256_sqrt_pd(a); \
361
+ _mm256_stream_pd(&((tDType*)p2)[i], a); \
362
+ } \
363
+ } \
364
+ } \
365
+ if (cnt_simd_loop != 0) { \
366
+ for (; i < n; i++) { \
367
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
368
+ } \
369
+ } \
370
+ return; \
371
+ } \
372
+ if (is_aligned_step(s1, sizeof(tDType)) && is_aligned_step(s2, sizeof(tDType))) { \
373
+ for (i = 0; i < n; i++) { \
374
+ *(tDType*)p2 = m_sqrt(*(tDType*)p1); \
375
+ p1 += s1; \
376
+ p2 += s2; \
377
+ } \
378
+ return; \
379
+ } \
380
+ } \
381
+ for (i = 0; i < n; i++) { \
382
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
383
+ x = m_sqrt(x); \
384
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
385
+ } \
386
+ } \
387
+ } \
388
+ } \
389
+ \
390
+ static VALUE tDType##_math_s_sqrt(VALUE mod, VALUE a1) { \
391
+ ndfunc_arg_in_t ain[1] = { { tNAryClass, 0 } }; \
392
+ ndfunc_arg_out_t aout[1] = { { tNAryClass, 0 } }; \
393
+ ndfunc_t ndf = { iter_##tDType##_math_s_sqrt, FULL_LOOP, 1, 1, ain, aout }; \
394
+ return na_ndloop(&ndf, 1, a1); \
395
+ }
396
+
397
+ #define DEF_NARRAY_FLT_SQRT_NEON_SGL_METHOD_FUNC(tDType, tNAryClass) \
398
+ static void iter_##tDType##_math_s_sqrt(na_loop_t* const lp) { \
399
+ size_t i = 0; \
400
+ size_t n; \
401
+ char *p1, *p2; \
402
+ ssize_t s1, s2; \
403
+ size_t *idx1, *idx2; \
404
+ tDType x; \
405
+ size_t cnt; \
406
+ size_t cnt_simd_loop = -1; \
407
+ float32x4_t a; \
408
+ size_t num_pack; \
409
+ num_pack = NEON_ALIGNMENT_SIZE / sizeof(tDType); \
410
+ \
411
+ INIT_COUNTER(lp, n); \
412
+ INIT_PTR_IDX(lp, 0, p1, s1, idx1); \
413
+ INIT_PTR_IDX(lp, 1, p2, s2, idx2); \
414
+ \
415
+ if (idx1) { \
416
+ if (idx2) { \
417
+ for (i = 0; i < n; i++) { \
418
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
419
+ x = m_sqrt(x); \
420
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
421
+ } \
422
+ } else { \
423
+ for (i = 0; i < n; i++) { \
424
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
425
+ x = m_sqrt(x); \
426
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
427
+ } \
428
+ } \
429
+ } else { \
430
+ if (idx2) { \
431
+ for (i = 0; i < n; i++) { \
432
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
433
+ x = m_sqrt(x); \
434
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
435
+ } \
436
+ } else { \
437
+ if (is_aligned(p1, sizeof(tDType)) && is_aligned(p2, sizeof(tDType))) { \
438
+ if (s1 == sizeof(tDType) && s2 == sizeof(tDType)) { \
439
+ if ((n >= num_pack) && \
440
+ is_same_aligned2(&((tDType*)p1)[i], &((tDType*)p2)[i], NEON_ALIGNMENT_SIZE)) { \
441
+ cnt = get_count_of_elements_not_aligned_to_simd_size( \
442
+ &((tDType*)p1)[i], NEON_ALIGNMENT_SIZE, sizeof(tDType) \
443
+ ); \
444
+ for (i = 0; i < cnt; i++) { \
445
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
446
+ } \
447
+ cnt_simd_loop = (n - i) % num_pack; \
448
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
449
+ a = vld1q_f32(&((tDType*)p1)[i]); \
450
+ a = vsqrtq_f32(a); \
451
+ vst1q_f32(&((tDType*)p2)[i], a); \
452
+ } \
453
+ } \
454
+ if (cnt_simd_loop != 0) { \
455
+ for (; i < n; i++) { \
456
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
457
+ } \
458
+ } \
459
+ return; \
460
+ } \
461
+ if (is_aligned_step(s1, sizeof(tDType)) && is_aligned_step(s2, sizeof(tDType))) { \
462
+ for (i = 0; i < n; i++) { \
463
+ *(tDType*)p2 = m_sqrt(*(tDType*)p1); \
464
+ p1 += s1; \
465
+ p2 += s2; \
466
+ } \
467
+ return; \
468
+ } \
469
+ } \
470
+ for (i = 0; i < n; i++) { \
471
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
472
+ x = m_sqrt(x); \
473
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
474
+ } \
475
+ } \
476
+ } \
477
+ } \
478
+ \
479
+ static VALUE tDType##_math_s_sqrt(VALUE mod, VALUE a1) { \
480
+ ndfunc_arg_in_t ain[1] = { { tNAryClass, 0 } }; \
481
+ ndfunc_arg_out_t aout[1] = { { tNAryClass, 0 } }; \
482
+ ndfunc_t ndf = { iter_##tDType##_math_s_sqrt, FULL_LOOP, 1, 1, ain, aout }; \
483
+ return na_ndloop(&ndf, 1, a1); \
484
+ }
485
+
486
+ #define DEF_NARRAY_FLT_SQRT_NEON_DBL_METHOD_FUNC(tDType, tNAryClass) \
487
+ static void iter_##tDType##_math_s_sqrt(na_loop_t* const lp) { \
488
+ size_t i = 0; \
489
+ size_t n; \
490
+ char *p1, *p2; \
491
+ ssize_t s1, s2; \
492
+ size_t *idx1, *idx2; \
493
+ tDType x; \
494
+ size_t cnt; \
495
+ size_t cnt_simd_loop = -1; \
496
+ float64x2_t a; \
497
+ size_t num_pack; \
498
+ num_pack = NEON_ALIGNMENT_SIZE / sizeof(tDType); \
499
+ \
500
+ INIT_COUNTER(lp, n); \
501
+ INIT_PTR_IDX(lp, 0, p1, s1, idx1); \
502
+ INIT_PTR_IDX(lp, 1, p2, s2, idx2); \
503
+ \
504
+ if (idx1) { \
505
+ if (idx2) { \
506
+ for (i = 0; i < n; i++) { \
507
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
508
+ x = m_sqrt(x); \
509
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
510
+ } \
511
+ } else { \
512
+ for (i = 0; i < n; i++) { \
513
+ GET_DATA_INDEX(p1, idx1, tDType, x); \
514
+ x = m_sqrt(x); \
515
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
516
+ } \
517
+ } \
518
+ } else { \
519
+ if (idx2) { \
520
+ for (i = 0; i < n; i++) { \
521
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
522
+ x = m_sqrt(x); \
523
+ SET_DATA_INDEX(p2, idx2, tDType, x); \
524
+ } \
525
+ } else { \
526
+ if (is_aligned(p1, sizeof(tDType)) && is_aligned(p2, sizeof(tDType))) { \
527
+ if (s1 == sizeof(tDType) && s2 == sizeof(tDType)) { \
528
+ if ((n >= num_pack) && \
529
+ is_same_aligned2(&((tDType*)p1)[i], &((tDType*)p2)[i], NEON_ALIGNMENT_SIZE)) { \
530
+ cnt = get_count_of_elements_not_aligned_to_simd_size( \
531
+ &((tDType*)p1)[i], NEON_ALIGNMENT_SIZE, sizeof(tDType) \
532
+ ); \
533
+ for (i = 0; i < cnt; i++) { \
534
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
535
+ } \
536
+ cnt_simd_loop = (n - i) % num_pack; \
537
+ for (; i < n - cnt_simd_loop; i += num_pack) { \
538
+ a = vld1q_f64(&((tDType*)p1)[i]); \
539
+ a = vsqrtq_f64(a); \
540
+ vst1q_f64(&((tDType*)p2)[i], a); \
541
+ } \
542
+ } \
543
+ if (cnt_simd_loop != 0) { \
544
+ for (; i < n; i++) { \
545
+ ((tDType*)p2)[i] = m_sqrt(((tDType*)p1)[i]); \
546
+ } \
547
+ } \
548
+ return; \
549
+ } \
550
+ if (is_aligned_step(s1, sizeof(tDType)) && is_aligned_step(s2, sizeof(tDType))) { \
551
+ for (i = 0; i < n; i++) { \
552
+ *(tDType*)p2 = m_sqrt(*(tDType*)p1); \
553
+ p1 += s1; \
554
+ p2 += s2; \
555
+ } \
556
+ return; \
557
+ } \
558
+ } \
559
+ for (i = 0; i < n; i++) { \
560
+ GET_DATA_STRIDE(p1, s1, tDType, x); \
561
+ x = m_sqrt(x); \
562
+ SET_DATA_STRIDE(p2, s2, tDType, x); \
563
+ } \
564
+ } \
565
+ } \
566
+ } \
567
+ \
568
+ static VALUE tDType##_math_s_sqrt(VALUE mod, VALUE a1) { \
569
+ ndfunc_arg_in_t ain[1] = { { tNAryClass, 0 } }; \
570
+ ndfunc_arg_out_t aout[1] = { { tNAryClass, 0 } }; \
571
+ ndfunc_t ndf = { iter_##tDType##_math_s_sqrt, FULL_LOOP, 1, 1, ain, aout }; \
572
+ return na_ndloop(&ndf, 1, a1); \
573
+ }
574
+
203
575
  #endif /* NUMO_NARRAY_MH_MATH_SQRT_H */