numo-narray 0.9.1.4 → 0.9.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -6
  3. data/Rakefile +4 -63
  4. data/ext/numo/narray/array.c +35 -32
  5. data/ext/numo/narray/data.c +40 -43
  6. data/ext/numo/narray/depend.erb +6 -10
  7. data/ext/numo/narray/extconf.rb +24 -21
  8. data/ext/numo/narray/gen/cogen.rb +2 -2
  9. data/ext/numo/narray/gen/narray_def.rb +5 -1
  10. data/ext/numo/narray/gen/spec.rb +17 -7
  11. data/ext/numo/narray/gen/tmpl/accum.c +2 -2
  12. data/ext/numo/narray/gen/tmpl/accum_arg.c +88 -0
  13. data/ext/numo/narray/gen/tmpl/accum_binary.c +1 -1
  14. data/ext/numo/narray/gen/tmpl/accum_index.c +25 -14
  15. data/ext/numo/narray/gen/tmpl/alloc_func.c +4 -1
  16. data/ext/numo/narray/gen/tmpl/allocate.c +1 -0
  17. data/ext/numo/narray/gen/tmpl/aref.c +5 -35
  18. data/ext/numo/narray/gen/tmpl/aset.c +7 -37
  19. data/ext/numo/narray/gen/tmpl/bincount.c +7 -7
  20. data/ext/numo/narray/gen/tmpl/cast.c +7 -0
  21. data/ext/numo/narray/gen/tmpl/clip.c +11 -15
  22. data/ext/numo/narray/gen/tmpl/cum.c +1 -1
  23. data/ext/numo/narray/gen/tmpl/each.c +4 -2
  24. data/ext/numo/narray/gen/tmpl/each_with_index.c +5 -2
  25. data/ext/numo/narray/gen/tmpl/lib.c +2 -2
  26. data/ext/numo/narray/gen/tmpl/logseq.c +6 -5
  27. data/ext/numo/narray/gen/tmpl/map_with_index.c +5 -6
  28. data/ext/numo/narray/gen/tmpl/median.c +2 -2
  29. data/ext/numo/narray/gen/tmpl/minmax.c +1 -1
  30. data/ext/numo/narray/gen/tmpl/poly.c +4 -4
  31. data/ext/numo/narray/gen/tmpl/qsort.c +1 -1
  32. data/ext/numo/narray/gen/tmpl/rand.c +8 -6
  33. data/ext/numo/narray/gen/tmpl/rand_norm.c +18 -16
  34. data/ext/numo/narray/gen/tmpl/seq.c +5 -4
  35. data/ext/numo/narray/gen/tmpl/sort.c +3 -3
  36. data/ext/numo/narray/gen/tmpl/sort_index.c +2 -2
  37. data/ext/numo/narray/gen/tmpl/store_array.c +14 -2
  38. data/ext/numo/narray/gen/tmpl/unary_s.c +55 -31
  39. data/ext/numo/narray/gen/tmpl_bit/allocate.c +1 -0
  40. data/ext/numo/narray/gen/tmpl_bit/aref.c +22 -30
  41. data/ext/numo/narray/gen/tmpl_bit/aset.c +20 -34
  42. data/ext/numo/narray/gen/tmpl_bit/binary.c +48 -14
  43. data/ext/numo/narray/gen/tmpl_bit/bit_count.c +5 -0
  44. data/ext/numo/narray/gen/tmpl_bit/bit_reduce.c +5 -0
  45. data/ext/numo/narray/gen/tmpl_bit/store_array.c +14 -2
  46. data/ext/numo/narray/gen/tmpl_bit/store_bit.c +27 -9
  47. data/ext/numo/narray/gen/tmpl_bit/unary.c +25 -7
  48. data/ext/numo/narray/index.c +363 -59
  49. data/ext/numo/narray/math.c +2 -2
  50. data/ext/numo/narray/narray.c +151 -36
  51. data/ext/numo/narray/ndloop.c +4 -4
  52. data/ext/numo/narray/numo/intern.h +3 -2
  53. data/ext/numo/narray/numo/narray.h +37 -14
  54. data/ext/numo/narray/numo/ndloop.h +2 -2
  55. data/ext/numo/narray/numo/template.h +11 -15
  56. data/ext/numo/narray/numo/types/complex.h +2 -2
  57. data/ext/numo/narray/numo/types/int16.h +5 -2
  58. data/ext/numo/narray/numo/types/int32.h +0 -1
  59. data/ext/numo/narray/numo/types/int64.h +0 -1
  60. data/ext/numo/narray/numo/types/int8.h +1 -2
  61. data/ext/numo/narray/numo/types/uint16.h +5 -2
  62. data/ext/numo/narray/numo/types/uint32.h +0 -1
  63. data/ext/numo/narray/numo/types/uint64.h +0 -1
  64. data/ext/numo/narray/numo/types/uint8.h +1 -2
  65. data/ext/numo/narray/numo/types/xint_macro.h +2 -0
  66. data/ext/numo/narray/step.c +58 -252
  67. data/ext/numo/narray/struct.c +3 -3
  68. data/lib/numo/narray.rb +1 -7
  69. data/lib/numo/narray/extra.rb +214 -213
  70. data/numo-narray.gemspec +7 -8
  71. metadata +17 -36
@@ -12,6 +12,7 @@ static VALUE
12
12
  if (na->size > 0 && ptr == NULL) {
13
13
  ptr = xmalloc(((na->size-1)/8/sizeof(BIT_DIGIT)+1)*sizeof(BIT_DIGIT));
14
14
  NA_DATA_PTR(na) = ptr;
15
+ NA_DATA_OWNED(na) = TRUE;
15
16
  }
16
17
  break;
17
18
  case NARRAY_VIEW_T:
@@ -1,40 +1,32 @@
1
1
  /*
2
- Array element referenece or slice view.
2
+ Multi-dimensional element reference.
3
3
  @overload [](dim0,...,dimL)
4
- @param [Numeric,Range,etc] dim0,...,dimL Multi-dimensional Index.
5
- @return [Numeric,NArray::<%=class_name%>] Element object or NArray view.
6
-
7
- --- Returns the element at +dim0+, +dim1+, ... are Numeric indices
8
- for each dimension, or returns a NArray View as a sliced subarray if
9
- +dim0+, +dim1+, ... includes other than Numeric index, e.g., Range
10
- or Array or true.
4
+ @param [Numeric,Range,Array,Numo::Int32,Numo::Int64,Numo::Bit,TrueClass,FalseClass,Symbol] dim0,...,dimL multi-dimensional indices.
5
+ @return [Numeric,Numo::Bit] an element or NArray view.
6
+ @see Numo::NArray#[]
7
+ @see #[]=
11
8
 
12
9
  @example
13
- a = Numo::DFloat.new(4,5).seq
14
- => Numo::DFloat#shape=[4,5]
15
- [[0, 1, 2, 3, 4],
16
- [5, 6, 7, 8, 9],
17
- [10, 11, 12, 13, 14],
18
- [15, 16, 17, 18, 19]]
19
-
20
- a[1,1]
21
- => 6.0
10
+ a = Numo::Int32.new(3,4).seq
11
+ # => Numo::Int32#shape=[3,4]
12
+ # [[0, 1, 2, 3],
13
+ # [4, 5, 6, 7],
14
+ # [8, 9, 10, 11]]
22
15
 
23
- a[1..3,1]
24
- => Numo::DFloat#shape=[3]
25
- [6, 11, 16]
16
+ b = (a%2).eq(0)
17
+ # => Numo::Bit#shape=[3,4]
18
+ # [[1, 0, 1, 0],
19
+ # [1, 0, 1, 0],
20
+ # [1, 0, 1, 0]]
26
21
 
27
- a[1,[1,3,4]]
28
- => Numo::DFloat#shape=[3]
29
- [6, 8, 9]
22
+ b[true,(0..-1)%2]
23
+ # => Numo::Bit(view)#shape=[3,2]
24
+ # [[1, 1],
25
+ # [1, 1],
26
+ # [1, 1]]
30
27
 
31
- a[true,2].fill(99)
32
- a
33
- => Numo::DFloat#shape=[4,5]
34
- [[0, 1, 99, 3, 4],
35
- [5, 6, 99, 8, 9],
36
- [10, 11, 99, 13, 14],
37
- [15, 16, 99, 18, 19]]
28
+ b[1,1]
29
+ # => 0
38
30
  */
39
31
  static VALUE
40
32
  <%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
@@ -1,41 +1,27 @@
1
1
  /*
2
- Array element(s) set.
3
- @overload []=(dim0,..,dimL,val)
4
- @param [Numeric,Range,etc] dim0,..,dimL Multi-dimensional Index.
5
- @param [Numeric,Numo::NArray,etc] val Value(s) to be set to self.
6
- @return [Numeric] returns val (last argument).
7
-
8
- --- Replace element(s) at +dim0+, +dim1+, ... (index/range/array/true
9
- for each dimention). Broadcasting mechanism is applied.
2
+ Multi-dimensional element assignment.
3
+ @overload []=(dim0,...,dimL,val)
4
+ @param [Numeric,Range,Array,Numo::Int32,Numo::Int64,Numo::Bit,TrueClass,FalseClass,Symbol] dim0,...,dimL multi-dimensional indices.
5
+ @param [Numeric,Numo::NArray,Array] val Value(s) to be set to self.
6
+ @return [Numeric,Numo::NArray,Array] returns `val` (last argument).
7
+ @see Numo::NArray#[]=
8
+ @see #[]
10
9
 
11
10
  @example
12
- a = Numo::DFloat.new(3,4).seq
13
- => Numo::DFloat#shape=[3,4]
14
- [[0, 1, 2, 3],
15
- [4, 5, 6, 7],
16
- [8, 9, 10, 11]]
17
-
18
- a[1,2]=99
19
- a
20
- => Numo::DFloat#shape=[3,4]
21
- [[0, 1, 2, 3],
22
- [4, 5, 99, 7],
23
- [8, 9, 10, 11]]
24
-
25
- a[1,[0,2]] = [101,102]
11
+ a = Numo::Bit.new(4,5).fill(0)
12
+ # => Numo::Bit#shape=[4,5]
13
+ # [[0, 0, 0, 0, 0],
14
+ # [0, 0, 0, 0, 0],
15
+ # [0, 0, 0, 0, 0],
16
+ # [0, 0, 0, 0, 0]]
17
+
18
+ a[(0..-1)%2,(1..-1)%2] = 1
26
19
  a
27
- => Numo::DFloat#shape=[3,4]
28
- [[0, 1, 2, 3],
29
- [101, 5, 102, 7],
30
- [8, 9, 10, 11]]
31
-
32
- a[1,true]=99
33
- a
34
- => Numo::DFloat#shape=[3,4]
35
- [[0, 1, 2, 3],
36
- [99, 99, 99, 99],
37
- [8, 9, 10, 11]]
38
-
20
+ # => Numo::Bit#shape=[4,5]
21
+ # [[0, 1, 0, 1, 0],
22
+ # [0, 0, 0, 0, 0],
23
+ # [0, 1, 0, 1, 0],
24
+ # [0, 0, 0, 0, 0]]
39
25
  */
40
26
  static VALUE
41
27
  <%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
@@ -21,10 +21,14 @@ static void
21
21
  STORE_BIT_STEP(a3, p3, s3, idx3, x);
22
22
  }
23
23
  } else {
24
- o1 = p1 % NB;
25
- o1 -= p3;
26
- o2 = p2 % NB;
27
- o2 -= p3;
24
+ a1 += p1/NB;
25
+ p1 %= NB;
26
+ a2 += p2/NB;
27
+ p2 %= NB;
28
+ a3 += p3/NB;
29
+ p3 %= NB;
30
+ o1 = p1-p3;
31
+ o2 = p2-p3;
28
32
  l1 = NB+o1;
29
33
  r1 = NB-o1;
30
34
  l2 = NB+o2;
@@ -54,23 +58,53 @@ static void
54
58
  }
55
59
  } else {
56
60
  for (; n>=NB; n-=NB) {
57
- x = *a1>>o1;
58
- if (o1<0) x |= *(a1-1)>>l1;
59
- if (o1>0) x |= *(a1+1)<<r1;
61
+ if (o1==0) {
62
+ x = *a1;
63
+ } else if (o1>0) {
64
+ x = *a1>>o1 | *(a1+1)<<r1;
65
+ } else {
66
+ x = *a1<<-o1 | *(a1-1)>>l1;
67
+ }
60
68
  a1++;
61
- y = *a2>>o2;
62
- if (o2<0) y |= *(a2-1)>>l2;
63
- if (o2>0) y |= *(a2+1)<<r2;
69
+ if (o2==0) {
70
+ y = *a2;
71
+ } else if (o2>0) {
72
+ y = *a2>>o2 | *(a2+1)<<r2;
73
+ } else {
74
+ y = *a2<<-o2 | *(a2-1)>>l2;
75
+ }
64
76
  a2++;
65
77
  x = m_<%=name%>(x,y);
66
78
  *(a3++) = x;
67
79
  }
68
80
  }
69
81
  if (n>0) {
70
- x = *a1>>o1;
71
- if (o1<0) x |= *(a1-1)>>l1;
72
- y = *a2>>o2;
73
- if (o2<0) y |= *(a2-1)>>l2;
82
+ if (o1==0) {
83
+ x = *a1;
84
+ } else if (o1>0) {
85
+ x = *a1>>o1;
86
+ if ((int)n>r1) {
87
+ x |= *(a1+1)<<r1;
88
+ }
89
+ } else {
90
+ x = *(a1-1)>>l1;
91
+ if ((int)n>-o1) {
92
+ x |= *a1<<-o1;
93
+ }
94
+ }
95
+ if (o2==0) {
96
+ y = *a2;
97
+ } else if (o2>0) {
98
+ y = *a2>>o2;
99
+ if ((int)n>r2) {
100
+ y |= *(a2+1)<<r2;
101
+ }
102
+ } else {
103
+ y = *(a2-1)>>l2;
104
+ if ((int)n>-o2) {
105
+ y |= *a2<<-o2;
106
+ }
107
+ }
74
108
  x = m_<%=name%>(x,y);
75
109
  *a3 = (x & SLB(n)) | (*a3 & BALL<<n);
76
110
  }
@@ -75,10 +75,15 @@ static VALUE
75
75
  <%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
76
76
  {
77
77
  VALUE v, reduce;
78
+ narray_t *na;
78
79
  ndfunc_arg_in_t ain[3] = {{cT,0},{sym_reduce,0},{sym_init,0}};
79
80
  ndfunc_arg_out_t aout[1] = {{numo_cInt64,0}};
80
81
  ndfunc_t ndf = { <%=c_iter%>, FULL_LOOP_NIP, 3, 1, ain, aout };
81
82
 
83
+ GetNArray(self,na);
84
+ if (NA_SIZE(na)==0) {
85
+ return INT2FIX(0);
86
+ }
82
87
  reduce = na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
83
88
  v = na_ndloop(&ndf, 3, self, reduce, INT2FIX(0));
84
89
  return rb_funcall(v,rb_intern("extract"),0);
@@ -107,10 +107,15 @@ static VALUE
107
107
  <%=c_func(-1)%>(int argc, VALUE *argv, VALUE self)
108
108
  {
109
109
  VALUE v, reduce;
110
+ narray_t *na;
110
111
  ndfunc_arg_in_t ain[3] = {{cT,0},{sym_reduce,0},{sym_init,0}};
111
112
  ndfunc_arg_out_t aout[1] = {{numo_cBit,0}};
112
113
  ndfunc_t ndf = {<%=c_iter%>, FULL_LOOP_NIP, 3,1, ain,aout};
113
114
 
115
+ GetNArray(self,na);
116
+ if (NA_SIZE(na)==0) {
117
+ return Qfalse;
118
+ }
114
119
  reduce = na_reduce_dimension(argc, argv, 1, &self, &ndf, 0);
115
120
  v = na_ndloop(&ndf, 3, self, reduce, INT2FIX(<%=init_bit%>));
116
121
  if (argc > 0) {
@@ -48,7 +48,13 @@ static void
48
48
  if (idx1) {
49
49
  for (i=i1=0; i1<n1 && i<n; i++,i1++) {
50
50
  x = ptr[i1];
51
- if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, na_cStep)) {
51
+ if (rb_obj_is_kind_of(x, rb_cRange)
52
+ #ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
53
+ || rb_obj_is_kind_of(x, rb_cArithSeq)
54
+ #else
55
+ || rb_obj_is_kind_of(x, rb_cEnumerator)
56
+ #endif
57
+ ) {
52
58
  nary_step_sequence(x,&len,&beg,&step);
53
59
  for (c=0; c<len && i<n; c++,i++) {
54
60
  y = beg + step * c;
@@ -65,7 +71,13 @@ static void
65
71
  } else {
66
72
  for (i=i1=0; i1<n1 && i<n; i++,i1++) {
67
73
  x = ptr[i1];
68
- if (rb_obj_is_kind_of(x, rb_cRange) || rb_obj_is_kind_of(x, na_cStep)) {
74
+ if (rb_obj_is_kind_of(x, rb_cRange)
75
+ #ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
76
+ || rb_obj_is_kind_of(x, rb_cArithSeq)
77
+ #else
78
+ || rb_obj_is_kind_of(x, rb_cEnumerator)
79
+ #endif
80
+ ) {
69
81
  nary_step_sequence(x,&len,&beg,&step);
70
82
  for (c=0; c<len && i<n; c++,i++) {
71
83
  y = beg + step * c;
@@ -2,7 +2,7 @@ static void
2
2
  <%=c_iter%>(na_loop_t *const lp)
3
3
  {
4
4
  size_t n;
5
- size_t p1, p3;
5
+ ssize_t p1, p3;
6
6
  ssize_t s1, s3;
7
7
  size_t *idx1, *idx3;
8
8
  int o1, l1, r1, len;
@@ -18,8 +18,11 @@ static void
18
18
  STORE_BIT_STEP(a3, p3, s3, idx3, x);
19
19
  }
20
20
  } else {
21
- o1 = p1 % NB;
22
- o1 -= p3;
21
+ a1 += p1/NB;
22
+ p1 %= NB;
23
+ a3 += p3/NB;
24
+ p3 %= NB;
25
+ o1 = p1-p3;
23
26
  l1 = NB+o1;
24
27
  r1 = NB-o1;
25
28
  if (p3>0 || n<NB) {
@@ -27,7 +30,7 @@ static void
27
30
  if ((int)n<len) len=n;
28
31
  if (o1>=0) x = *a1>>o1;
29
32
  else x = *a1<<-o1;
30
- if (p1+len>NB) x |= *(a1+1)<<r1;
33
+ if (p1+len>(ssize_t)NB) x |= *(a1+1)<<r1;
31
34
  a1++;
32
35
  *a3 = (x & (SLB(len)<<p3)) | (*a3 & ~(SLB(len)<<p3));
33
36
  a3++;
@@ -40,16 +43,31 @@ static void
40
43
  }
41
44
  } else {
42
45
  for (; n>=NB; n-=NB) {
43
- x = *a1>>o1;
44
- if (o1<0) x |= *(a1-1)>>l1;
45
- if (o1>0) x |= *(a1+1)<<r1;
46
+ if (o1==0) {
47
+ x = *a1;
48
+ } else if (o1>0) {
49
+ x = *a1>>o1 | *(a1+1)<<r1;
50
+ } else {
51
+ x = *a1<<-o1 | *(a1-1)>>l1;
52
+ }
46
53
  a1++;
47
54
  *(a3++) = x;
48
55
  }
49
56
  }
50
57
  if (n>0) {
51
- x = *a1>>o1;
52
- if (o1<0) x |= *(a1-1)>>l1;
58
+ if (o1==0) {
59
+ x = *a1;
60
+ } else if (o1>0) {
61
+ x = *a1>>o1;
62
+ if ((int)n>r1) {
63
+ x |= *(a1+1)<<r1;
64
+ }
65
+ } else {
66
+ x = *(a1-1)>>l1;
67
+ if ((int)n>-o1) {
68
+ x |= *a1<<-o1;
69
+ }
70
+ }
53
71
  *a3 = (x & SLB(n)) | (*a3 & BALL<<n);
54
72
  }
55
73
  }
@@ -20,8 +20,11 @@ static void
20
20
  STORE_BIT_STEP(a3, p3, s3, idx3, y);
21
21
  }
22
22
  } else {
23
- o1 = p1 % NB;
24
- o1 -= p3;
23
+ a1 += p1/NB;
24
+ p1 %= NB;
25
+ a3 += p3/NB;
26
+ p3 %= NB;
27
+ o1 = p1-p3;
25
28
  l1 = NB+o1;
26
29
  r1 = NB-o1;
27
30
  if (p3>0 || n<NB) {
@@ -44,17 +47,32 @@ static void
44
47
  }
45
48
  } else {
46
49
  for (; n>=NB; n-=NB) {
47
- x = *a1>>o1;
48
- if (o1<0) x |= *(a1-1)>>l1;
49
- if (o1>0) x |= *(a1+1)<<r1;
50
+ if (o1==0) {
51
+ x = *a1;
52
+ } else if (o1>0) {
53
+ x = *a1>>o1 | *(a1+1)<<r1;
54
+ } else {
55
+ x = *a1<<-o1 | *(a1-1)>>l1;
56
+ }
50
57
  a1++;
51
58
  y = m_<%=name%>(x);
52
59
  *(a3++) = y;
53
60
  }
54
61
  }
55
62
  if (n>0) {
56
- x = *a1>>o1;
57
- if (o1<0) x |= *(a1-1)>>l1;
63
+ if (o1==0) {
64
+ x = *a1;
65
+ } else if (o1>0) {
66
+ x = *a1>>o1;
67
+ if ((int)n>r1) {
68
+ x |= *(a1+1)<<r1;
69
+ }
70
+ } else {
71
+ x = *(a1-1)>>l1;
72
+ if ((int)n>-o1) {
73
+ x |= *a1<<-o1;
74
+ }
75
+ }
58
76
  y = m_<%=name%>(x);
59
77
  *a3 = (y & SLB(n)) | (*a3 & BALL<<n);
60
78
  }
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  index.c
3
- Numerical Array Extension for Ruby
4
- (C) Copyright 1999-2017 by Masahiro TANAKA
3
+ Ruby/Numo::NArray - Numerical Array class for Ruby
4
+ Copyright (C) 1999-2020 Masahiro TANAKA
5
5
  */
6
6
  //#define NARRAY_C
7
7
 
@@ -16,24 +16,6 @@
16
16
  #define cIndex numo_cInt32
17
17
  #endif
18
18
 
19
- // from ruby/enumerator.c
20
- struct enumerator {
21
- VALUE obj;
22
- ID meth;
23
- VALUE args;
24
- // use only above in this source
25
- VALUE fib;
26
- VALUE dst;
27
- VALUE lookahead;
28
- VALUE feedvalue;
29
- VALUE stop_exc;
30
- VALUE size;
31
- // incompatible below depending on ruby version
32
- //VALUE procs; // ruby 2.4
33
- //rb_enumerator_size_func *size_fn; // ruby 2.1-2.4
34
- //VALUE (*size_fn)(ANYARGS); // ruby 2.0
35
- };
36
-
37
19
  // note: the memory refed by this pointer is not freed and causes memroy leak.
38
20
  typedef struct {
39
21
  size_t n; // the number of elements of the dimesnion
@@ -80,6 +62,7 @@ static ID id_dup;
80
62
  static ID id_bracket;
81
63
  static ID id_shift_left;
82
64
  static ID id_mask;
65
+ static ID id_where;
83
66
 
84
67
 
85
68
  static void
@@ -142,25 +125,66 @@ na_parse_array(VALUE ary, int orig_dim, ssize_t size, na_index_arg_t *q)
142
125
  static void
143
126
  na_parse_narray_index(VALUE a, int orig_dim, ssize_t size, na_index_arg_t *q)
144
127
  {
145
- VALUE idx;
146
- narray_t *na;
147
- narray_data_t *nidx;
128
+ VALUE idx, cls;
129
+ narray_t *na, *nidx;
148
130
  size_t k, n;
149
- ssize_t *nidxp;
150
131
 
151
132
  GetNArray(a,na);
152
133
  if (NA_NDIM(na) != 1) {
153
134
  rb_raise(rb_eIndexError, "should be 1-d NArray");
154
135
  }
155
- n = NA_SIZE(na);
156
- idx = nary_new(cIndex,1,&n);
157
- na_store(idx,a);
158
-
159
- GetNArrayData(idx,nidx);
160
- nidxp = (ssize_t*)nidx->ptr;
161
- q->idx = ALLOC_N(size_t, n);
162
- for (k=0; k<n; k++) {
163
- q->idx[k] = na_range_check(nidxp[k], size, orig_dim);
136
+ cls = rb_obj_class(a);
137
+ if (cls==numo_cBit) {
138
+ if (NA_SIZE(na) != (size_t)size) {
139
+ rb_raise(rb_eIndexError, "Bit-NArray size mismatch");
140
+ }
141
+ idx = rb_funcall(a,id_where,0);
142
+ GetNArray(idx,nidx);
143
+ n = NA_SIZE(nidx);
144
+ q->idx = ALLOC_N(size_t, n);
145
+ if (na->type!=NARRAY_DATA_T) {
146
+ rb_bug("NArray#where returned wrong type of NArray");
147
+ }
148
+ if (rb_obj_class(idx)==numo_cInt32) {
149
+ int32_t *p = (int32_t*)NA_DATA_PTR(nidx);
150
+ for (k=0; k<n; k++) {
151
+ q->idx[k] = (size_t)p[k];
152
+ }
153
+ } else
154
+ if (rb_obj_class(idx)==numo_cInt64) {
155
+ int64_t *p = (int64_t*)NA_DATA_PTR(nidx);
156
+ for (k=0; k<n; k++) {
157
+ q->idx[k] = (size_t)p[k];
158
+ }
159
+ } else {
160
+ rb_bug("NArray#where should return Int32 or Int64");
161
+ }
162
+ RB_GC_GUARD(idx);
163
+ } else {
164
+ n = NA_SIZE(na);
165
+ q->idx = ALLOC_N(size_t, n);
166
+ if (cls==numo_cInt32 && na->type==NARRAY_DATA_T) {
167
+ int32_t *p = (int32_t*)NA_DATA_PTR(na);
168
+ for (k=0; k<n; k++) {
169
+ q->idx[k] = na_range_check(p[k], size, orig_dim);
170
+ }
171
+ } else
172
+ if (cls==numo_cInt64 && na->type==NARRAY_DATA_T) {
173
+ int64_t *p = (int64_t*)NA_DATA_PTR(na);
174
+ for (k=0; k<n; k++) {
175
+ q->idx[k] = na_range_check(p[k], size, orig_dim);
176
+ }
177
+ } else {
178
+ ssize_t *p;
179
+ idx = nary_new(cIndex,1,&n);
180
+ na_store(idx,a);
181
+ GetNArray(idx,nidx);
182
+ p = (ssize_t*)NA_DATA_PTR(nidx);
183
+ for (k=0; k<n; k++) {
184
+ q->idx[k] = na_range_check(p[k], size, orig_dim);
185
+ }
186
+ RB_GC_GUARD(idx);
187
+ }
164
188
  }
165
189
  q->n = n;
166
190
  q->beg = 0;
@@ -173,10 +197,46 @@ static void
173
197
  na_parse_range(VALUE range, ssize_t step, int orig_dim, ssize_t size, na_index_arg_t *q)
174
198
  {
175
199
  int n;
176
- VALUE excl_end;
177
200
  ssize_t beg, end, beg_orig, end_orig;
178
201
  const char *dot = "..", *edot = "...";
179
202
 
203
+ #ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
204
+ rb_arithmetic_sequence_components_t x;
205
+ rb_arithmetic_sequence_extract(range, &x);
206
+ step = NUM2SSIZET(x.step);
207
+
208
+ beg = beg_orig = NUM2SSIZET(x.begin);
209
+ if (beg < 0) {
210
+ beg += size;
211
+ }
212
+ if (T_NIL == TYPE(x.end)) { // endless range
213
+ end = size - 1;
214
+ if (RTEST(x.exclude_end)) {
215
+ dot = edot;
216
+ }
217
+ if (beg < 0 || beg >= size) {
218
+ rb_raise(rb_eRangeError,
219
+ "%"SZF"d%s is out of range for size=%"SZF"d",
220
+ beg_orig, dot, size);
221
+ }
222
+ } else {
223
+ end = end_orig = NUM2SSIZET(x.end);
224
+ if (end < 0) {
225
+ end += size;
226
+ }
227
+ if (RTEST(x.exclude_end)) {
228
+ end--;
229
+ dot = edot;
230
+ }
231
+ if (beg < 0 || beg >= size || end < 0 || end >= size) {
232
+ rb_raise(rb_eRangeError,
233
+ "%"SZF"d%s%"SZF"d is out of range for size=%"SZF"d",
234
+ beg_orig, dot, end_orig, size);
235
+ }
236
+ }
237
+ #else
238
+ VALUE excl_end;
239
+
180
240
  beg = beg_orig = NUM2SSIZET(rb_funcall(range,id_beg,0));
181
241
  if (beg < 0) {
182
242
  beg += size;
@@ -195,17 +255,18 @@ na_parse_range(VALUE range, ssize_t step, int orig_dim, ssize_t size, na_index_a
195
255
  "%"SZF"d%s%"SZF"d is out of range for size=%"SZF"d",
196
256
  beg_orig, dot, end_orig, size);
197
257
  }
258
+ #endif
198
259
  n = (end-beg)/step+1;
199
260
  if (n<0) n=0;
200
261
  na_index_set_step(q,orig_dim,n,beg,step);
201
262
 
202
263
  }
203
264
 
204
- static void
205
- na_parse_enumerator(VALUE enum_obj, int orig_dim, ssize_t size, na_index_arg_t *q)
265
+ void
266
+ na_parse_enumerator_step(VALUE enum_obj, VALUE *pstep )
206
267
  {
207
268
  int len;
208
- ssize_t step;
269
+ VALUE step;
209
270
  struct enumerator *e;
210
271
 
211
272
  if (!RB_TYPE_P(enum_obj, T_DATA)) {
@@ -213,26 +274,40 @@ na_parse_enumerator(VALUE enum_obj, int orig_dim, ssize_t size, na_index_arg_t *
213
274
  }
214
275
  e = (struct enumerator *)DATA_PTR(enum_obj);
215
276
 
216
- if (rb_obj_is_kind_of(e->obj, rb_cRange)) {
217
- if (e->meth == id_each) {
218
- na_parse_range(e->obj, 1, orig_dim, size, q);
277
+ if (!rb_obj_is_kind_of(e->obj, rb_cRange)) {
278
+ rb_raise(rb_eTypeError,"not Range object");
279
+ }
280
+
281
+ if (e->meth == id_each) {
282
+ step = INT2NUM(1);
283
+ }
284
+ else if (e->meth == id_step) {
285
+ if (TYPE(e->args) != T_ARRAY) {
286
+ rb_raise(rb_eArgError,"no argument for step");
219
287
  }
220
- else if (e->meth == id_step) {
221
- if (TYPE(e->args) != T_ARRAY) {
222
- rb_raise(rb_eArgError,"no argument for step");
223
- }
224
- len = RARRAY_LEN(e->args);
225
- if (len != 1) {
226
- rb_raise(rb_eArgError,"invalid number of step argument (1 for %d)",len);
227
- }
228
- step = NUM2SSIZET(RARRAY_AREF(e->args,0));
229
- na_parse_range(e->obj, step, orig_dim, size, q);
230
- } else {
231
- rb_raise(rb_eTypeError,"unknown Range method: %s",rb_id2name(e->meth));
288
+ len = RARRAY_LEN(e->args);
289
+ if (len != 1) {
290
+ rb_raise(rb_eArgError,"invalid number of step argument (1 for %d)",len);
232
291
  }
292
+ step = RARRAY_AREF(e->args,0);
233
293
  } else {
234
- rb_raise(rb_eTypeError,"not Range object");
294
+ rb_raise(rb_eTypeError,"unknown Range method: %s",rb_id2name(e->meth));
295
+ }
296
+ if (pstep) *pstep = step;
297
+ }
298
+
299
+ static void
300
+ na_parse_enumerator(VALUE enum_obj, int orig_dim, ssize_t size, na_index_arg_t *q)
301
+ {
302
+ VALUE step;
303
+ struct enumerator *e;
304
+
305
+ if (!RB_TYPE_P(enum_obj, T_DATA)) {
306
+ rb_raise(rb_eTypeError,"wrong argument type (not T_DATA)");
235
307
  }
308
+ na_parse_enumerator_step(enum_obj, &step);
309
+ e = (struct enumerator *)DATA_PTR(enum_obj);
310
+ na_parse_range(e->obj, NUM2SSIZET(step), orig_dim, size, q); // e->obj : Range Object
236
311
  }
237
312
 
238
313
  // Analyze *a* which is *i*-th index object and store the information to q
@@ -289,14 +364,15 @@ na_index_parse_each(volatile VALUE a, ssize_t size, int i, na_index_arg_t *q)
289
364
  if (rb_obj_is_kind_of(a, rb_cRange)) {
290
365
  na_parse_range(a, 1, i, size, q);
291
366
  }
367
+ #ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
368
+ else if (rb_obj_is_kind_of(a, rb_cArithSeq)) {
369
+ //na_parse_arith_seq(a, i, size, q);
370
+ na_parse_range(a, 1, i, size, q);
371
+ }
372
+ #endif
292
373
  else if (rb_obj_is_kind_of(a, rb_cEnumerator)) {
293
374
  na_parse_enumerator(a, i, size, q);
294
375
  }
295
- else if (rb_obj_is_kind_of(a, na_cStep)) {
296
- ssize_t beg, step, n;
297
- nary_step_array_index(a, size, (size_t*)(&n), &beg, &step);
298
- na_index_set_step(q,i,n,beg,step);
299
- }
300
376
  // NArray index
301
377
  else if (NA_IsNArray(a)) {
302
378
  na_parse_narray_index(a, i, size, q);
@@ -308,6 +384,102 @@ na_index_parse_each(volatile VALUE a, ssize_t size, int i, na_index_arg_t *q)
308
384
  }
309
385
 
310
386
 
387
+ static void
388
+ na_at_parse_each(volatile VALUE a, ssize_t size, int i, VALUE *idx, ssize_t stride)
389
+ {
390
+ na_index_arg_t q;
391
+ size_t n, k;
392
+ ssize_t *index;
393
+
394
+ // NArray index
395
+ if (NA_IsNArray(a)) {
396
+ VALUE a2;
397
+ narray_t *na, *na2;
398
+ ssize_t *p2;
399
+ GetNArray(a,na);
400
+ if (NA_NDIM(na) != 1) {
401
+ rb_raise(rb_eIndexError, "should be 1-d NArray");
402
+ }
403
+ n = NA_SIZE(na);
404
+ a2 = nary_new(cIndex,1,&n);
405
+ na_store(a2,a);
406
+ GetNArray(a2,na2);
407
+ p2 = (ssize_t*)NA_DATA_PTR(na2);
408
+ if (*idx == Qnil) {
409
+ *idx = a2;
410
+ for (k=0; k<n; k++) {
411
+ na_range_check(p2[k],size,i);
412
+ }
413
+ } else {
414
+ narray_t *nidx;
415
+ GetNArray(*idx,nidx);
416
+ index = (ssize_t*)NA_DATA_PTR(nidx);
417
+ if (NA_SIZE(nidx) != n) {
418
+ rb_raise(nary_eShapeError, "index array sizes mismatch");
419
+ }
420
+ for (k=0; k<n; k++) {
421
+ index[k] += na_range_check(p2[k],size,i) * stride;
422
+ }
423
+ }
424
+ RB_GC_GUARD(a2);
425
+ return;
426
+ }
427
+ else if (TYPE(a) == T_ARRAY) {
428
+ n = RARRAY_LEN(a);
429
+ if (*idx == Qnil) {
430
+ *idx = nary_new(cIndex,1,&n);
431
+ index = (ssize_t*)na_get_pointer_for_write(*idx); // allocate memory
432
+ for (k=0; k<n; k++) {
433
+ index[k] = na_range_check(NUM2SSIZET(RARRAY_AREF(a,k)),size,i);
434
+ }
435
+ } else {
436
+ narray_t *nidx;
437
+ GetNArray(*idx,nidx);
438
+ index = (ssize_t*)NA_DATA_PTR(nidx);
439
+ if (NA_SIZE(nidx) != n) {
440
+ rb_raise(nary_eShapeError, "index array sizes mismatch");
441
+ }
442
+ for (k=0; k<n; k++) {
443
+ index[k] += na_range_check(NUM2SSIZET(RARRAY_AREF(a,k)),size,i) * stride;
444
+ }
445
+ }
446
+ return;
447
+ }
448
+ else if (rb_obj_is_kind_of(a, rb_cRange)) {
449
+ na_parse_range(a, 1, i, size, &q);
450
+ }
451
+ #ifdef HAVE_RB_ARITHMETIC_SEQUENCE_EXTRACT
452
+ else if (rb_obj_is_kind_of(a, rb_cArithSeq)) {
453
+ na_parse_range(a, 1, i, size, &q);
454
+ }
455
+ #endif
456
+ else if (rb_obj_is_kind_of(a, rb_cEnumerator)) {
457
+ na_parse_enumerator(a, i, size, &q);
458
+ }
459
+ else {
460
+ rb_raise(rb_eIndexError, "not allowed type");
461
+ }
462
+
463
+ if (*idx == Qnil) {
464
+ *idx = nary_new(cIndex,1,&q.n);
465
+ index = (ssize_t*)na_get_pointer_for_write(*idx); // allocate memory
466
+ for (k=0; k<q.n; k++) {
467
+ index[k] = q.beg + q.step*k;
468
+ }
469
+ } else {
470
+ narray_t *nidx;
471
+ GetNArray(*idx,nidx);
472
+ index = (ssize_t*)NA_DATA_PTR(nidx);
473
+ if (NA_SIZE(nidx) != q.n) {
474
+ rb_raise(nary_eShapeError, "index array sizes mismatch");
475
+ }
476
+ for (k=0; k<q.n; k++) {
477
+ index[k] += (q.beg + q.step*k) * stride;
478
+ }
479
+ }
480
+ }
481
+
482
+
311
483
  static size_t
312
484
  na_index_parse_args(VALUE args, narray_t *na, na_index_arg_t *q, int ndim)
313
485
  {
@@ -574,7 +746,7 @@ VALUE na_aref_md_protected(VALUE data_value)
574
746
 
575
747
  na_alloc_shape((narray_t*)na2, ndim_new);
576
748
 
577
- na2->stridx = ALLOC_N(stridx_t,ndim_new);
749
+ na2->stridx = ZALLOC_N(stridx_t,ndim_new);
578
750
 
579
751
  elmsz = nary_element_stride(self);
580
752
 
@@ -842,11 +1014,142 @@ static VALUE na_slice(int argc, VALUE *argv, VALUE self)
842
1014
  return na_aref_main(argc, argv, self, 1, nd);
843
1015
  }
844
1016
 
1017
+ /*
1018
+ Multi-dimensional element reference.
1019
+ Returns an element at `dim0`, `dim1`, ... are Numeric indices for each dimension, or returns a NArray View as a sliced array if `dim0`, `dim1`, ... includes other than Numeric index, e.g., Range or Array or true.
1020
+ @overload [](dim0,...,dimL)
1021
+ @param [Numeric,Range,Array,Numo::Int32,Numo::Int64,Numo::Bit,TrueClass,FalseClass,Symbol] dim0,...,dimL multi-dimensional indices.
1022
+ @return [Numeric,Numo::NArray] an element or NArray view.
1023
+ @see #[]=
1024
+ @see #at
1025
+
1026
+ @example
1027
+ a = Numo::DFloat.new(4,5).seq
1028
+ # => Numo::DFloat#shape=[4,5]
1029
+ # [[0, 1, 2, 3, 4],
1030
+ # [5, 6, 7, 8, 9],
1031
+ # [10, 11, 12, 13, 14],
1032
+ # [15, 16, 17, 18, 19]]
1033
+
1034
+ a[1,1]
1035
+ # => 6.0
1036
+
1037
+ a[1..3,1]
1038
+ # => Numo::DFloat#shape=[3]
1039
+ # [6, 11, 16]
1040
+
1041
+ a[1,[1,3,4]]
1042
+ # => Numo::DFloat#shape=[3]
1043
+ # [6, 8, 9]
1044
+
1045
+ a[true,2].fill(99)
1046
+ a
1047
+ # => Numo::DFloat#shape=[4,5]
1048
+ # [[0, 1, 99, 3, 4],
1049
+ # [5, 6, 99, 8, 9],
1050
+ # [10, 11, 99, 13, 14],
1051
+ # [15, 16, 99, 18, 19]]
1052
+ */
1053
+ // implemented in subclasses
1054
+ #define na_aref rb_f_notimplement
1055
+
1056
+ /*
1057
+ Multi-dimensional element assignment.
1058
+ Replace element(s) at `dim0`, `dim1`, ... .
1059
+ Broadcasting mechanism is applied.
1060
+ @overload []=(dim0,...,dimL,val)
1061
+ @param [Numeric,Range,Array,Numo::Int32,Numo::Int64,Numo::Bit,TrueClass,FalseClass,Symbol] dim0,...,dimL multi-dimensional indices.
1062
+ @param [Numeric,Numo::NArray,Array] val Value(s) to be set to self.
1063
+ @return [Numeric,Numo::NArray,Array] returns `val` (last argument).
1064
+ @see #[]
1065
+ @example
1066
+ a = Numo::DFloat.new(3,4).seq
1067
+ # => Numo::DFloat#shape=[3,4]
1068
+ # [[0, 1, 2, 3],
1069
+ # [4, 5, 6, 7],
1070
+ # [8, 9, 10, 11]]
1071
+
1072
+ a[1,2]=99
1073
+ a
1074
+ # => Numo::DFloat#shape=[3,4]
1075
+ # [[0, 1, 2, 3],
1076
+ # [4, 5, 99, 7],
1077
+ # [8, 9, 10, 11]]
1078
+
1079
+ a[1,[0,2]] = [101,102]
1080
+ a
1081
+ # => Numo::DFloat#shape=[3,4]
1082
+ # [[0, 1, 2, 3],
1083
+ # [101, 5, 102, 7],
1084
+ # [8, 9, 10, 11]]
1085
+
1086
+ a[1,true]=99
1087
+ a
1088
+ # => Numo::DFloat#shape=[3,4]
1089
+ # [[0, 1, 2, 3],
1090
+ # [99, 99, 99, 99],
1091
+ # [8, 9, 10, 11]]
1092
+
1093
+ */
1094
+ // implemented in subclasses
1095
+ #define na_aset rb_f_notimplement
1096
+
1097
+ /*
1098
+ Multi-dimensional array indexing.
1099
+ Similar to numpy's tuple indexing, i.e., `a[[1,2,..],[3,4,..]]`
1100
+ Same as Numo::NArray#[] for one-dimensional NArray.
1101
+ @overload at(dim0,...,dimL)
1102
+ @param [Range,Array,Numo::Int32,Numo::Int64] dim0,...,dimL multi-dimensional index arrays.
1103
+ @return [Numo::NArray] one-dimensional NArray view.
1104
+ @see #[]
1105
+
1106
+ @example
1107
+ x = Numo::DFloat.new(3,3,3).seq
1108
+ # => Numo::DFloat#shape=[3,3,3]
1109
+ # [[[0, 1, 2],
1110
+ # [3, 4, 5],
1111
+ # [6, 7, 8]],
1112
+ # [[9, 10, 11],
1113
+ # [12, 13, 14],
1114
+ # [15, 16, 17]],
1115
+ # [[18, 19, 20],
1116
+ # [21, 22, 23],
1117
+ # [24, 25, 26]]]
1118
+
1119
+ x.at([0,1,2],[0,1,2],[-1,-2,-3])
1120
+ # => Numo::DFloat(view)#shape=[3]
1121
+ # [2, 13, 24]
1122
+ */
1123
+ static VALUE na_at(int argc, VALUE *argv, VALUE self)
1124
+ {
1125
+ int i;
1126
+ size_t n;
1127
+ ssize_t stride=1;
1128
+ narray_t *na;
1129
+ VALUE idx=Qnil;
1130
+
1131
+ na_index_arg_to_internal_order(argc, argv, self);
1132
+
1133
+ GetNArray(self,na);
1134
+ if (NA_NDIM(na) != argc) {
1135
+ rb_raise(rb_eArgError,"the number of argument must be same as dimension");
1136
+ }
1137
+ for (i=argc; i>0; ) {
1138
+ i--;
1139
+ n = NA_SHAPE(na)[i];
1140
+ na_at_parse_each(argv[i], n, i, &idx, stride);
1141
+ stride *= n;
1142
+ }
1143
+ return na_aref_main(1, &idx, self, 1, 1);
1144
+ }
845
1145
 
846
1146
  void
847
1147
  Init_nary_index()
848
1148
  {
849
1149
  rb_define_method(cNArray, "slice", na_slice, -1);
1150
+ rb_define_method(cNArray, "[]", na_aref, -1);
1151
+ rb_define_method(cNArray, "[]=", na_aset, -1);
1152
+ rb_define_method(cNArray, "at", na_at, -1);
850
1153
 
851
1154
  sym_ast = ID2SYM(rb_intern("*"));
852
1155
  sym_all = ID2SYM(rb_intern("all"));
@@ -867,4 +1170,5 @@ Init_nary_index()
867
1170
  id_bracket = rb_intern("[]");
868
1171
  id_shift_left = rb_intern("<<");
869
1172
  id_mask = rb_intern("mask");
1173
+ id_where = rb_intern("where");
870
1174
  }