numo-narray 0.9.0.1-x64-mingw32

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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +4 -0
  3. data/README.md +47 -0
  4. data/Rakefile +41 -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 +117 -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 +140 -0
  82. data/ext/numo/narray/narray.c +1539 -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 +872 -0
  114. data/lib/2.1/numo/narray.so +0 -0
  115. data/lib/2.2/numo/narray.so +0 -0
  116. data/lib/2.3/numo/narray.so +0 -0
  117. data/lib/erbpp.rb +286 -0
  118. data/lib/erbpp/line_number.rb +126 -0
  119. data/lib/erbpp/narray_def.rb +338 -0
  120. data/lib/numo/narray.rb +6 -0
  121. data/numo-narray.gemspec +35 -0
  122. data/spec/bit_spec.rb +93 -0
  123. data/spec/narray_spec.rb +249 -0
  124. 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,140 @@
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
+ rb_hash_aset(hCast, rb_cFixnum, rb_mMath);
134
+ rb_hash_aset(hCast, rb_cBignum, rb_mMath);
135
+ rb_hash_aset(hCast, rb_cInteger, rb_mMath);
136
+ rb_hash_aset(hCast, rb_cFloat, rb_mMath);
137
+ rb_hash_aset(hCast, rb_cComplex, numo_mDComplexMath);
138
+
139
+ id_send = rb_intern("send");
140
+ }
@@ -0,0 +1,1539 @@
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, const 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, const 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, const 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
+ nary_eCastError = rb_define_class_under(cNArray, "CastError", rb_eStandardError);
1448
+ nary_eShapeError = rb_define_class_under(cNArray, "ShapeError", rb_eStandardError);
1449
+ nary_eOperationError = rb_define_class_under(cNArray, "OperationError", rb_eStandardError);
1450
+ nary_eDimensionError = rb_define_class_under(cNArray, "DimensionError", rb_eStandardError);
1451
+
1452
+ rb_define_singleton_method(cNArray, "debug=", na_debug_set, 1);
1453
+ rb_define_singleton_method(cNArray, "profile", na_profile, 0);
1454
+ rb_define_singleton_method(cNArray, "profile=", na_profile_set, 1);
1455
+
1456
+ /* Ruby allocation framework */
1457
+ rb_define_alloc_func(cNArray, na_s_allocate);
1458
+ rb_define_method(cNArray, "initialize", na_initialize, -2);
1459
+ rb_define_method(cNArray, "initialize_copy", na_initialize_copy, 1);
1460
+
1461
+ rb_define_singleton_method(cNArray, "zeros", na_s_zeros, -1);
1462
+ rb_define_singleton_method(cNArray, "ones", na_s_ones, -1);
1463
+ rb_define_singleton_method(cNArray, "eye", na_s_eye, -1);
1464
+
1465
+ rb_define_method(cNArray, "size", na_size, 0);
1466
+ rb_define_alias (cNArray, "length","size");
1467
+ rb_define_alias (cNArray, "total","size");
1468
+ rb_define_method(cNArray, "shape", na_shape, 0);
1469
+ rb_define_method(cNArray, "ndim", na_ndim,0);
1470
+ rb_define_alias (cNArray, "rank","ndim");
1471
+
1472
+ rb_define_method(cNArray, "debug_info", rb_narray_debug_info, 0);
1473
+
1474
+ rb_define_method(cNArray, "view", na_make_view, 0);
1475
+ rb_define_method(cNArray, "expand_dims", na_expand_dims, 1);
1476
+ rb_define_method(cNArray, "reverse", nary_reverse, -1);
1477
+
1478
+ rb_define_singleton_method(cNArray, "upcast", numo_na_upcast, 1);
1479
+ rb_define_singleton_method(cNArray, "byte_size", nary_s_byte_size, 0);
1480
+
1481
+ rb_define_singleton_method(cNArray, "from_string", nary_s_from_string, -1);
1482
+ rb_define_method(cNArray, "to_string", nary_to_string, 0);
1483
+
1484
+ rb_define_method(cNArray, "byte_size", nary_byte_size, 0);
1485
+
1486
+ rb_define_method(cNArray, "cast_to", nary_cast_to, 1);
1487
+
1488
+ rb_define_method(cNArray, "coerce", nary_coerce, 1);
1489
+
1490
+ rb_define_method(cNArray, "column_major?", na_column_major_p, 0);
1491
+ rb_define_method(cNArray, "row_major?", na_row_major_p, 0);
1492
+ rb_define_method(cNArray, "byte_swapped?", na_byte_swapped_p, 0);
1493
+ rb_define_method(cNArray, "host_order?", na_host_order_p, 0);
1494
+
1495
+ rb_define_method(cNArray, "inplace", na_inplace, 0);
1496
+ rb_define_method(cNArray, "inplace?", na_inplace_p, 0);
1497
+ rb_define_method(cNArray, "inplace!", na_inplace_bang, 0);
1498
+ rb_define_method(cNArray, "out_of_place!", na_out_of_place_bang, 0);
1499
+ rb_define_alias (cNArray, "not_inplace!", "out_of_place!");
1500
+
1501
+ rb_define_method(cNArray, "==", na_equal, 1);
1502
+
1503
+ id_allocate = rb_intern("allocate");
1504
+ id_contiguous_stride = rb_intern(CONTIGUOUS_STRIDE);
1505
+ //id_element_bit_size = rb_intern(ELEMENT_BIT_SIZE);
1506
+ //id_element_byte_size = rb_intern(ELEMENT_BYTE_SIZE);
1507
+
1508
+ sym_reduce = ID2SYM(rb_intern("reduce"));
1509
+ sym_option = ID2SYM(rb_intern("option"));
1510
+ sym_loop_opt = ID2SYM(rb_intern("loop_opt"));
1511
+ sym_init = ID2SYM(rb_intern("init"));
1512
+
1513
+ Init_nary_step();
1514
+ Init_nary_index();
1515
+
1516
+ Init_nary_data();
1517
+
1518
+ Init_nary_dcomplex();
1519
+ Init_nary_dfloat();
1520
+ Init_nary_scomplex();
1521
+ Init_nary_sfloat();
1522
+
1523
+ Init_nary_int64();
1524
+ Init_nary_uint64();
1525
+ Init_nary_int32();
1526
+ Init_nary_uint32();
1527
+ Init_nary_int16();
1528
+ Init_nary_uint16();
1529
+ Init_nary_int8();
1530
+ Init_nary_uint8();
1531
+ Init_nary_bit();
1532
+
1533
+ Init_nary_math();
1534
+
1535
+ Init_nary_rand();
1536
+ Init_nary_array();
1537
+ Init_nary_struct();
1538
+ Init_nary_robject();
1539
+ }