numo-narray 0.9.1.4 → 0.9.1.9

Sign up to get free protection for your applications and to get access to all the features.
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
  }