numo-narray 0.9.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +50 -0
  4. data/Rakefile +64 -0
  5. data/ext/numo/narray/SFMT-params.h +97 -0
  6. data/ext/numo/narray/SFMT-params19937.h +46 -0
  7. data/ext/numo/narray/SFMT.c +620 -0
  8. data/ext/numo/narray/SFMT.h +157 -0
  9. data/ext/numo/narray/array.c +525 -0
  10. data/ext/numo/narray/data.c +901 -0
  11. data/ext/numo/narray/depend.erb +33 -0
  12. data/ext/numo/narray/extconf.rb +118 -0
  13. data/ext/numo/narray/gen/bit.erb.c +811 -0
  14. data/ext/numo/narray/gen/cogen.rb +18 -0
  15. data/ext/numo/narray/gen/def/dcomplex.rb +32 -0
  16. data/ext/numo/narray/gen/def/dfloat.rb +30 -0
  17. data/ext/numo/narray/gen/def/int16.rb +29 -0
  18. data/ext/numo/narray/gen/def/int32.rb +29 -0
  19. data/ext/numo/narray/gen/def/int64.rb +29 -0
  20. data/ext/numo/narray/gen/def/int8.rb +29 -0
  21. data/ext/numo/narray/gen/def/robject.rb +30 -0
  22. data/ext/numo/narray/gen/def/scomplex.rb +32 -0
  23. data/ext/numo/narray/gen/def/sfloat.rb +30 -0
  24. data/ext/numo/narray/gen/def/uint16.rb +29 -0
  25. data/ext/numo/narray/gen/def/uint32.rb +29 -0
  26. data/ext/numo/narray/gen/def/uint64.rb +29 -0
  27. data/ext/numo/narray/gen/def/uint8.rb +29 -0
  28. data/ext/numo/narray/gen/dtype.erb.c +328 -0
  29. data/ext/numo/narray/gen/tmpl/accum.c +36 -0
  30. data/ext/numo/narray/gen/tmpl/accum_binary.c +75 -0
  31. data/ext/numo/narray/gen/tmpl/accum_index.c +58 -0
  32. data/ext/numo/narray/gen/tmpl/allocate.c +35 -0
  33. data/ext/numo/narray/gen/tmpl/aref.c +51 -0
  34. data/ext/numo/narray/gen/tmpl/aset.c +61 -0
  35. data/ext/numo/narray/gen/tmpl/binary.c +53 -0
  36. data/ext/numo/narray/gen/tmpl/binary2.c +55 -0
  37. data/ext/numo/narray/gen/tmpl/binary_s.c +34 -0
  38. data/ext/numo/narray/gen/tmpl/bit_binary.c +94 -0
  39. data/ext/numo/narray/gen/tmpl/bit_count.c +82 -0
  40. data/ext/numo/narray/gen/tmpl/bit_unary.c +77 -0
  41. data/ext/numo/narray/gen/tmpl/cast.c +37 -0
  42. data/ext/numo/narray/gen/tmpl/cast_array.c +79 -0
  43. data/ext/numo/narray/gen/tmpl/cast_numeric.c +22 -0
  44. data/ext/numo/narray/gen/tmpl/coerce_cast.c +8 -0
  45. data/ext/numo/narray/gen/tmpl/cond_binary.c +51 -0
  46. data/ext/numo/narray/gen/tmpl/cond_unary.c +45 -0
  47. data/ext/numo/narray/gen/tmpl/cum.c +42 -0
  48. data/ext/numo/narray/gen/tmpl/each.c +43 -0
  49. data/ext/numo/narray/gen/tmpl/each_with_index.c +64 -0
  50. data/ext/numo/narray/gen/tmpl/extract.c +23 -0
  51. data/ext/numo/narray/gen/tmpl/eye.c +91 -0
  52. data/ext/numo/narray/gen/tmpl/fill.c +38 -0
  53. data/ext/numo/narray/gen/tmpl/format.c +60 -0
  54. data/ext/numo/narray/gen/tmpl/format_to_a.c +47 -0
  55. data/ext/numo/narray/gen/tmpl/head.c +25 -0
  56. data/ext/numo/narray/gen/tmpl/inspect.c +16 -0
  57. data/ext/numo/narray/gen/tmpl/map_with_index.c +94 -0
  58. data/ext/numo/narray/gen/tmpl/median.c +44 -0
  59. data/ext/numo/narray/gen/tmpl/minmax.c +47 -0
  60. data/ext/numo/narray/gen/tmpl/poly.c +49 -0
  61. data/ext/numo/narray/gen/tmpl/pow.c +74 -0
  62. data/ext/numo/narray/gen/tmpl/powint.c +17 -0
  63. data/ext/numo/narray/gen/tmpl/qsort.c +149 -0
  64. data/ext/numo/narray/gen/tmpl/rand.c +33 -0
  65. data/ext/numo/narray/gen/tmpl/rand_norm.c +46 -0
  66. data/ext/numo/narray/gen/tmpl/robj_allocate.c +32 -0
  67. data/ext/numo/narray/gen/tmpl/seq.c +61 -0
  68. data/ext/numo/narray/gen/tmpl/set2.c +56 -0
  69. data/ext/numo/narray/gen/tmpl/sort.c +36 -0
  70. data/ext/numo/narray/gen/tmpl/sort_index.c +86 -0
  71. data/ext/numo/narray/gen/tmpl/store.c +31 -0
  72. data/ext/numo/narray/gen/tmpl/store_array.c +5 -0
  73. data/ext/numo/narray/gen/tmpl/store_from.c +53 -0
  74. data/ext/numo/narray/gen/tmpl/store_numeric.c +22 -0
  75. data/ext/numo/narray/gen/tmpl/to_a.c +41 -0
  76. data/ext/numo/narray/gen/tmpl/unary.c +58 -0
  77. data/ext/numo/narray/gen/tmpl/unary2.c +58 -0
  78. data/ext/numo/narray/gen/tmpl/unary_s.c +57 -0
  79. data/ext/numo/narray/index.c +822 -0
  80. data/ext/numo/narray/kwarg.c +79 -0
  81. data/ext/numo/narray/math.c +142 -0
  82. data/ext/numo/narray/narray.c +1541 -0
  83. data/ext/numo/narray/ndloop.c +1928 -0
  84. data/ext/numo/narray/numo/compat.h +23 -0
  85. data/ext/numo/narray/numo/intern.h +112 -0
  86. data/ext/numo/narray/numo/narray.h +411 -0
  87. data/ext/numo/narray/numo/ndloop.h +99 -0
  88. data/ext/numo/narray/numo/template.h +140 -0
  89. data/ext/numo/narray/numo/types/bit.h +19 -0
  90. data/ext/numo/narray/numo/types/complex.h +410 -0
  91. data/ext/numo/narray/numo/types/complex_macro.h +205 -0
  92. data/ext/numo/narray/numo/types/dcomplex.h +11 -0
  93. data/ext/numo/narray/numo/types/dfloat.h +12 -0
  94. data/ext/numo/narray/numo/types/float_def.h +34 -0
  95. data/ext/numo/narray/numo/types/float_macro.h +277 -0
  96. data/ext/numo/narray/numo/types/int16.h +12 -0
  97. data/ext/numo/narray/numo/types/int32.h +12 -0
  98. data/ext/numo/narray/numo/types/int64.h +12 -0
  99. data/ext/numo/narray/numo/types/int8.h +12 -0
  100. data/ext/numo/narray/numo/types/int_macro.h +34 -0
  101. data/ext/numo/narray/numo/types/robj_macro.h +218 -0
  102. data/ext/numo/narray/numo/types/robject.h +21 -0
  103. data/ext/numo/narray/numo/types/scomplex.h +11 -0
  104. data/ext/numo/narray/numo/types/sfloat.h +13 -0
  105. data/ext/numo/narray/numo/types/uint16.h +12 -0
  106. data/ext/numo/narray/numo/types/uint32.h +12 -0
  107. data/ext/numo/narray/numo/types/uint64.h +12 -0
  108. data/ext/numo/narray/numo/types/uint8.h +12 -0
  109. data/ext/numo/narray/numo/types/uint_macro.h +31 -0
  110. data/ext/numo/narray/numo/types/xint_macro.h +133 -0
  111. data/ext/numo/narray/rand.c +87 -0
  112. data/ext/numo/narray/step.c +506 -0
  113. data/ext/numo/narray/struct.c +871 -0
  114. data/lib/erbpp.rb +286 -0
  115. data/lib/erbpp/line_number.rb +126 -0
  116. data/lib/erbpp/narray_def.rb +342 -0
  117. data/lib/numo/narray.rb +6 -0
  118. data/numo-narray.gemspec +35 -0
  119. data/spec/bit_spec.rb +93 -0
  120. data/spec/narray_spec.rb +249 -0
  121. metadata +238 -0
@@ -0,0 +1,79 @@
1
+ /*
2
+ kwarg.c : Process keyword arguments for Ruby
3
+
4
+ Copyright (c) 2001 Masahiro TANAKA <masa@ir.isas.ac.jp>
5
+
6
+ This program is free software.
7
+ You can distribute/modify this program
8
+ under the same terms as Ruby itself.
9
+ NO WARRANTY.
10
+ */
11
+ #include <ruby.h>
12
+ #include "numo/compat.h"
13
+
14
+ /* void rb_scan_kw_args __((VALUE, ...)); */
15
+
16
+ static VALUE
17
+ kw_hash_i(i, tmp)
18
+ VALUE i, tmp;
19
+ {
20
+ VALUE key;
21
+
22
+ key = RARRAY_AREF(i,0);
23
+ if (TYPE(key)==T_SYMBOL) {
24
+ key = rb_funcall(key, rb_intern("id2name"), 0);
25
+ } else
26
+ if (TYPE(key)!=T_STRING) {
27
+ rb_raise(rb_eArgError, "keywords must be String or Symbol");
28
+ }
29
+
30
+ rb_hash_aset(tmp, key, RARRAY_AREF(i,1));
31
+ return Qnil;
32
+ }
33
+
34
+ #ifdef HAVE_STDARG_PROTOTYPES
35
+ #include <stdarg.h>
36
+ #define va_init_list(a,b) va_start(a,b)
37
+ #else
38
+ #include <varargs.h>
39
+ #define va_init_list(a,b) va_start(a)
40
+ #endif
41
+
42
+ void
43
+ #ifdef HAVE_STDARG_PROTOTYPES
44
+ rb_scan_kw_args(VALUE hash, ...)
45
+ #else
46
+ rb_scan_kw_args(hash, va_alist)
47
+ VALUE hash;
48
+ va_dcl
49
+ #endif
50
+ {
51
+ va_list vargs;
52
+ va_init_list(vargs, hash);
53
+
54
+ char *key;
55
+ VALUE *var, val, str, tmp;
56
+
57
+ tmp = rb_hash_new();
58
+ if (TYPE(hash) == T_HASH)
59
+ rb_iterate(rb_each, hash, kw_hash_i, tmp);
60
+ else if (hash != Qnil)
61
+ rb_fatal("rb_san_kw_args: non-hash arg passed");
62
+
63
+ for (;;) {
64
+ key = va_arg(vargs, char*);
65
+ if (!key) break;
66
+ var = va_arg(vargs, VALUE*);
67
+ //printf("i=%d key=%x, val=%x\n",i,key,val);
68
+ str = rb_str_new2(key);
69
+ val = rb_funcall(tmp, rb_intern("delete"), 1, str);
70
+ if (var) *var = val;
71
+ }
72
+ va_end(vargs);
73
+
74
+ if (rb_funcall(tmp, rb_intern("empty?"), 0)==Qfalse) {
75
+ val = rb_funcall(tmp, rb_intern("keys"), 0);
76
+ val = rb_funcall(val, rb_intern("join"), 1, rb_str_new2(","));
77
+ rb_raise(rb_eArgError, "unknown keywords: %s",StringValueCStr(val));
78
+ }
79
+ }
@@ -0,0 +1,142 @@
1
+ /*
2
+ math.c
3
+ Numerical Array Extension for Ruby
4
+ (C) Copyright 1999-2011 by Masahiro TANAKA
5
+
6
+ This program is free software.
7
+ You can distribute/modify this program
8
+ under the same terms as Ruby itself.
9
+ NO WARRANTY.
10
+ */
11
+ #include <ruby.h>
12
+ #include "numo/narray.h"
13
+
14
+ VALUE numo_mNMath;
15
+ EXTERN VALUE numo_mDFloatMath, numo_mDComplexMath;
16
+ static ID id_send;
17
+
18
+ VALUE
19
+ nary_type_s_upcast(VALUE type1, VALUE type2)
20
+ {
21
+ VALUE upcast_hash;
22
+ VALUE result_type;
23
+
24
+ if (type1==type2) return type1;
25
+ upcast_hash = rb_const_get(type1, rb_intern("UPCAST"));
26
+ result_type = rb_hash_aref(upcast_hash, type2);
27
+ if (NIL_P(result_type)) {
28
+ if (TYPE(type2)==T_CLASS) {
29
+ if ( RTEST(rb_class_inherited_p(type2,cNArray)) ) {
30
+ upcast_hash = rb_const_get(type2, rb_intern("UPCAST"));
31
+ result_type = rb_hash_aref(upcast_hash, type1);
32
+ }
33
+ }
34
+ }
35
+ return result_type;
36
+ }
37
+
38
+
39
+ VALUE nary_math_cast2(VALUE type1, VALUE type2)
40
+ {
41
+ if ( RTEST(rb_class_inherited_p( type1, cNArray )) ){
42
+ return nary_type_s_upcast( type1, type2 );
43
+ }
44
+ if ( RTEST(rb_class_inherited_p( type2, cNArray )) ){
45
+ return nary_type_s_upcast( type2, type1 );
46
+ }
47
+ if ( RTEST(rb_class_inherited_p( type1, rb_cNumeric )) &&
48
+ RTEST(rb_class_inherited_p( type2, rb_cNumeric )) ){
49
+ if ( RTEST(rb_class_inherited_p( type1, rb_cComplex)) ||
50
+ RTEST(rb_class_inherited_p( type2, rb_cComplex )) ){
51
+ return rb_cComplex;
52
+ }
53
+ return rb_cFloat;
54
+ }
55
+ return type2;
56
+ }
57
+
58
+
59
+ VALUE na_ary_composition_dtype(VALUE);
60
+
61
+ VALUE nary_mathcast(int argc, VALUE *argv)
62
+ {
63
+ VALUE type, type2;
64
+ int i;
65
+ type = na_ary_composition_dtype(argv[0]);
66
+ for (i=1; i<argc; i++) {
67
+ type2 = na_ary_composition_dtype(argv[i]);
68
+ type = nary_math_cast2(type, type2);
69
+ if (NIL_P(type)) {
70
+ rb_raise(rb_eTypeError,"%s is unknown for Numo::NMath",
71
+ rb_class2name(argv[i]));
72
+ }
73
+ }
74
+ return type;
75
+ }
76
+
77
+
78
+ /*
79
+ Dispatches method to Math module of upcasted type,
80
+ eg, Numo::DFloat::Math.
81
+ @overload method_missing(name,x,...)
82
+ @param [Symbol] name method name.
83
+ @param [NArray,Numeric] x input array.
84
+ @return [NArray] result.
85
+ */
86
+ VALUE nary_math_method_missing(int argc, VALUE *argv, VALUE mod)
87
+ {
88
+ VALUE type, ans, typemod, hash;
89
+ if (argc>1) {
90
+ type = nary_mathcast(argc-1,argv+1);
91
+
92
+ hash = rb_const_get(mod, rb_intern("DISPATCH"));
93
+ typemod = rb_hash_aref( hash, type );
94
+ if (NIL_P(typemod)) {
95
+ rb_raise(rb_eTypeError,"%s is unknown for Numo::NMath",
96
+ rb_class2name(type));
97
+ }
98
+
99
+ ans = rb_funcall2(typemod,id_send,argc,argv);
100
+
101
+ if (!RTEST(rb_class_inherited_p(type,cNArray)) &&
102
+ IsNArray(ans) ) {
103
+ ans = rb_funcall(ans,rb_intern("extract"),0);
104
+ }
105
+ return ans;
106
+ }
107
+ rb_raise(rb_eArgError,"argument or method missing");
108
+ return Qnil;
109
+ }
110
+
111
+
112
+ void
113
+ Init_nary_math()
114
+ {
115
+ VALUE hCast;
116
+
117
+ numo_mNMath = rb_define_module_under(mNumo, "NMath");
118
+ rb_define_singleton_method(numo_mNMath, "method_missing", nary_math_method_missing, -1);
119
+
120
+ hCast = rb_hash_new();
121
+ rb_define_const(numo_mNMath, "DISPATCH", hCast);
122
+ rb_hash_aset(hCast, numo_cInt64, numo_mDFloatMath);
123
+ rb_hash_aset(hCast, numo_cInt32, numo_mDFloatMath);
124
+ rb_hash_aset(hCast, numo_cInt16, numo_mDFloatMath);
125
+ rb_hash_aset(hCast, numo_cInt8, numo_mDFloatMath);
126
+ rb_hash_aset(hCast, numo_cUInt64, numo_mDFloatMath);
127
+ rb_hash_aset(hCast, numo_cUInt32, numo_mDFloatMath);
128
+ rb_hash_aset(hCast, numo_cUInt16, numo_mDFloatMath);
129
+ rb_hash_aset(hCast, numo_cUInt8, numo_mDFloatMath);
130
+ rb_hash_aset(hCast, numo_cDFloat, numo_mDFloatMath);
131
+ rb_hash_aset(hCast, numo_cDFloat, numo_mDFloatMath);
132
+ rb_hash_aset(hCast, numo_cDComplex, numo_mDComplexMath);
133
+ #ifdef HAVE_RB_CFIXNUM
134
+ rb_hash_aset(hCast, rb_cFixnum, rb_mMath);
135
+ rb_hash_aset(hCast, rb_cBignum, rb_mMath);
136
+ #endif
137
+ rb_hash_aset(hCast, rb_cInteger, rb_mMath);
138
+ rb_hash_aset(hCast, rb_cFloat, rb_mMath);
139
+ rb_hash_aset(hCast, rb_cComplex, numo_mDComplexMath);
140
+
141
+ id_send = rb_intern("send");
142
+ }
@@ -0,0 +1,1541 @@
1
+ /*
2
+ narray.c
3
+ Numerical Array Extension for Ruby
4
+ (C) Copyright 1999-2016 by Masahiro TANAKA
5
+
6
+ This program is free software.
7
+ You can distribute/modify this program
8
+ under the same terms as Ruby itself.
9
+ NO WARRANTY.
10
+ */
11
+ #define NARRAY_C
12
+ #include <ruby.h>
13
+ #include "numo/narray.h"
14
+ #include "extconf.h"
15
+ #include <assert.h>
16
+
17
+ /* global variables within this module */
18
+ VALUE numo_cNArray;
19
+ VALUE rb_mNumo;
20
+ VALUE nary_eCastError;
21
+ VALUE nary_eShapeError;
22
+ VALUE nary_eOperationError;
23
+ VALUE nary_eDimensionError;
24
+
25
+ static ID id_contiguous_stride;
26
+ //static ID id_element_bit_size;
27
+ //static ID id_element_byte_size;
28
+
29
+ VALUE cPointer;
30
+
31
+ static ID id_allocate;
32
+
33
+ VALUE sym_reduce;
34
+ VALUE sym_option;
35
+ VALUE sym_loop_opt;
36
+ VALUE sym_init;
37
+
38
+ VALUE na_cStep;
39
+ #ifndef HAVE_RB_CCOMPLEX
40
+ VALUE rb_cComplex;
41
+ #endif
42
+
43
+ void Init_nary_data();
44
+ void Init_nary_step();
45
+ void Init_nary_index();
46
+ void Init_nary_bit();
47
+ void Init_nary_int8();
48
+ void Init_nary_int16();
49
+ void Init_nary_int32();
50
+ void Init_nary_int64();
51
+ void Init_nary_uint8();
52
+ void Init_nary_uint16();
53
+ void Init_nary_uint32();
54
+ void Init_nary_uint64();
55
+ void Init_nary_sfloat();
56
+ void Init_nary_scomplex();
57
+ void Init_nary_dfloat();
58
+ void Init_nary_dcomplex();
59
+ void Init_nary_math();
60
+ void Init_nary_rand();
61
+ void Init_nary_array();
62
+ void Init_nary_struct();
63
+ void Init_nary_robject();
64
+
65
+
66
+ static void
67
+ rb_narray_debug_info_nadata(VALUE self)
68
+ {
69
+ narray_data_t *na;
70
+ GetNArrayData(self,na);
71
+
72
+ printf(" ptr = 0x%"SZF"x\n", (size_t)(na->ptr));
73
+ }
74
+
75
+
76
+ static VALUE
77
+ rb_narray_debug_info_naview(VALUE self)
78
+ {
79
+ int i;
80
+ narray_view_t *na;
81
+ size_t *idx;
82
+ size_t j;
83
+ GetNArrayView(self,na);
84
+
85
+ printf(" data = 0x%"SZF"x\n", (size_t)na->data);
86
+ printf(" offset = %"SZF"d\n", (size_t)na->offset);
87
+ printf(" stridx = 0x%"SZF"x\n", (size_t)na->stridx);
88
+
89
+ if (na->stridx) {
90
+ printf(" stridx = [");
91
+ for (i=0; i<na->base.ndim; i++) {
92
+ if (SDX_IS_INDEX(na->stridx[i])) {
93
+
94
+ idx = SDX_GET_INDEX(na->stridx[i]);
95
+ printf(" index[%d]=[", i);
96
+ for (j=0; j<na->base.shape[i]; j++) {
97
+ printf(" %"SZF"d", idx[j]);
98
+ }
99
+ printf(" ] ");
100
+
101
+ } else {
102
+ printf(" %"SZF"d", SDX_GET_STRIDE(na->stridx[i]));
103
+ }
104
+ }
105
+ printf(" ]\n");
106
+ }
107
+ return Qnil;
108
+ }
109
+
110
+
111
+ VALUE
112
+ rb_narray_debug_info(VALUE self)
113
+ {
114
+ int i;
115
+ narray_t *na;
116
+ GetNArray(self,na);
117
+
118
+ printf("%s:\n",rb_class2name(CLASS_OF(self)));
119
+ printf(" id = 0x%"SZF"x\n", self);
120
+ printf(" type = %d\n", na->type);
121
+ printf(" flag = [%d,%d]\n", na->flag[0], na->flag[1]);
122
+ printf(" size = %"SZF"d\n", na->size);
123
+ printf(" ndim = %d\n", na->ndim);
124
+ printf(" shape = 0x%"SZF"x\n", (size_t)na->shape);
125
+ if (na->shape) {
126
+ printf(" shape = [");
127
+ for (i=0;i<na->ndim;i++)
128
+ printf(" %"SZF"d", na->shape[i]);
129
+ printf(" ]\n");
130
+ }
131
+
132
+ switch(na->type) {
133
+ case NARRAY_DATA_T:
134
+ case NARRAY_FILEMAP_T:
135
+ rb_narray_debug_info_nadata(self);
136
+ break;
137
+ case NARRAY_VIEW_T:
138
+ rb_narray_debug_info_naview(self);
139
+ break;
140
+ }
141
+ return Qnil;
142
+ }
143
+
144
+
145
+ void
146
+ na_free(narray_data_t* na)
147
+ {
148
+ assert(na->base.type==NARRAY_DATA_T);
149
+
150
+ if (na->ptr != NULL) {
151
+ xfree(na->ptr);
152
+ na->ptr = NULL;
153
+ }
154
+ if (na->base.size > 0) {
155
+ if (na->base.shape != NULL && na->base.shape != &(na->base.size)) {
156
+ xfree(na->base.shape);
157
+ na->base.shape = NULL;
158
+ }
159
+ }
160
+ xfree(na);
161
+ }
162
+
163
+ static void
164
+ na_free_view(narray_view_t* na)
165
+ {
166
+ assert(na->base.type==NARRAY_VIEW_T);
167
+
168
+ if (na->stridx != NULL) {
169
+ xfree(na->stridx);
170
+ na->stridx = NULL;
171
+ }
172
+ if (na->base.size > 0) {
173
+ if (na->base.shape != NULL && na->base.shape != &(na->base.size)) {
174
+ xfree(na->base.shape);
175
+ na->base.shape = NULL;
176
+ }
177
+ }
178
+ xfree(na);
179
+ }
180
+
181
+ static void
182
+ na_gc_mark_view(narray_view_t* na)
183
+ {
184
+ rb_gc_mark(na->data);
185
+ }
186
+
187
+ VALUE
188
+ na_s_allocate(VALUE klass)
189
+ {
190
+ narray_data_t *na = ALLOC(narray_data_t);
191
+
192
+ na->base.ndim = 0;
193
+ na->base.type = NARRAY_DATA_T;
194
+ na->base.flag[0] = 0;
195
+ na->base.flag[1] = 0;
196
+ na->base.size = 0;
197
+ na->base.shape = NULL;
198
+ na->base.reduce = INT2FIX(0);
199
+ na->ptr = NULL;
200
+ return Data_Wrap_Struct(klass, 0, na_free, na);
201
+ }
202
+
203
+
204
+ VALUE
205
+ na_s_allocate_view(VALUE klass)
206
+ {
207
+ narray_view_t *na = ALLOC(narray_view_t);
208
+
209
+ na->base.ndim = 0;
210
+ na->base.type = NARRAY_VIEW_T;
211
+ na->base.flag[0] = 0;
212
+ na->base.flag[1] = 0;
213
+ na->base.size = 0;
214
+ na->base.shape = NULL;
215
+ na->base.reduce = INT2FIX(0);
216
+ na->data = Qnil;
217
+ na->offset = 0;
218
+ na->stridx = NULL;
219
+ return Data_Wrap_Struct(klass, na_gc_mark_view, na_free_view, na);
220
+ }
221
+
222
+
223
+ //static const size_t zero=0;
224
+
225
+ void
226
+ na_array_to_internal_shape(VALUE self, VALUE ary, size_t *shape)
227
+ {
228
+ size_t i, n, c, s;
229
+ VALUE v;
230
+ narray_t *na;
231
+ int flag = 0;
232
+
233
+ n = RARRAY_LEN(ary);
234
+
235
+ if (RTEST(self)) {
236
+ GetNArray(self, na);
237
+ flag = TEST_COLUMN_MAJOR(na);
238
+ }
239
+ if (flag) {
240
+ c = n-1;
241
+ s = -1;
242
+ } else {
243
+ c = 0;
244
+ s = 1;
245
+ }
246
+ for (i=0; i<n; i++) {
247
+ v = RARRAY_AREF(ary,i);
248
+ if (!FIXNUM_P(v) && !rb_obj_is_kind_of(v, rb_cInteger)) {
249
+ rb_raise(rb_eTypeError, "array size must be Integer");
250
+ }
251
+ if (RTEST(rb_funcall(v, rb_intern("<"), 1, INT2FIX(0)))) {
252
+ rb_raise(rb_eArgError,"size must be non-negative");
253
+ }
254
+ shape[c] = NUM2SIZE(v);
255
+ c += s;
256
+ }
257
+ }
258
+
259
+
260
+
261
+ void
262
+ na_alloc_shape(narray_t *na, int ndim)
263
+ {
264
+ na->ndim = ndim;
265
+ na->size = 0;
266
+ if (ndim == 0) {
267
+ na->shape = NULL;
268
+ }
269
+ else if (ndim == 1) {
270
+ na->shape = &(na->size);
271
+ }
272
+ else if (ndim < 0) {
273
+ rb_raise(nary_eDimensionError,"ndim=%d is negative", ndim);
274
+ }
275
+ else if (ndim > NA_MAX_DIMENSION) {
276
+ rb_raise(nary_eDimensionError,"ndim=%d is too many", ndim);
277
+ } else {
278
+ na->shape = ALLOC_N(size_t, ndim);
279
+ }
280
+ }
281
+
282
+ void
283
+ na_setup_shape(narray_t *na, int ndim, size_t *shape)
284
+ {
285
+ int i;
286
+ size_t size;
287
+
288
+ na_alloc_shape(na, ndim);
289
+
290
+ if (ndim==0) {
291
+ na->size = 1;
292
+ }
293
+ else if (ndim==1) {
294
+ na->size = shape[0];
295
+ }
296
+ else {
297
+ for (i=0, size=1; i<ndim; i++) {
298
+ na->shape[i] = shape[i];
299
+ size *= shape[i];
300
+ }
301
+ na->size = size;
302
+ }
303
+ }
304
+
305
+ void
306
+ na_setup(VALUE self, int ndim, size_t *shape)
307
+ {
308
+ narray_t *na;
309
+ GetNArray(self,na);
310
+ na_setup_shape(na, ndim, shape);
311
+ }
312
+
313
+
314
+ /*
315
+ * call-seq:
316
+ * Numo::DataType.new(shape) => narray
317
+ * Numo::DataType.new(size1, size2, ...) => narray
318
+ *
319
+ * Constructs a narray using the given <i>DataType</i> and <i>shape</i> or
320
+ * <i>sizes</i>.
321
+ */
322
+ static VALUE
323
+ na_initialize(VALUE self, VALUE args)
324
+ {
325
+ VALUE v;
326
+ size_t *shape=NULL;
327
+ int ndim;
328
+
329
+ if (RARRAY_LEN(args) == 1) {
330
+ v = RARRAY_AREF(args,0);
331
+ if (TYPE(v) != T_ARRAY) {
332
+ v = args;
333
+ }
334
+ } else {
335
+ v = args;
336
+ }
337
+ ndim = RARRAY_LEN(v);
338
+ if (ndim > NA_MAX_DIMENSION) {
339
+ rb_raise(rb_eArgError,"ndim=%d exceeds maximum dimension",ndim);
340
+ }
341
+ shape = ALLOCA_N(size_t, ndim);
342
+ // setup size_t shape[] from VALUE shape argument
343
+ na_array_to_internal_shape(self, v, shape);
344
+ na_setup(self, ndim, shape);
345
+
346
+ return self;
347
+ }
348
+
349
+
350
+ VALUE
351
+ rb_narray_new(VALUE klass, int ndim, size_t *shape)
352
+ {
353
+ volatile VALUE obj;
354
+
355
+ obj = rb_funcall(klass, id_allocate, 0);
356
+ na_setup(obj, ndim, shape);
357
+ return obj;
358
+ }
359
+
360
+
361
+ VALUE
362
+ rb_narray_view_new(VALUE klass, int ndim, size_t *shape)
363
+ {
364
+ volatile VALUE obj;
365
+
366
+ obj = na_s_allocate_view(klass);
367
+ na_setup(obj, ndim, shape);
368
+ return obj;
369
+ }
370
+
371
+
372
+ /*
373
+ Replaces the contents of self with the contents of other narray.
374
+ Used in dup and clone method.
375
+ @overload initialize_copy(other)
376
+ @param [Numo::NArray] other
377
+ @return [Numo::NArray] self
378
+ */
379
+ static VALUE
380
+ na_initialize_copy(VALUE self, VALUE orig)
381
+ {
382
+ narray_t *na;
383
+ GetNArray(orig,na);
384
+
385
+ na_setup(self,NA_NDIM(na),NA_SHAPE(na));
386
+ na_store(self,orig);
387
+ na_copy_flags(orig,self);
388
+ return self;
389
+ }
390
+
391
+
392
+ /*
393
+ * call-seq:
394
+ * zeros(shape) => narray
395
+ * zeros(size1,size2,...) => narray
396
+ *
397
+ * Returns a zero-filled narray with <i>shape</i>.
398
+ * This singleton method is valid not for NArray class itself
399
+ * but for typed NArray subclasses, e.g., DFloat, Int64.
400
+ * @example
401
+ * a = Numo::DFloat.zeros(3,5)
402
+ * => Numo::DFloat#shape=[3,5]
403
+ * [[0, 0, 0, 0, 0],
404
+ * [0, 0, 0, 0, 0],
405
+ * [0, 0, 0, 0, 0]]
406
+ */
407
+ static VALUE
408
+ na_s_zeros(int argc, VALUE *argv, VALUE klass)
409
+ {
410
+ VALUE obj;
411
+ obj = rb_class_new_instance(argc, argv, klass);
412
+ return rb_funcall(obj, rb_intern("fill"), 1, INT2FIX(0));
413
+ }
414
+
415
+
416
+ /*
417
+ * call-seq:
418
+ * ones(shape) => narray
419
+ * ones(size1,size2,...) => narray
420
+ *
421
+ * Returns a one-filled narray with <i>shape</i>.
422
+ * This singleton method is valid not for NArray class itself
423
+ * but for typed NArray subclasses, e.g., DFloat, Int64.
424
+ * @example
425
+ * a = Numo::DFloat.ones(3,5)
426
+ * => Numo::DFloat#shape=[3,5]
427
+ * [[1, 1, 1, 1, 1],
428
+ * [1, 1, 1, 1, 1],
429
+ * [1, 1, 1, 1, 1]]
430
+ */
431
+ static VALUE
432
+ na_s_ones(int argc, VALUE *argv, VALUE klass)
433
+ {
434
+ VALUE obj;
435
+ obj = rb_class_new_instance(argc, argv, klass);
436
+ return rb_funcall(obj, rb_intern("fill"), 1, INT2FIX(1));
437
+ }
438
+
439
+
440
+ /*
441
+ Returns a NArray with shape=(n,n) whose diagonal elements are 1, otherwise 0.
442
+ @overload eye(n)
443
+ @param [Integer] n Size of NArray. Creates 2-D NArray with shape=(n,n)
444
+ @return [Numo::NArray] created NArray.
445
+ @example
446
+ a = Numo::DFloat.eye(3)
447
+ => Numo::DFloat#shape=[3,3]
448
+ [[1, 0, 0],
449
+ [0, 1, 0],
450
+ [0, 0, 1]]
451
+ */
452
+ static VALUE
453
+ na_s_eye(int argc, VALUE *argv, VALUE klass)
454
+ {
455
+ VALUE obj;
456
+ VALUE tmp[2];
457
+
458
+ if (argc==0) {
459
+ rb_raise(rb_eArgError,"No argument");
460
+ }
461
+ else if (argc==1) {
462
+ tmp[0] = tmp[1] = argv[0];
463
+ argv = tmp;
464
+ argc = 2;
465
+ }
466
+ obj = rb_class_new_instance(argc, argv, klass);
467
+ return rb_funcall(obj, rb_intern("eye"), 0);
468
+ }
469
+
470
+
471
+ char *
472
+ na_get_pointer(VALUE self)
473
+ {
474
+ narray_t *na;
475
+ GetNArray(self,na);
476
+
477
+ switch(NA_TYPE(na)) {
478
+ case NARRAY_DATA_T:
479
+ return NA_DATA_PTR(na);
480
+ case NARRAY_FILEMAP_T:
481
+ return ((narray_filemap_t*)na)->ptr;
482
+ case NARRAY_VIEW_T:
483
+ return na_get_pointer(NA_VIEW_DATA(na));
484
+ //puts("pass NARRAY_VIEW_T in na_get_pointer_for_write");
485
+ //ptr += ((narray_view_t*)na)->offset;
486
+ //ptr += NA_VIEW_OFFSET(na);
487
+ break;
488
+ default:
489
+ rb_raise(rb_eRuntimeError,"invalid NA_TYPE");
490
+ }
491
+ return NULL;
492
+ }
493
+
494
+ char *
495
+ na_get_pointer_for_write(VALUE self)
496
+ {
497
+ char *ptr;
498
+ narray_t *na;
499
+ GetNArray(self,na);
500
+
501
+ if (OBJ_FROZEN(self)) {
502
+ rb_raise(rb_eRuntimeError, "cannot write to frozen NArray.");
503
+ }
504
+
505
+ if (NA_TYPE(na) == NARRAY_DATA_T) {
506
+ ptr = NA_DATA_PTR(na);
507
+ if (na->size > 0 && ptr == NULL) {
508
+ rb_funcall(self, id_allocate, 0);
509
+ ptr = NA_DATA_PTR(na);
510
+ }
511
+ } else {
512
+ ptr = na_get_pointer(self);
513
+ if (NA_SIZE(na) > 0 && ptr == NULL) {
514
+ rb_raise(rb_eRuntimeError,"cannot write to unallocated NArray");
515
+ }
516
+ }
517
+
518
+ //NA_SET_LOCK(na);
519
+
520
+ return ptr;
521
+ }
522
+
523
+ char *
524
+ na_get_pointer_for_read(VALUE self)
525
+ {
526
+ char *ptr;
527
+ narray_t *na;
528
+ GetNArray(self,na);
529
+
530
+ //if (NA_TEST_LOCK(na)) {
531
+ // rb_raise(rb_eRuntimeError, "cannot read locked NArray.");
532
+ //}
533
+
534
+ if (NA_TYPE(na) == NARRAY_DATA_T) {
535
+ ptr = NA_DATA_PTR(na);
536
+ } else {
537
+ ptr = na_get_pointer(self);
538
+ }
539
+
540
+ if (NA_SIZE(na) > 0 && ptr == NULL) {
541
+ rb_raise(rb_eRuntimeError,"cannot read unallocated NArray");
542
+ }
543
+
544
+ //NA_SET_LOCK(na);
545
+
546
+ return ptr;
547
+ }
548
+
549
+
550
+ void
551
+ na_release_lock(VALUE self)
552
+ {
553
+ narray_t *na;
554
+ GetNArray(self,na);
555
+
556
+ NA_UNSET_LOCK(na);
557
+
558
+ switch(NA_TYPE(na)) {
559
+ case NARRAY_VIEW_T:
560
+ na_release_lock(NA_VIEW_DATA(na));
561
+ break;
562
+ }
563
+ }
564
+
565
+ // fix name, ex, allow_stride_for_flatten_view
566
+ VALUE
567
+ na_check_ladder(VALUE self, int start_dim)
568
+ {
569
+ int i;
570
+ ssize_t st0, st1;
571
+ narray_t *na1;
572
+ narray_view_t *na;
573
+ GetNArray(self,na1);
574
+
575
+ //puts("pass ladder");
576
+
577
+ if (start_dim < -na1->ndim || start_dim >= na1->ndim) {
578
+ rb_bug("start_dim (%d) out of range",start_dim);
579
+ }
580
+
581
+ switch(na1->type) {
582
+ case NARRAY_DATA_T:
583
+ case NARRAY_FILEMAP_T:
584
+ return Qtrue;
585
+ case NARRAY_VIEW_T:
586
+ GetNArrayView(self,na);
587
+ // negative dim -> position from last dim
588
+ if (start_dim < 0) {
589
+ start_dim += na->base.ndim;
590
+ }
591
+ // not ladder if it has index
592
+ for (i=start_dim; i<na->base.ndim; i++) {
593
+ if (SDX_IS_INDEX(na->stridx[i]))
594
+ return Qfalse;
595
+ }
596
+ // check stride
597
+ i = start_dim;
598
+ st0 = SDX_GET_STRIDE(na->stridx[i]);
599
+ for (i++; i<na->base.ndim; i++) {
600
+ st1 = SDX_GET_STRIDE(na->stridx[i]);
601
+ if (st0 != (ssize_t)(st1*na->base.shape[i])) {
602
+ return Qfalse;
603
+ }
604
+ st0 = st1;
605
+ }
606
+ return Qtrue;
607
+ }
608
+ return Qtrue;
609
+ }
610
+
611
+
612
+ /*
613
+ stridx_t *
614
+ na_get_stride(VALUE v)
615
+ {
616
+ int i;
617
+ size_t st;
618
+ stridx_t *stridx=NULL;
619
+ narray_t *na;
620
+ GetNArray(v,na);
621
+
622
+ switch(NA_TYPE(na)) {
623
+ case NARRAY_DATA_T:
624
+ if (NA_DATA_PTR(na)==NULL) {
625
+ rb_raise(rb_eRuntimeError,"cannot read no-data NArray");
626
+ }
627
+ break;
628
+ case NARRAY_FILEMAP_T:
629
+ break;
630
+ case NARRAY_VIEW_T:
631
+ stridx = NA_STRIDX(na);
632
+ break;
633
+ default:
634
+ rb_raise(rb_eRuntimeError,"invalid narray internal type");
635
+ }
636
+
637
+ if (!stridx) {
638
+ stridx = ALLOC_N(stridx_t, na->ndim);
639
+ st = NUM2SIZE(rb_const_get(CLASS_OF(v), id_contiguous_stride));
640
+ //printf("step_unit=%ld, CLASS_OF(v)=%lx\n",st, CLASS_OF(v));
641
+ for (i=na->ndim; i>0;) {
642
+ SDX_SET_STRIDE(stridx[--i],st);
643
+ st *= na->shape[i];
644
+ }
645
+ }
646
+
647
+ return stridx;
648
+ }
649
+ */
650
+
651
+
652
+ /* method: size() -- returns the total number of typeents */
653
+ static VALUE
654
+ na_size(VALUE self)
655
+ {
656
+ narray_t *na;
657
+ GetNArray(self,na);
658
+ return SIZE2NUM(na->size);
659
+ }
660
+
661
+
662
+ /* method: size() -- returns the total number of typeents */
663
+ static VALUE
664
+ na_ndim(VALUE self)
665
+ {
666
+ narray_t *na;
667
+ GetNArray(self,na);
668
+ return INT2NUM(na->ndim);
669
+ }
670
+
671
+
672
+ /* method: shape() -- returns shape, array of the size of dimensions */
673
+ static VALUE
674
+ na_shape(VALUE self)
675
+ {
676
+ volatile VALUE v;
677
+ narray_t *na;
678
+ size_t i, n, c, s;
679
+
680
+ GetNArray(self,na);
681
+ n = NA_NDIM(na);
682
+ if (TEST_COLUMN_MAJOR(na)) {
683
+ c = n-1;
684
+ s = -1;
685
+ } else {
686
+ c = 0;
687
+ s = 1;
688
+ }
689
+ v = rb_ary_new2(n);
690
+ for (i=0; i<n; i++) {
691
+ rb_ary_push(v, SIZE2NUM(na->shape[c]));
692
+ c += s;
693
+ }
694
+ return v;
695
+ }
696
+
697
+
698
+ size_t
699
+ na_get_elmsz(VALUE vna)
700
+ {
701
+ return NUM2SIZE(rb_const_get(CLASS_OF(vna), id_contiguous_stride));
702
+ }
703
+
704
+ size_t
705
+ na_dtype_elmsz(VALUE klass)
706
+ {
707
+ return NUM2SIZE(rb_const_get(klass, id_contiguous_stride));
708
+ }
709
+
710
+ size_t
711
+ na_get_offset(VALUE self)
712
+ {
713
+ narray_t *na;
714
+ GetNArray(self,na);
715
+
716
+ switch(na->type) {
717
+ case NARRAY_DATA_T:
718
+ case NARRAY_FILEMAP_T:
719
+ return 0;
720
+ case NARRAY_VIEW_T:
721
+ return NA_VIEW_OFFSET(na);
722
+ }
723
+ return 0;
724
+ }
725
+
726
+
727
+ void
728
+ na_index_arg_to_internal_order(int argc, VALUE *argv, VALUE self)
729
+ {
730
+ int i,j;
731
+ VALUE tmp;
732
+
733
+ if (TEST_COLUMN_MAJOR(self)) {
734
+ for (i=0,j=argc-1; i<argc/2; i++,j--) {
735
+ tmp = argv[i];
736
+ argv[i] = argv[j];
737
+ argv[j] = tmp;
738
+ }
739
+ }
740
+ }
741
+
742
+ void
743
+ na_copy_flags(VALUE src, VALUE dst)
744
+ {
745
+ narray_t *na1, *na2;
746
+
747
+ GetNArray(src,na1);
748
+ GetNArray(dst,na2);
749
+
750
+ na2->flag[0] = na1->flag[0];
751
+ na2->flag[1] = na1->flag[1];
752
+
753
+ RBASIC(dst)->flags |= (RBASIC(src)->flags) &
754
+ (FL_USER1|FL_USER2|FL_USER3|FL_USER4|FL_USER5|FL_USER6|FL_USER7);
755
+ }
756
+
757
+
758
+ VALUE
759
+ na_original_data(VALUE self)
760
+ {
761
+ narray_t *na;
762
+ narray_view_t *nv;
763
+
764
+ GetNArray(self,na);
765
+ switch(na->type) {
766
+ case NARRAY_VIEW_T:
767
+ GetNArrayView(self, nv);
768
+ return nv->data;
769
+ }
770
+ return self;
771
+ }
772
+
773
+
774
+ //----------------------------------------------------------------------
775
+
776
+ /*
777
+ * call-seq:
778
+ * narray.view => narray
779
+ *
780
+ * Return view of NArray
781
+ */
782
+ VALUE
783
+ na_make_view(VALUE self)
784
+ {
785
+ int i, nd;
786
+ size_t j;
787
+ size_t *idx1, *idx2;
788
+ ssize_t stride;
789
+ narray_t *na;
790
+ narray_view_t *na1, *na2;
791
+ volatile VALUE view;
792
+
793
+ GetNArray(self,na);
794
+ nd = na->ndim;
795
+
796
+ view = na_s_allocate_view(CLASS_OF(self));
797
+
798
+ na_copy_flags(self, view);
799
+ GetNArrayView(view, na2);
800
+
801
+ na_setup_shape((narray_t*)na2, nd, na->shape);
802
+ na2->stridx = ALLOC_N(stridx_t,nd);
803
+
804
+ switch(na->type) {
805
+ case NARRAY_DATA_T:
806
+ case NARRAY_FILEMAP_T:
807
+ stride = na_get_elmsz(self);
808
+ for (i=nd; i--;) {
809
+ SDX_SET_STRIDE(na2->stridx[i],stride);
810
+ stride *= na->shape[i];
811
+ }
812
+ na2->offset = 0;
813
+ na2->data = self;
814
+ break;
815
+ case NARRAY_VIEW_T:
816
+ GetNArrayView(self, na1);
817
+ for (i=0; i<nd; i++) {
818
+ if (SDX_IS_INDEX(na1->stridx[i])) {
819
+ idx1 = SDX_GET_INDEX(na1->stridx[i]);
820
+ idx2 = ALLOC_N(size_t,na1->base.shape[i]);
821
+ for (j=0; j<na1->base.shape[i]; j++) {
822
+ idx2[j] = idx1[j];
823
+ }
824
+ SDX_SET_INDEX(na2->stridx[i],idx2);
825
+ } else {
826
+ na2->stridx[i] = na1->stridx[i];
827
+ }
828
+ }
829
+ na2->offset = na1->offset;
830
+ na2->data = na1->data;
831
+ break;
832
+ }
833
+
834
+ return view;
835
+ }
836
+
837
+
838
+ //----------------------------------------------------------------------
839
+
840
+ /*
841
+ * call-seq:
842
+ * narray.expand_dims(dim) => narray view
843
+ *
844
+ * Expand the shape of an array. Insert a new axis with size=1
845
+ * at a given dimension.
846
+ * @param [Integer] dim dimension at which new axis is inserted.
847
+ * @return [Numo::NArray] result narray view.
848
+ */
849
+ VALUE
850
+ na_expand_dims(VALUE self, VALUE vdim)
851
+ {
852
+ int i, j, nd, dim;
853
+ size_t *shape, *na_shape;
854
+ stridx_t *stridx, *na_stridx;
855
+ narray_t *na;
856
+ narray_view_t *na2;
857
+ VALUE view;
858
+
859
+ GetNArray(self,na);
860
+ nd = na->ndim;
861
+
862
+ dim = NUM2INT(vdim);
863
+ if (dim < -nd-1 || dim > nd) {
864
+ rb_raise(nary_eDimensionError,"invalid axis (%d for %dD NArray)",
865
+ dim,nd);
866
+ }
867
+ if (dim < 0) {
868
+ dim += nd+1;
869
+ }
870
+
871
+ view = na_make_view(self);
872
+ GetNArrayView(view, na2);
873
+
874
+ shape = ALLOC_N(size_t,nd+1);
875
+ stridx = ALLOC_N(stridx_t,nd+1);
876
+ na_shape = na2->base.shape;
877
+ na_stridx = na2->stridx;
878
+
879
+ for (i=j=0; i<=nd; i++) {
880
+ if (i==dim) {
881
+ shape[i] = 1;
882
+ SDX_SET_STRIDE(stridx[i],0);
883
+ } else {
884
+ shape[i] = na_shape[j];
885
+ stridx[i] = na_stridx[j];
886
+ j++;
887
+ }
888
+ }
889
+
890
+ na2->stridx = stridx;
891
+ xfree(na_stridx);
892
+ na2->base.shape = shape;
893
+ xfree(na_shape);
894
+ na2->base.ndim++;
895
+ return view;
896
+ }
897
+
898
+ //----------------------------------------------------------------------
899
+
900
+ /*
901
+ * call-seq:
902
+ * narray.reverse([dim0,dim1,..]) => narray
903
+ *
904
+ * Return reversed view along specified dimeinsion
905
+ */
906
+ VALUE
907
+ nary_reverse(int argc, VALUE *argv, VALUE self)
908
+ {
909
+ int i, nd;
910
+ size_t j, n;
911
+ size_t offset;
912
+ size_t *idx1, *idx2;
913
+ ssize_t stride;
914
+ ssize_t sign;
915
+ narray_t *na;
916
+ narray_view_t *na1, *na2;
917
+ VALUE view;
918
+ VALUE reduce;
919
+
920
+ reduce = na_reduce_dimension(argc, argv, 1, &self);
921
+
922
+ GetNArray(self,na);
923
+ nd = na->ndim;
924
+
925
+ view = na_s_allocate_view(CLASS_OF(self));
926
+
927
+ na_copy_flags(self, view);
928
+ GetNArrayView(view, na2);
929
+
930
+ na_setup_shape((narray_t*)na2, nd, na->shape);
931
+ na2->stridx = ALLOC_N(stridx_t,nd);
932
+
933
+ switch(na->type) {
934
+ case NARRAY_DATA_T:
935
+ case NARRAY_FILEMAP_T:
936
+ stride = na_get_elmsz(self);
937
+ offset = 0;
938
+ for (i=nd; i--;) {
939
+ if (na_test_reduce(reduce,i)) {
940
+ offset += (na->shape[i]-1)*stride;
941
+ sign = -1;
942
+ } else {
943
+ sign = 1;
944
+ }
945
+ SDX_SET_STRIDE(na2->stridx[i],stride*sign);
946
+ stride *= na->shape[i];
947
+ }
948
+ na2->offset = offset;
949
+ na2->data = self;
950
+ break;
951
+ case NARRAY_VIEW_T:
952
+ GetNArrayView(self, na1);
953
+ offset = na1->offset;
954
+ for (i=0; i<nd; i++) {
955
+ n = na1->base.shape[i];
956
+ if (SDX_IS_INDEX(na1->stridx[i])) {
957
+ idx1 = SDX_GET_INDEX(na1->stridx[i]);
958
+ idx2 = ALLOC_N(size_t,n);
959
+ if (na_test_reduce(reduce,i)) {
960
+ for (j=0; j<n; j++) {
961
+ idx2[n-1-j] = idx1[j];
962
+ }
963
+ } else {
964
+ for (j=0; j<n; j++) {
965
+ idx2[j] = idx1[j];
966
+ }
967
+ }
968
+ SDX_SET_INDEX(na2->stridx[i],idx2);
969
+ } else {
970
+ stride = SDX_GET_STRIDE(na1->stridx[i]);
971
+ if (na_test_reduce(reduce,i)) {
972
+ offset += (n-1)*stride;
973
+ SDX_SET_STRIDE(na2->stridx[i],-stride);
974
+ } else {
975
+ na2->stridx[i] = na1->stridx[i];
976
+ }
977
+ }
978
+ }
979
+ na2->offset = offset;
980
+ na2->data = na1->data;
981
+ break;
982
+ }
983
+
984
+ return view;
985
+ }
986
+
987
+ //----------------------------------------------------------------------
988
+
989
+ VALUE
990
+ numo_na_upcast(VALUE type1, VALUE type2)
991
+ {
992
+ VALUE upcast_hash;
993
+ VALUE result_type;
994
+
995
+ if (type1==type2) {
996
+ return type1;
997
+ }
998
+ upcast_hash = rb_const_get(type1, rb_intern("UPCAST"));
999
+ result_type = rb_hash_aref(upcast_hash, type2);
1000
+ if (NIL_P(result_type)) {
1001
+ if (TYPE(type2)==T_CLASS) {
1002
+ if (RTEST(rb_class_inherited_p(type2,cNArray))) {
1003
+ upcast_hash = rb_const_get(type2, rb_intern("UPCAST"));
1004
+ result_type = rb_hash_aref(upcast_hash, type1);
1005
+ }
1006
+ }
1007
+ }
1008
+ return result_type;
1009
+ }
1010
+
1011
+ /*
1012
+ Returns an array containing other and self,
1013
+ both are converted to upcasted type of NArray.
1014
+ Note that NArray has distinct UPCAST mechanism.
1015
+ Coerce is used for operation between non-NArray and NArray.
1016
+ @overload coerce(other)
1017
+ @param [Object] other numeric object.
1018
+ @return [Array] NArray-casted [other,self]
1019
+ */
1020
+ static VALUE
1021
+ nary_coerce(VALUE x, VALUE y)
1022
+ {
1023
+ VALUE type;
1024
+
1025
+ type = numo_na_upcast(CLASS_OF(x), CLASS_OF(y));
1026
+ y = rb_funcall(type,rb_intern("cast"),1,y);
1027
+ return rb_assoc_new(y , x);
1028
+ }
1029
+
1030
+
1031
+ /*
1032
+ Returns total byte size of NArray.
1033
+ @return [Integer] byte size.
1034
+ */
1035
+ static VALUE
1036
+ nary_byte_size(VALUE self)
1037
+ {
1038
+ VALUE velmsz; //klass,
1039
+ narray_t *na;
1040
+ size_t sz;
1041
+
1042
+ GetNArray(self,na);
1043
+ velmsz = rb_const_get(CLASS_OF(self), rb_intern(ELEMENT_BYTE_SIZE));
1044
+ sz = SIZE2NUM(NUM2SIZE(velmsz) * na->size);
1045
+ return sz;
1046
+ }
1047
+
1048
+ /*
1049
+ Returns byte size of one element of NArray.
1050
+ @return [Numeric] byte size.
1051
+ */
1052
+ static VALUE
1053
+ nary_s_byte_size(VALUE type)
1054
+ {
1055
+ return rb_const_get(type, rb_intern(ELEMENT_BYTE_SIZE));
1056
+ }
1057
+
1058
+
1059
+ /*
1060
+ Returns a new 1-D array initialized from binary raw data in a string.
1061
+ @overload from_string(string,[shape])
1062
+ @param [String] string Binary raw data.
1063
+ @param [Array] shape array of integers representing array shape.
1064
+ @return [Numo::NArray] NArray containing binary data.
1065
+ */
1066
+ static VALUE
1067
+ nary_s_from_string(int argc, VALUE *argv, VALUE type)
1068
+ {
1069
+ size_t len, str_len, elmsz;
1070
+ size_t *shape;
1071
+ char *ptr;
1072
+ int i, nd, narg;
1073
+ VALUE vstr,vshape,vna;
1074
+
1075
+ narg = rb_scan_args(argc,argv,"11",&vstr,&vshape);
1076
+ str_len = RSTRING_LEN(vstr);
1077
+ elmsz = na_dtype_elmsz(type);
1078
+ if (narg==2) {
1079
+ nd = RARRAY_LEN(vshape);
1080
+ if (nd == 0 || nd > NA_MAX_DIMENSION) {
1081
+ rb_raise(nary_eDimensionError,"too long or empty shape (%d)", nd);
1082
+ }
1083
+ shape = ALLOCA_N(size_t,nd);
1084
+ len = 1;
1085
+ for (i=0; i<nd; ++i) {
1086
+ len *= shape[i] = NUM2SIZE(RARRAY_AREF(vshape,i));
1087
+ }
1088
+ if (len*elmsz != str_len) {
1089
+ rb_raise(rb_eArgError, "size mismatch");
1090
+ }
1091
+ } else {
1092
+ nd = 1;
1093
+ shape = ALLOCA_N(size_t,nd);
1094
+ shape[0] = len = str_len / elmsz;
1095
+ if (len == 0) {
1096
+ rb_raise(rb_eArgError, "string is empty or too short");
1097
+ }
1098
+ }
1099
+
1100
+ vna = rb_narray_new(type, nd, shape);
1101
+ ptr = na_get_pointer_for_write(vna);
1102
+
1103
+ memcpy(ptr, RSTRING_PTR(vstr), elmsz*len);
1104
+
1105
+ return vna;
1106
+ }
1107
+
1108
+ /*
1109
+ Returns string containing the raw data bytes in NArray.
1110
+ @overload to_string()
1111
+ @return [String] String object containing binary raw data.
1112
+ */
1113
+ static VALUE
1114
+ nary_to_string(VALUE self)
1115
+ {
1116
+ size_t len, esz;
1117
+ char *ptr;
1118
+ VALUE str;
1119
+ narray_t *na;
1120
+
1121
+ GetNArray(self,na);
1122
+ if (na->type == NARRAY_VIEW_T) {
1123
+ self = na_copy(self);
1124
+ }
1125
+ esz = na_get_elmsz(self);
1126
+ len = na->size * esz;
1127
+ ptr = na_get_pointer_for_read(self);
1128
+ str = rb_usascii_str_new(ptr,len);
1129
+ RB_GC_GUARD(self);
1130
+ return str;
1131
+ }
1132
+
1133
+
1134
+ /*
1135
+ Cast self to another NArray datatype.
1136
+ @overload cast_to(datatype)
1137
+ @param [Class] datatype NArray datatype.
1138
+ @return [Numo::NArray]
1139
+ */
1140
+ static VALUE
1141
+ nary_cast_to(VALUE obj, VALUE type)
1142
+ {
1143
+ return rb_funcall(type, rb_intern("cast"), 1, obj);
1144
+ }
1145
+
1146
+
1147
+
1148
+ bool
1149
+ na_test_reduce(VALUE reduce, int dim)
1150
+ {
1151
+ size_t m;
1152
+
1153
+ if (!RTEST(reduce))
1154
+ return 0;
1155
+ if (FIXNUM_P(reduce)) {
1156
+ m = FIX2LONG(reduce);
1157
+ if (m==0) return 1;
1158
+ return (m & (1u<<dim)) ? 1 : 0;
1159
+ } else {
1160
+ return (rb_funcall(reduce,rb_intern("[]"),1,INT2FIX(dim))==INT2FIX(1)) ?
1161
+ 1 : 0 ;
1162
+ }
1163
+ }
1164
+
1165
+
1166
+ VALUE
1167
+ na_reduce_dimension(int argc, VALUE *argv, int naryc, VALUE *naryv)
1168
+ {
1169
+ int ndim, ndim0;
1170
+ int row_major;
1171
+ int i, r;
1172
+ size_t j;
1173
+ size_t len;
1174
+ ssize_t beg, step;
1175
+ VALUE v;
1176
+ narray_t *na;
1177
+ size_t m;
1178
+ VALUE reduce;
1179
+
1180
+ if (naryc<1) {
1181
+ rb_raise(rb_eRuntimeError,"must be positive: naryc=%d", naryc);
1182
+ }
1183
+ GetNArray(naryv[0],na);
1184
+ reduce = na->reduce;
1185
+ if (argc==0) {
1186
+ //printf("pass argc=0 reduce=%d\n",NUM2INT(reduce));
1187
+ return reduce;
1188
+ }
1189
+ ndim = ndim0 = na->ndim;
1190
+ row_major = TEST_COLUMN_MAJOR(naryv[0]);
1191
+ for (i=1; i<naryc; i++) {
1192
+ GetNArray(naryv[i],na);
1193
+ if (TEST_COLUMN_MAJOR(naryv[i]) != row_major) {
1194
+ rb_raise(nary_eDimensionError,"dimension order is different");
1195
+ }
1196
+ if (na->ndim > ndim) {
1197
+ ndim = na->ndim;
1198
+ }
1199
+ }
1200
+ if (ndim != ndim0) {
1201
+ j = FIX2ULONG(reduce) << (ndim-ndim0);
1202
+ reduce = ULONG2NUM(j);
1203
+ if (!FIXNUM_P(reduce)) {
1204
+ rb_raise(nary_eDimensionError,"reduce has too many bits");
1205
+ }
1206
+ }
1207
+ //printf("argc=%d\n",argc);
1208
+
1209
+ m = 0;
1210
+ reduce = Qnil;
1211
+ for (i=0; i<argc; i++) {
1212
+ v = argv[i];
1213
+ //printf("argv[%d]=",i);rb_p(v);
1214
+ if (TYPE(v)==T_FIXNUM) {
1215
+ beg = FIX2INT(v);
1216
+ if (beg<0) beg+=ndim;
1217
+ if (beg>=ndim || beg<0) {
1218
+ rb_raise(nary_eDimensionError,"dimension is out of range");
1219
+ }
1220
+ len = 1;
1221
+ step = 0;
1222
+ //printf("beg=%d step=%d len=%d\n",beg,step,len);
1223
+ } else if (rb_obj_is_kind_of(v,rb_cRange) ||
1224
+ rb_obj_is_kind_of(v,na_cStep)) {
1225
+ nary_step_array_index( v, ndim, &len, &beg, &step );
1226
+ } else {
1227
+ rb_raise(nary_eDimensionError, "invalid dimension argument %s",
1228
+ rb_obj_classname(v));
1229
+ }
1230
+ for (j=0; j<len; j++) {
1231
+ r = beg + step*j;
1232
+ if (row_major)
1233
+ r = ndim-1-r;
1234
+ if (reduce==Qnil) {
1235
+ if ( r < (ssize_t)sizeof(size_t) ) {
1236
+ m |= ((size_t)1) << r;
1237
+ continue;
1238
+ } else {
1239
+ reduce = SIZE2NUM(m);
1240
+ }
1241
+ }
1242
+ v = rb_funcall( INT2FIX(1), rb_intern("<<"), 1, INT2FIX(r) );
1243
+ reduce = rb_funcall( reduce, rb_intern("|"), 1, v );
1244
+ }
1245
+ }
1246
+ if (reduce==Qnil) reduce = SIZE2NUM(m);
1247
+ return reduce;
1248
+ }
1249
+
1250
+ //--------------------------------------
1251
+
1252
+ /*
1253
+ void
1254
+ na_index_arg_to_internal_order( int argc, VALUE *argv, VALUE self )
1255
+ {
1256
+ int i,j;
1257
+ VALUE tmp;
1258
+
1259
+ if (TEST_COLUMN_MAJOR(self)) {
1260
+ for (i=0,j=argc-1; i<argc/2; i++,j--) {
1261
+ tmp = argv[i];
1262
+ argv[i] = argv[j];
1263
+ argv[j] = tmp;
1264
+ }
1265
+ }
1266
+ }
1267
+
1268
+ VALUE
1269
+ na_index_array_to_internal_order( VALUE args, VALUE self )
1270
+ {
1271
+ int i,j;
1272
+
1273
+ if (TEST_COLUMN_MAJOR(self)) {
1274
+ return rb_funcall( args, rb_intern("reverse"), 0 );
1275
+ }
1276
+ return args;
1277
+ }
1278
+ */
1279
+
1280
+
1281
+ /*
1282
+ Return true if column major.
1283
+ */
1284
+ VALUE na_column_major_p( VALUE self )
1285
+ {
1286
+ if (TEST_COLUMN_MAJOR(self))
1287
+ return Qtrue;
1288
+ else
1289
+ return Qfalse;
1290
+ }
1291
+
1292
+ /*
1293
+ Return true if row major.
1294
+ */
1295
+ VALUE na_row_major_p( VALUE self )
1296
+ {
1297
+ if (TEST_ROW_MAJOR(self))
1298
+ return Qtrue;
1299
+ else
1300
+ return Qfalse;
1301
+ }
1302
+
1303
+
1304
+ /*
1305
+ Return true if byte swapped.
1306
+ */
1307
+ VALUE na_byte_swapped_p( VALUE self )
1308
+ {
1309
+ if (TEST_BYTE_SWAPPED(self))
1310
+ return Qtrue;
1311
+ return Qfalse;
1312
+ }
1313
+
1314
+ /*
1315
+ Return true if not byte swapped.
1316
+ */
1317
+ VALUE na_host_order_p( VALUE self )
1318
+ {
1319
+ if (TEST_BYTE_SWAPPED(self))
1320
+ return Qfalse;
1321
+ return Qtrue;
1322
+ }
1323
+
1324
+
1325
+ /*
1326
+ Returns view of narray with inplace flagged.
1327
+ @return [Numo::NArray] view of narray with inplace flag.
1328
+ */
1329
+ VALUE na_inplace( VALUE self )
1330
+ {
1331
+ VALUE view = self;
1332
+ //view = na_clone(self);
1333
+ SET_INPLACE(view);
1334
+ return view;
1335
+ }
1336
+
1337
+ /*
1338
+ Set inplace flag to self.
1339
+ @return [Numo::NArray] self
1340
+ */
1341
+ VALUE na_inplace_bang( VALUE self )
1342
+ {
1343
+ SET_INPLACE(self);
1344
+ return self;
1345
+ }
1346
+
1347
+ VALUE na_inplace_store( VALUE self, VALUE val )
1348
+ {
1349
+ if (self==val)
1350
+ return self;
1351
+ else
1352
+ return na_store( self, val );
1353
+ }
1354
+
1355
+ /*
1356
+ Return true if inplace flagged.
1357
+ */
1358
+ VALUE na_inplace_p( VALUE self )
1359
+ {
1360
+ if (TEST_INPLACE(self))
1361
+ return Qtrue;
1362
+ else
1363
+ return Qfalse;
1364
+ }
1365
+
1366
+ /*
1367
+ Unset inplace flag to self.
1368
+ @return [Numo::NArray] self
1369
+ */
1370
+ VALUE na_out_of_place_bang( VALUE self )
1371
+ {
1372
+ UNSET_INPLACE(self);
1373
+ return self;
1374
+ }
1375
+
1376
+ int na_debug_flag=0;
1377
+
1378
+ VALUE na_debug_set(VALUE mod, VALUE flag)
1379
+ {
1380
+ na_debug_flag = RTEST(flag);
1381
+ return Qnil;
1382
+ }
1383
+
1384
+ double na_profile_value=0;
1385
+
1386
+ VALUE na_profile(VALUE mod)
1387
+ {
1388
+ return rb_float_new(na_profile_value);
1389
+ }
1390
+
1391
+ VALUE na_profile_set(VALUE mod, VALUE val)
1392
+ {
1393
+ na_profile_value = NUM2DBL(val);
1394
+ return val;
1395
+ }
1396
+
1397
+
1398
+ /*
1399
+ Equality of self and other in view of numerical array.
1400
+ i.e., both arrays have same shape and corresponding elements are equal.
1401
+ @overload == other
1402
+ @param [Object] other
1403
+ @return [Boolean] true if self and other is equal.
1404
+ */
1405
+ VALUE
1406
+ na_equal(VALUE self, volatile VALUE other)
1407
+ {
1408
+ volatile VALUE vbool;
1409
+ narray_t *na1, *na2;
1410
+ int i;
1411
+
1412
+ GetNArray(self,na1);
1413
+
1414
+ if (!rb_obj_is_kind_of(other,cNArray)) {
1415
+ other = rb_funcall(CLASS_OF(self), rb_intern("cast"), 1, other);
1416
+ }
1417
+
1418
+ GetNArray(other,na2);
1419
+ if (na1->ndim != na2->ndim) {
1420
+ return Qfalse;
1421
+ }
1422
+ for (i=0; i<na1->ndim; i++) {
1423
+ if (na1->shape[i] != na2->shape[i]) {
1424
+ return Qfalse;
1425
+ }
1426
+ }
1427
+ vbool = rb_funcall(self, rb_intern("eq"), 1, other);
1428
+ return (rb_funcall(vbool, rb_intern("count_false"), 0)==INT2FIX(0)) ? Qtrue : Qfalse;
1429
+ }
1430
+
1431
+
1432
+
1433
+ /* initialization of NArray Class */
1434
+ void
1435
+ Init_narray()
1436
+ {
1437
+ mNumo = rb_define_module("Numo");
1438
+
1439
+ /* define NArray class */
1440
+ cNArray = rb_define_class_under(mNumo, "NArray", rb_cObject);
1441
+
1442
+ #ifndef HAVE_RB_CCOMPLEX
1443
+ rb_require("complex");
1444
+ rb_cComplex = rb_const_get(rb_cObject, rb_intern("Complex"));
1445
+ #endif
1446
+
1447
+ rb_define_const(cNArray, "VERSION", rb_str_new2(NARRAY_VERSION));
1448
+
1449
+ nary_eCastError = rb_define_class_under(cNArray, "CastError", rb_eStandardError);
1450
+ nary_eShapeError = rb_define_class_under(cNArray, "ShapeError", rb_eStandardError);
1451
+ nary_eOperationError = rb_define_class_under(cNArray, "OperationError", rb_eStandardError);
1452
+ nary_eDimensionError = rb_define_class_under(cNArray, "DimensionError", rb_eStandardError);
1453
+
1454
+ rb_define_singleton_method(cNArray, "debug=", na_debug_set, 1);
1455
+ rb_define_singleton_method(cNArray, "profile", na_profile, 0);
1456
+ rb_define_singleton_method(cNArray, "profile=", na_profile_set, 1);
1457
+
1458
+ /* Ruby allocation framework */
1459
+ rb_define_alloc_func(cNArray, na_s_allocate);
1460
+ rb_define_method(cNArray, "initialize", na_initialize, -2);
1461
+ rb_define_method(cNArray, "initialize_copy", na_initialize_copy, 1);
1462
+
1463
+ rb_define_singleton_method(cNArray, "zeros", na_s_zeros, -1);
1464
+ rb_define_singleton_method(cNArray, "ones", na_s_ones, -1);
1465
+ rb_define_singleton_method(cNArray, "eye", na_s_eye, -1);
1466
+
1467
+ rb_define_method(cNArray, "size", na_size, 0);
1468
+ rb_define_alias (cNArray, "length","size");
1469
+ rb_define_alias (cNArray, "total","size");
1470
+ rb_define_method(cNArray, "shape", na_shape, 0);
1471
+ rb_define_method(cNArray, "ndim", na_ndim,0);
1472
+ rb_define_alias (cNArray, "rank","ndim");
1473
+
1474
+ rb_define_method(cNArray, "debug_info", rb_narray_debug_info, 0);
1475
+
1476
+ rb_define_method(cNArray, "view", na_make_view, 0);
1477
+ rb_define_method(cNArray, "expand_dims", na_expand_dims, 1);
1478
+ rb_define_method(cNArray, "reverse", nary_reverse, -1);
1479
+
1480
+ rb_define_singleton_method(cNArray, "upcast", numo_na_upcast, 1);
1481
+ rb_define_singleton_method(cNArray, "byte_size", nary_s_byte_size, 0);
1482
+
1483
+ rb_define_singleton_method(cNArray, "from_string", nary_s_from_string, -1);
1484
+ rb_define_method(cNArray, "to_string", nary_to_string, 0);
1485
+
1486
+ rb_define_method(cNArray, "byte_size", nary_byte_size, 0);
1487
+
1488
+ rb_define_method(cNArray, "cast_to", nary_cast_to, 1);
1489
+
1490
+ rb_define_method(cNArray, "coerce", nary_coerce, 1);
1491
+
1492
+ rb_define_method(cNArray, "column_major?", na_column_major_p, 0);
1493
+ rb_define_method(cNArray, "row_major?", na_row_major_p, 0);
1494
+ rb_define_method(cNArray, "byte_swapped?", na_byte_swapped_p, 0);
1495
+ rb_define_method(cNArray, "host_order?", na_host_order_p, 0);
1496
+
1497
+ rb_define_method(cNArray, "inplace", na_inplace, 0);
1498
+ rb_define_method(cNArray, "inplace?", na_inplace_p, 0);
1499
+ rb_define_method(cNArray, "inplace!", na_inplace_bang, 0);
1500
+ rb_define_method(cNArray, "out_of_place!", na_out_of_place_bang, 0);
1501
+ rb_define_alias (cNArray, "not_inplace!", "out_of_place!");
1502
+
1503
+ rb_define_method(cNArray, "==", na_equal, 1);
1504
+
1505
+ id_allocate = rb_intern("allocate");
1506
+ id_contiguous_stride = rb_intern(CONTIGUOUS_STRIDE);
1507
+ //id_element_bit_size = rb_intern(ELEMENT_BIT_SIZE);
1508
+ //id_element_byte_size = rb_intern(ELEMENT_BYTE_SIZE);
1509
+
1510
+ sym_reduce = ID2SYM(rb_intern("reduce"));
1511
+ sym_option = ID2SYM(rb_intern("option"));
1512
+ sym_loop_opt = ID2SYM(rb_intern("loop_opt"));
1513
+ sym_init = ID2SYM(rb_intern("init"));
1514
+
1515
+ Init_nary_step();
1516
+ Init_nary_index();
1517
+
1518
+ Init_nary_data();
1519
+
1520
+ Init_nary_dcomplex();
1521
+ Init_nary_dfloat();
1522
+ Init_nary_scomplex();
1523
+ Init_nary_sfloat();
1524
+
1525
+ Init_nary_int64();
1526
+ Init_nary_uint64();
1527
+ Init_nary_int32();
1528
+ Init_nary_uint32();
1529
+ Init_nary_int16();
1530
+ Init_nary_uint16();
1531
+ Init_nary_int8();
1532
+ Init_nary_uint8();
1533
+ Init_nary_bit();
1534
+
1535
+ Init_nary_math();
1536
+
1537
+ Init_nary_rand();
1538
+ Init_nary_array();
1539
+ Init_nary_struct();
1540
+ Init_nary_robject();
1541
+ }