narray-nmatrix 0.6.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +809 -0
- data/MANIFEST +53 -0
- data/README.en +51 -0
- data/README.ja +52 -0
- data/SPEC.en +327 -0
- data/SPEC.ja +307 -0
- data/depend +14 -0
- data/extconf.rb +100 -0
- data/lib/narray.rb +18 -0
- data/lib/narray/narray.rb +5 -0
- data/lib/narray_ext.rb +362 -0
- data/lib/nmatrix.rb +252 -0
- data/mkmath.rb +784 -0
- data/mknafunc.rb +192 -0
- data/mkop.rb +648 -0
- data/na_array.c +650 -0
- data/na_func.c +1705 -0
- data/na_index.c +1011 -0
- data/na_linalg.c +633 -0
- data/na_random.c +416 -0
- data/narray.c +1321 -0
- data/narray.def +29 -0
- data/narray.h +186 -0
- data/narray_local.h +218 -0
- metadata +92 -0
data/SPEC.ja
ADDED
@@ -0,0 +1,307 @@
|
|
1
|
+
|
2
|
+
Ruby/NArray ver 0.6.0.7 (2013-02-01) by Masahiro TANAKA
|
3
|
+
|
4
|
+
|
5
|
+
クラスメソッド:
|
6
|
+
NArray.new(typecode, size, ...) 配列を生成する。要素は0で初期化。
|
7
|
+
|
8
|
+
NArray.byte(size,...) 1 byte unsigned integer
|
9
|
+
NArray.sint(size,...) 2 byte signed integer
|
10
|
+
NArray.int(size,...) 4 byte signed integer
|
11
|
+
NArray.sfloat(size,...) single precision float
|
12
|
+
NArray.float(size,...) double precision float
|
13
|
+
NArray.scomplex(size,...) single precision complex
|
14
|
+
NArray.complex(size,...) double precision complex
|
15
|
+
NArray.object(size,...) Ruby object
|
16
|
+
以上要素は0またはnilで初期化。
|
17
|
+
|
18
|
+
NArray.to_na(array) NArrayに変換
|
19
|
+
NArray.to_na(string,type[,size,..])
|
20
|
+
NArray[...]
|
21
|
+
NArray[1,5,10.0] #=> NArray.float(3):[1.0, 5.0, 10.0]
|
22
|
+
NArray[1..10] #=> NArray.int(10):[1,2,3,4,5,6,7,8,9,10]
|
23
|
+
|
24
|
+
|
25
|
+
クラス変数:
|
26
|
+
CLASS_DIMENSION データとして扱われる次元。
|
27
|
+
NArrayは0。NVectorは1。NMatrixは2。
|
28
|
+
|
29
|
+
配列情報参照
|
30
|
+
self.dim 次元(インデックスの数)を返す。
|
31
|
+
self.rank 次元(インデックスの数)を返す。
|
32
|
+
self.shape 次元ごとのサイズを返す。
|
33
|
+
self.total 全要素数を返す。
|
34
|
+
|
35
|
+
インデックス参照
|
36
|
+
self[ dim0, dim1, ... ]
|
37
|
+
|
38
|
+
-- インデックス引数に指定できるもの: 数値、範囲、配列、true, false
|
39
|
+
-- インデックスの順序: FORTRAN 型
|
40
|
+
-- 添字引数が1つの場合、多次元配列はflattenされた1次元配列とみなされる。
|
41
|
+
例: a が 3x3 配列のとき、a[3] は a[0,1] の要素を指す。
|
42
|
+
|
43
|
+
a[ 1, 2, -1 ] 要素の取り出し。負数は最後から数える(-1が最後)
|
44
|
+
要素指定の次元は縮約される。
|
45
|
+
a[ 0..3, 4..1 ] 範囲取り出し。範囲の最後が最初より前ならば逆順になる。
|
46
|
+
a[ [1,4,2] ] インデックス配列。要素が[a[1],a[4],a[2]]のNArrayが返る。
|
47
|
+
a[] a.dup と同じ。
|
48
|
+
a[ 0, true ] a[0, 0..-1] と同じ。
|
49
|
+
a[ 0, false ] aが3次元のとき、a[0,true,true] と同じ。
|
50
|
+
省略された次元すべてにtrueを指定したのと同じ。
|
51
|
+
a[ mask ] マスキング. mask は長さが a と等しい byte 型
|
52
|
+
NArray. mask の各要素の値に応じて、a のそれぞ
|
53
|
+
れは落される(0の場合)か、保持される(0以外の場合)。
|
54
|
+
例:
|
55
|
+
a=NArray.float(2,2).indgen!
|
56
|
+
p a[ a.lt 3 ]
|
57
|
+
--> [ 0.0, 1.0, 2.0 ]
|
58
|
+
(a.lt 3 は byte 型 NArray を返す)
|
59
|
+
(同じことは a[ (a.lt 3).where ] でも出来る)
|
60
|
+
|
61
|
+
-- self.slice(...) self[...] と同じだが、長さが1になった次元を落
|
62
|
+
さず(self[]は落す)、もとのランクを保つ。但し、
|
63
|
+
1次元インデックス付けとマスキングは例外([]と同
|
64
|
+
じ)。
|
65
|
+
|
66
|
+
インデックス代入。-- 取出しとほぼ同じルール。
|
67
|
+
|
68
|
+
a[ 1, 2, 3 ] = 1
|
69
|
+
a[ 0..3, 1..4, 2..5 ] = 2
|
70
|
+
a[ [1,3,2,4], true ] = 3
|
71
|
+
a[] = 4 a.fill!(4) と同じ。
|
72
|
+
|
73
|
+
a[0..2] = b[1..5] --> 要素数が異なるのでエラー。
|
74
|
+
a[1,2] = b[0..2,1..3] [1,2]を始点として代入。
|
75
|
+
a[0..2,0..3] = b[0..2,1] 繰り返し代入。
|
76
|
+
( a[0,0]=b[0,1],..,a[0,3]=b[0,1] )
|
77
|
+
|
78
|
+
行・列の削除 -- インデックス取り出しの逆
|
79
|
+
|
80
|
+
self.delete_at(...) 引数はインデクス参照と同じ。
|
81
|
+
参照: https://github.com/masa16/narray/issues/5
|
82
|
+
|
83
|
+
値のセット。
|
84
|
+
self.indgen!([start[,step]]) startからstepづつ増加した値をセット。
|
85
|
+
self.fill!(value) すべての要素にvalueをセット。
|
86
|
+
self.random!(max) 0<=x<max の一様なランダム値を生成。
|
87
|
+
using MT19337
|
88
|
+
self.randomn 平均0、分散1の正規分布のランダム値を生成。
|
89
|
+
(Box-Muller)
|
90
|
+
NArray.srand([seed]) 乱数のシードを設定。
|
91
|
+
省略時は時刻から自動生成。
|
92
|
+
|
93
|
+
演算: 要素ごとにおこなう。
|
94
|
+
a = NArray.float(3,3).indgen
|
95
|
+
b = NArray.float(3,3).fill(10)
|
96
|
+
c = a*b # --> NArray.float(3,3)
|
97
|
+
|
98
|
+
a = NArray.float(3,1).indgen
|
99
|
+
b = NArray.float(1,3).fill(10)
|
100
|
+
c = a*b # --> NArray.float(3,3) -- size=1の次元は拡張する。
|
101
|
+
|
102
|
+
算術演算子
|
103
|
+
-self
|
104
|
+
self + other
|
105
|
+
self - other
|
106
|
+
self * other
|
107
|
+
self / other
|
108
|
+
self % other
|
109
|
+
self ** other
|
110
|
+
self.abs
|
111
|
+
|
112
|
+
self.add! other
|
113
|
+
self.sbt! other
|
114
|
+
self.mul! other
|
115
|
+
self.div! other
|
116
|
+
self.mod! other
|
117
|
+
|
118
|
+
self.mul_add(other,dim,...) (self * other).sum(dim,...)とほぼ同じ。
|
119
|
+
ただし途中で配列を作らない。
|
120
|
+
|
121
|
+
ビット演算子(整数のみ可能)
|
122
|
+
~self
|
123
|
+
self & other
|
124
|
+
self | other
|
125
|
+
self ^ other
|
126
|
+
|
127
|
+
比較
|
128
|
+
-- 要素ごとに値を比較し、結果をBYTE型 NArrayを返す。
|
129
|
+
true/falseでないことに注意。
|
130
|
+
self.eq other ( == とは異なることに注意)
|
131
|
+
self.ne other
|
132
|
+
self.gt other
|
133
|
+
self > other
|
134
|
+
self.ge other
|
135
|
+
self >= other
|
136
|
+
self.lt other
|
137
|
+
self < other
|
138
|
+
self.le other
|
139
|
+
self <= other
|
140
|
+
|
141
|
+
self.and other 要素ごとの条件比較。
|
142
|
+
self.or other
|
143
|
+
self.xor other
|
144
|
+
self.not other
|
145
|
+
|
146
|
+
self.all? 要素がすべて真ならば真。
|
147
|
+
self.any? 要素のどれかが真ならば真。
|
148
|
+
self.none? 要素のどれかが真ならば真。
|
149
|
+
self.where 要素が真のインデックス配列を返す。
|
150
|
+
self.where2 要素が真と偽のインデックス配列を含む(Ruby)配列を返す。
|
151
|
+
|
152
|
+
例: idx_t,idx_f = (a>12).where2
|
153
|
+
|
154
|
+
同値性
|
155
|
+
NArray[1] == NArray[1] #=> true
|
156
|
+
NArray[1] == NArray[1.0] #=> true
|
157
|
+
NArray[1].eql? NArray[1] #=> true
|
158
|
+
NArray[1].eql? NArray[1.0] #=> false
|
159
|
+
NArray[1].equal? NArray[1] #=> false
|
160
|
+
a=b=NArray[1]; a.equal? b #=> true
|
161
|
+
|
162
|
+
統計
|
163
|
+
self.sum(dim,..) 指定した次元の和
|
164
|
+
self.cumsum 累積和(1次元配列のみ)
|
165
|
+
self.prod(dim,..) 指定した次元の積
|
166
|
+
self.cumprod 累積積(1次元配列のみ)
|
167
|
+
self.mean(dim,..) 指定した次元の平均。
|
168
|
+
self.stddev(dim,..) 指定した次元の標準偏差(標本標準偏差)。
|
169
|
+
self.rms(dim,..) 指定した次元のroot mean square。
|
170
|
+
self.rmsdev(dim,..) 指定した次元のroot mean square deviation。
|
171
|
+
self.min(dim,..) 指定した次元の最小。
|
172
|
+
self.max(dim,..) 指定した次元の最大。
|
173
|
+
(省略時は全ての次元。Range指定可。)
|
174
|
+
self.median(dim) 0..dimの次元の中央値。省略時はすべての次元。
|
175
|
+
|
176
|
+
ソート
|
177
|
+
self.sort(dim) 0..dimの次元でソート。省略時はすべての次元。
|
178
|
+
self.sort_index(dim) ソートしたインデックスを返す。
|
179
|
+
self[self.sort_index] は self.sort と同等。
|
180
|
+
|
181
|
+
転置
|
182
|
+
self.transpose( dim0, dim1, .. )
|
183
|
+
配列の転置。selfの第(dim0)次元が新しい配列の第0次元になる。
|
184
|
+
負数は後からの順番。
|
185
|
+
transpose(-1,1..-2,0) で最初と最後を入れ換え。
|
186
|
+
|
187
|
+
インデックスの変更 (要素数は不変)
|
188
|
+
self.reshape!(size,...)
|
189
|
+
self.shape= size,...
|
190
|
+
self.newdim!(dim,...) 指定位置にサイズ1の次元を挿入する。
|
191
|
+
|
192
|
+
データの参照
|
193
|
+
self.refer selfのデータを参照する別のオブジェクトを作成。
|
194
|
+
self.reshape(size,...) self.refer.reshape! と同様。
|
195
|
+
self.newdim(dim,...) self.refer.newdim! と同様。
|
196
|
+
|
197
|
+
反転・回転
|
198
|
+
self.reverse([dim,...]) 指定した次元を逆順にする
|
199
|
+
self.rot90([k]) 2次元配列の90度の回転をk回行う
|
200
|
+
|
201
|
+
型変換
|
202
|
+
self.floor selfより小さい最大の整数を返す。
|
203
|
+
self.ceil selfより大きい最小の整数を返す。
|
204
|
+
self.round selfにもっとも近い整数を返す。
|
205
|
+
self.to_f 値を浮動小数点数に変換する。
|
206
|
+
self.to_i 値を整数に変換する。
|
207
|
+
self.to_a 値をRubyの配列に変換する。
|
208
|
+
self.to_s バイナリデータをそのままRubyの文字列データに変換する。
|
209
|
+
self.to_string 各要素を文字列に変換する。
|
210
|
+
|
211
|
+
イテレータ
|
212
|
+
self.each {|i| ...}
|
213
|
+
self.collect {|i| ...}
|
214
|
+
self.collect! {|i| ...}
|
215
|
+
|
216
|
+
バイトスワップ
|
217
|
+
self.swap_byte バイトスワップ
|
218
|
+
self.hton ネットワークバイトオーダーに変換
|
219
|
+
self.ntoh
|
220
|
+
self.htov VAXバイトオーダーに変換
|
221
|
+
self.vtoh
|
222
|
+
|
223
|
+
Boolean / マスク関係
|
224
|
+
self.count_false 値 == 0 の要素数 (byte型のみ)
|
225
|
+
self.count_true 値 == 1 の要素数 (byte型のみ)
|
226
|
+
self.mask( mask ) self[ mask ] と同じだかマスキング専用.
|
227
|
+
[] と違い int, sint のマスクも使える.
|
228
|
+
|
229
|
+
複素数
|
230
|
+
self.real
|
231
|
+
self.imag
|
232
|
+
self.conj
|
233
|
+
self.conj!
|
234
|
+
self.angle atan2(self.imag, self.real)
|
235
|
+
self.imag= other 虚数部分にotherをセット。
|
236
|
+
self.im 虚数倍。
|
237
|
+
|
238
|
+
NMath モジュール
|
239
|
+
sqrt(x)
|
240
|
+
exp(x)
|
241
|
+
log(x)
|
242
|
+
log10(x)
|
243
|
+
log2(x)
|
244
|
+
atan2(x,y)
|
245
|
+
sin,cos,tan
|
246
|
+
sinh,cosh,tanh
|
247
|
+
asin,acos,atan
|
248
|
+
asinh,acosh,atanh
|
249
|
+
csc,sec,cot
|
250
|
+
csch,sech,coth
|
251
|
+
acsc,asec,acot
|
252
|
+
acsch,asech,acoth
|
253
|
+
covariance
|
254
|
+
|
255
|
+
|
256
|
+
FFTW モジュール (fftw-2.1.3をshared libでコンパイルしたもので確認)
|
257
|
+
(別モジュール)
|
258
|
+
fftw(x,[1|-1])
|
259
|
+
convol(a,b) FFTWを用いた畳み込み。
|
260
|
+
|
261
|
+
|
262
|
+
NMatrix
|
263
|
+
|
264
|
+
NArrayのサブクラス。最初の2次元をMatrixとして用いる。
|
265
|
+
残りの次元は多次元配列として扱われる。
|
266
|
+
次元の順序は、数学での表記とは逆: a_ij => a[j,i]
|
267
|
+
|
268
|
+
メソッド:
|
269
|
+
+,- 相手が NMatrix のときに演算可。
|
270
|
+
* 相手が NMatrix または NVector のときは Matrix積。
|
271
|
+
相手が Numeric または NArray のときは Scalar積。
|
272
|
+
例: NMatrix[[1,2],[3,4]] * [1,10]
|
273
|
+
== NMatrix[ [[1,2],[3,4]], [[10,20],[30,40]] ]
|
274
|
+
/ 相手が Numeric または NArray のときはScalar除算。
|
275
|
+
相手が square NMatrix のときはLUにより線形方程式を解く。
|
276
|
+
a/b == b.lu.solve(a)
|
277
|
+
|
278
|
+
transpose 引数を省略した場合は、最初のMatrix次元を交換。
|
279
|
+
diagonal(other)
|
280
|
+
diagonal!(other) 対角要素に値をセット。引数省略時は1をセット。
|
281
|
+
I 対角要素に値に1をセット。
|
282
|
+
inverse 逆行列
|
283
|
+
lu LU分解を計算。NMatrixLU クラスのインスタンスを返す。
|
284
|
+
|
285
|
+
|
286
|
+
NVector
|
287
|
+
|
288
|
+
NArrayのサブクラス。最初の1次元をVectorとして用いる。
|
289
|
+
残りの次元は多次元配列として扱われる。
|
290
|
+
|
291
|
+
メソッド:
|
292
|
+
+,- 相手が NVector のときに演算可。
|
293
|
+
* 相手が NMatrix のときは Matrix積。
|
294
|
+
相手が NVector のときは 内積。
|
295
|
+
相手が Numeric または NArray のときは Scalar積。
|
296
|
+
/ 相手が Numeric または NArray のときは Scalar除算。
|
297
|
+
相手が square NMatrix のときはLUにより線形方程式を解く。
|
298
|
+
v/m == m.lu.solve(v)
|
299
|
+
|
300
|
+
NMatrixLU
|
301
|
+
|
302
|
+
NMatrix#lu メソッドにより作られる。
|
303
|
+
LU (NMatrix) と pivot (NVector) を含む。
|
304
|
+
|
305
|
+
メソッド:
|
306
|
+
solve(other) LU分解の結果を使って other を解く。
|
307
|
+
other は NMatrix または NVector のインスタンス。
|
data/depend
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
na_op.c: mknafunc.rb mkop.rb
|
2
|
+
$(RUBY) -I$(srcdir) $(srcdir)/mkop.rb
|
3
|
+
|
4
|
+
na_op.o: na_op.c narray.h $(hdrdir)/ruby.h
|
5
|
+
|
6
|
+
|
7
|
+
na_math.c: mknafunc.rb mkmath.rb
|
8
|
+
$(RUBY) -I$(srcdir) $(srcdir)/mkmath.rb
|
9
|
+
|
10
|
+
na_math.o: na_math.c narray.h $(hdrdir)/ruby.h
|
11
|
+
|
12
|
+
|
13
|
+
cleanall: clean
|
14
|
+
@$(RM) -r Makefile narray_config.h na_op.c na_math.c src pkg
|
data/extconf.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require "mkmf"
|
2
|
+
|
3
|
+
def have_type(type, header=nil)
|
4
|
+
printf "checking for %s... ", type
|
5
|
+
STDOUT.flush
|
6
|
+
src = <<"SRC"
|
7
|
+
#include <ruby.h>
|
8
|
+
SRC
|
9
|
+
unless header.nil?
|
10
|
+
src << <<"SRC"
|
11
|
+
#include <#{header}>
|
12
|
+
SRC
|
13
|
+
end
|
14
|
+
r = try_link(src + <<"SRC")
|
15
|
+
int main() { return 0; }
|
16
|
+
int t() { #{type} a; return 0; }
|
17
|
+
SRC
|
18
|
+
unless r
|
19
|
+
print "no\n"
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
$defs.push(format("-DHAVE_%s", type.upcase))
|
23
|
+
print "yes\n"
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_conf_h(file)
|
28
|
+
print "creating #{file}\n"
|
29
|
+
hfile = open(file, "w")
|
30
|
+
for line in $defs
|
31
|
+
line =~ /^-D(.*)/
|
32
|
+
hfile.printf "#define %s 1\n", $1
|
33
|
+
end
|
34
|
+
hfile.close
|
35
|
+
end
|
36
|
+
|
37
|
+
if RUBY_VERSION < '1.8'
|
38
|
+
alias __install_rb :install_rb
|
39
|
+
def install_rb(mfile, dest, srcdir = nil)
|
40
|
+
__install_rb(mfile, dest, srcdir)
|
41
|
+
archdir = dest.sub(/sitelibdir/,"sitearchdir").sub(/rubylibdir/,"archdir")
|
42
|
+
path = ['$(srcdir)/narray.h','narray_config.h']
|
43
|
+
path << ['libnarray.a'] if /cygwin|mingw/ =~ RUBY_PLATFORM
|
44
|
+
for f in path
|
45
|
+
mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' %s %s\n", f, archdir
|
46
|
+
end
|
47
|
+
end
|
48
|
+
else
|
49
|
+
$INSTALLFILES = [['narray.h', '$(archdir)'], ['narray_config.h', '$(archdir)']]
|
50
|
+
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
51
|
+
$INSTALLFILES << ['libnarray.a', '$(archdir)']
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
56
|
+
if RUBY_VERSION >= '1.9.0'
|
57
|
+
$DLDFLAGS << " -Wl,--export-all,--out-implib=libnarray.a"
|
58
|
+
elsif RUBY_VERSION > '1.8.0'
|
59
|
+
$DLDFLAGS << ",--out-implib=libnarray.a"
|
60
|
+
elsif RUBY_VERSION > '1.8'
|
61
|
+
CONFIG["DLDFLAGS"] << ",--out-implib=libnarray.a"
|
62
|
+
system("touch libnarray.a")
|
63
|
+
else
|
64
|
+
CONFIG["DLDFLAGS"] << " --output-lib libnarray.a"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
#$DEBUG = true
|
69
|
+
#$CFLAGS = ["-Wall",$CFLAGS].join(" ")
|
70
|
+
|
71
|
+
srcs = %w(
|
72
|
+
narray
|
73
|
+
na_array
|
74
|
+
na_func
|
75
|
+
na_index
|
76
|
+
na_random
|
77
|
+
na_op
|
78
|
+
na_math
|
79
|
+
na_linalg
|
80
|
+
)
|
81
|
+
|
82
|
+
header = "stdint.h"
|
83
|
+
unless have_header(header)
|
84
|
+
header = "sys/types.h"
|
85
|
+
unless have_header(header)
|
86
|
+
header = nil
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
have_type("u_int8_t", header)
|
91
|
+
have_type("uint8_t", header)
|
92
|
+
have_type("int16_t", header)
|
93
|
+
have_type("int32_t", header)
|
94
|
+
have_type("u_int32_t", header)
|
95
|
+
have_type("uint32_t", header)
|
96
|
+
|
97
|
+
$objs = srcs.collect{|i| i+".o"}
|
98
|
+
|
99
|
+
create_conf_h("narray_config.h")
|
100
|
+
create_makefile("narray")
|
data/lib/narray.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# This file exists for backwards compatibility with earlier versions of NArray
|
2
|
+
# that defined all of its classes and modules in the top level namespace rather
|
3
|
+
# than just the NArray class at the top level and all other related classes and
|
4
|
+
# modules nested within the NArray class.
|
5
|
+
#
|
6
|
+
# After requiring the 'narray/narray' package to load the top level NArray class
|
7
|
+
# and the nested classes and modules it contains, top level aliases are created
|
8
|
+
# for the nested classes to provide backwards compatibility.
|
9
|
+
|
10
|
+
require 'narray/narray'
|
11
|
+
|
12
|
+
# Create top level aliases
|
13
|
+
|
14
|
+
NMath = NArray::NMath
|
15
|
+
NVector = NArray::NVector
|
16
|
+
NMatrix = NArray::NMatrix
|
17
|
+
NMatrixLU = NArray::NMatrixLU
|
18
|
+
NArrayScalar = NArray::NArrayScalar
|
@@ -0,0 +1,5 @@
|
|
1
|
+
# Require the NArray shared library that defines the top level "NA" module and
|
2
|
+
# all of its contents. Requiring "narray.so" will load the narray shared
|
3
|
+
# library even on systems that use an extension other than ".so" for shared
|
4
|
+
# libraries (e.g. ".bundle" or ".dylib" on Mac OS X or ".dll" on Windows).
|
5
|
+
require 'narray.so'
|
data/lib/narray_ext.rb
ADDED
@@ -0,0 +1,362 @@
|
|
1
|
+
# Numerical Array Extention for Ruby
|
2
|
+
# (C) Copyright 2000-2008 by Masahiro TANAKA
|
3
|
+
#
|
4
|
+
# This program is free software.
|
5
|
+
# You can distribute/modify this program
|
6
|
+
# under the same terms as Ruby itself.
|
7
|
+
# NO WARRANTY.
|
8
|
+
#
|
9
|
+
class NArray
|
10
|
+
|
11
|
+
def self.cast(array,type=nil)
|
12
|
+
case array
|
13
|
+
when NArray
|
14
|
+
when Array
|
15
|
+
array = NArray.to_na(array)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "1st argument must be NArray or Array"
|
18
|
+
end
|
19
|
+
type = array.typecode if type.nil?
|
20
|
+
shape = array.shape
|
21
|
+
na = self.new(type,*shape)
|
22
|
+
na[] = array
|
23
|
+
na
|
24
|
+
end
|
25
|
+
|
26
|
+
def integer?
|
27
|
+
self.typecode==NArray::BYTE ||
|
28
|
+
self.typecode==NArray::SINT ||
|
29
|
+
self.typecode==NArray::LINT
|
30
|
+
end
|
31
|
+
def complex?
|
32
|
+
self.typecode==NArray::DCOMPLEX ||
|
33
|
+
self.typecode==NArray::SCOMPLEX
|
34
|
+
end
|
35
|
+
|
36
|
+
def all?
|
37
|
+
where.size == size
|
38
|
+
end
|
39
|
+
|
40
|
+
def any?
|
41
|
+
where.size > 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def none?
|
45
|
+
where.size == 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(other)
|
49
|
+
other.kind_of?(NArray) &&
|
50
|
+
shape == other.shape &&
|
51
|
+
eq(other).all?
|
52
|
+
end
|
53
|
+
|
54
|
+
def eql?(other)
|
55
|
+
self.class == other.class &&
|
56
|
+
typecode == other.typecode &&
|
57
|
+
shape == other.shape &&
|
58
|
+
case typecode
|
59
|
+
when NArray::OBJECT
|
60
|
+
to_a.eql? other.to_a
|
61
|
+
else
|
62
|
+
to_s.eql? other.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def hash
|
67
|
+
case typecode
|
68
|
+
when NArray::OBJECT
|
69
|
+
[self.class, to_a].hash
|
70
|
+
else
|
71
|
+
[self.class, typecode, shape, to_s].hash
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def rank_total(*ranks)
|
76
|
+
if ranks.size>0
|
77
|
+
idx = []
|
78
|
+
ranks.each{|i| idx.push(*i)}
|
79
|
+
# ranks is expected to be, e.g., [1, 3..5, 7]
|
80
|
+
a = self.shape
|
81
|
+
n = 1
|
82
|
+
idx.each{|i| n *= a[i]}
|
83
|
+
n
|
84
|
+
else
|
85
|
+
self.total
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# delete rows/columns
|
90
|
+
def delete_at(*args)
|
91
|
+
if args.size > self.rank
|
92
|
+
raise ArgumentError, "too many arguments"
|
93
|
+
end
|
94
|
+
shp = self.shape
|
95
|
+
ind = []
|
96
|
+
self.rank.times do |i|
|
97
|
+
n = shp[i]
|
98
|
+
case a=args[i]
|
99
|
+
when Integer
|
100
|
+
a = n+a if a<0
|
101
|
+
raise IndexError, "index(%d) out of range"%[a] if a<0
|
102
|
+
x = [0...a,a+1...n]
|
103
|
+
when Range
|
104
|
+
b = a.first
|
105
|
+
b = n+b if b<0
|
106
|
+
raise IndexError, "index(%s) out of range"%[a] if b<0
|
107
|
+
e = a.last
|
108
|
+
e = n+e if e<0
|
109
|
+
e -= 1 if a.exclude_end?
|
110
|
+
raise IndexError, "index(%s) out of range"%[a] if e<0
|
111
|
+
x = [0...b,e+1...n]
|
112
|
+
when Array
|
113
|
+
x = (0...n).to_a
|
114
|
+
x -= a.map do |j|
|
115
|
+
raise IndexError, "contains non-integer" unless Integer===j
|
116
|
+
(j<0) ? n+j : j
|
117
|
+
end
|
118
|
+
else
|
119
|
+
if a
|
120
|
+
raise ArgumentError, "invalid argument"
|
121
|
+
else
|
122
|
+
x = true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
ind << x
|
126
|
+
end
|
127
|
+
self[*ind]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Statistics
|
131
|
+
def mean(*ranks)
|
132
|
+
if integer?
|
133
|
+
a = self.to_type(NArray::DFLOAT)
|
134
|
+
else
|
135
|
+
a = self
|
136
|
+
end
|
137
|
+
a = NArray.ref(a)
|
138
|
+
a.sum(*ranks) / (rank_total(*ranks))
|
139
|
+
end
|
140
|
+
|
141
|
+
def stddev(*ranks)
|
142
|
+
if integer?
|
143
|
+
a = self.to_type(NArray::DFLOAT)
|
144
|
+
else
|
145
|
+
a = self
|
146
|
+
end
|
147
|
+
a = NArray.ref(a)
|
148
|
+
n = rank_total(*ranks)
|
149
|
+
if complex?
|
150
|
+
NMath::sqrt( (( a-a.accum(*ranks).div!(n) ).abs**2).sum(*ranks)/(n-1) )
|
151
|
+
else
|
152
|
+
NMath::sqrt( (( a-a.accum(*ranks).div!(n) )**2).sum(*ranks)/(n-1) )
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def rms(*ranks)
|
157
|
+
if integer?
|
158
|
+
a = self.to_type(NArray::DFLOAT)
|
159
|
+
else
|
160
|
+
a = self
|
161
|
+
end
|
162
|
+
a = NArray.ref(a)
|
163
|
+
n = rank_total(*ranks)
|
164
|
+
if complex?
|
165
|
+
NMath::sqrt( (a.abs**2).sum(*ranks)/n )
|
166
|
+
else
|
167
|
+
NMath::sqrt( (a**2).sum(*ranks)/n )
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def rmsdev(*ranks)
|
172
|
+
if integer?
|
173
|
+
a = self.to_type(NArray::DFLOAT)
|
174
|
+
else
|
175
|
+
a = self
|
176
|
+
end
|
177
|
+
a = NArray.ref(a)
|
178
|
+
n = rank_total(*ranks)
|
179
|
+
if complex?
|
180
|
+
NMath::sqrt( (( a-a.accum(*ranks).div!(n) ).abs**2).sum(*ranks)/n )
|
181
|
+
else
|
182
|
+
NMath::sqrt( (( a-a.accum(*ranks).div!(n) )**2).sum(*ranks)/n )
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def median(rank=nil)
|
187
|
+
shape = self.shape
|
188
|
+
rank = shape.size-1 if rank==nil
|
189
|
+
s = sort(rank).reshape!(true,*shape[rank+1..-1])
|
190
|
+
n = s.shape[0]
|
191
|
+
if n%2==1
|
192
|
+
s[n/2,false]
|
193
|
+
else
|
194
|
+
s[n/2-1..n/2,false].sum(0)/2
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
# Normal distributed random number; valid for floating point types
|
200
|
+
def randomn
|
201
|
+
size = self.size
|
202
|
+
case type = self.typecode
|
203
|
+
when COMPLEX; type=FLOAT
|
204
|
+
when SCOMPLEX; type=SFLOAT
|
205
|
+
when FLOAT
|
206
|
+
when SFLOAT
|
207
|
+
else
|
208
|
+
raise TypeError, "NArray type must be (S)FLOAT or (S)COMPLEX."
|
209
|
+
end
|
210
|
+
rr = NArray.new(type,size)
|
211
|
+
xx = NArray.new(type,size)
|
212
|
+
i = 0
|
213
|
+
while i < size
|
214
|
+
n = size-i
|
215
|
+
m = ((n+Math::sqrt(n))*1.27).to_i
|
216
|
+
x = NArray.new(type,m).random!(1) * 2 - 1
|
217
|
+
y = NArray.new(type,m).random!(1) * 2 - 1
|
218
|
+
r = x**2 + y**2
|
219
|
+
idx = (r<1).where
|
220
|
+
idx = idx[0...n] if idx.size > n
|
221
|
+
if idx.size>0
|
222
|
+
rr[i] = r[idx]
|
223
|
+
xx[i] = x[idx]
|
224
|
+
i += idx.size
|
225
|
+
end
|
226
|
+
end
|
227
|
+
# Box-Muller transform
|
228
|
+
rr = ( xx * NMath::sqrt( -2 * NMath::log(rr) / rr ) )
|
229
|
+
# finish
|
230
|
+
rr.reshape!(*self.shape) if self.rank > 1
|
231
|
+
rr = rr.to_type(self.typecode) if type!=self.typecode
|
232
|
+
if RUBY_VERSION < "1.8.0"
|
233
|
+
self.type.refer(rr)
|
234
|
+
else
|
235
|
+
self.class.refer(rr)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
#alias randomn! randomn
|
239
|
+
|
240
|
+
def randomn!
|
241
|
+
self[]= randomn
|
242
|
+
self
|
243
|
+
end
|
244
|
+
|
245
|
+
def reverse(*ranks)
|
246
|
+
if self.rank==0
|
247
|
+
return self.dup
|
248
|
+
elsif ranks.size==0
|
249
|
+
idx = (0...self.rank).map{-1..0}
|
250
|
+
else
|
251
|
+
idx = [true]*self.rank
|
252
|
+
ranks.each do |i|
|
253
|
+
if !i.kind_of?(Integer)
|
254
|
+
raise ArgumentError, "Argument must be Integer"
|
255
|
+
end
|
256
|
+
if i >= self.rank
|
257
|
+
raise ArgumentError, "dimension(%s) out of range"%[i]
|
258
|
+
end
|
259
|
+
idx[i] = -1..0
|
260
|
+
end
|
261
|
+
end
|
262
|
+
self[*idx]
|
263
|
+
end
|
264
|
+
|
265
|
+
def rot90(n_times=1)
|
266
|
+
if self.rank < 2
|
267
|
+
raise "must be >= 2 dimensional array"
|
268
|
+
end
|
269
|
+
case n_times%4
|
270
|
+
when 0
|
271
|
+
self.dup
|
272
|
+
when 1
|
273
|
+
self.transpose(1,0).reverse(0)
|
274
|
+
when 2
|
275
|
+
self.reverse(0,1)
|
276
|
+
when 3
|
277
|
+
self.transpose(1,0).reverse(1)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
#SFloatOne = NArray.sfloat(1).fill!(1)
|
282
|
+
|
283
|
+
module NMath
|
284
|
+
PI = Math::PI
|
285
|
+
E = Math::E
|
286
|
+
|
287
|
+
def recip x
|
288
|
+
1/x.to_f
|
289
|
+
end
|
290
|
+
|
291
|
+
# Trigonometric function
|
292
|
+
def csc x
|
293
|
+
1/sin(x)
|
294
|
+
end
|
295
|
+
def csch x
|
296
|
+
1/sinh(x)
|
297
|
+
end
|
298
|
+
def acsc x
|
299
|
+
asin(1/x.to_f)
|
300
|
+
end
|
301
|
+
def acsch x
|
302
|
+
asinh(1/x.to_f)
|
303
|
+
end
|
304
|
+
|
305
|
+
def sec x
|
306
|
+
1/cos(x)
|
307
|
+
end
|
308
|
+
def sech x
|
309
|
+
1/cosh(x)
|
310
|
+
end
|
311
|
+
def asec x
|
312
|
+
acos(1/x.to_f)
|
313
|
+
end
|
314
|
+
def asech x
|
315
|
+
acosh(1/x.to_f)
|
316
|
+
end
|
317
|
+
|
318
|
+
def cot x
|
319
|
+
1/tan(x)
|
320
|
+
end
|
321
|
+
def coth x
|
322
|
+
1/tanh(x)
|
323
|
+
end
|
324
|
+
def acot x
|
325
|
+
atan(1/x.to_f)
|
326
|
+
end
|
327
|
+
def acoth x
|
328
|
+
atanh(1/x.to_f)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Statistics
|
332
|
+
def covariance(x,y,*ranks)
|
333
|
+
x = NArray.to_na(x) unless x.kind_of?(NArray)
|
334
|
+
x = x.to_type(NArray::DFLOAT) if x.integer?
|
335
|
+
y = NArray.to_na(y) unless y.kind_of?(NArray)
|
336
|
+
y = y.to_type(NArray::DFLOAT) if y.integer?
|
337
|
+
n = x.rank_total(*ranks)
|
338
|
+
xm = x.accum(*ranks).div!(n)
|
339
|
+
ym = y.accum(*ranks).div!(n)
|
340
|
+
((x-xm)*(y-ym)).sum(*ranks) / (n-1)
|
341
|
+
end
|
342
|
+
|
343
|
+
module_function :recip
|
344
|
+
module_function :csc,:sec,:cot,:csch,:sech,:coth
|
345
|
+
module_function :acsc,:asec,:acot,:acsch,:asech,:acoth
|
346
|
+
module_function :covariance
|
347
|
+
end
|
348
|
+
|
349
|
+
end # class NArray
|
350
|
+
|
351
|
+
|
352
|
+
module FFTW
|
353
|
+
def convol(a1,a2)
|
354
|
+
n1x,n1y = a1.shape
|
355
|
+
n2x,n2y = a2.shape
|
356
|
+
raise "arrays must have same shape" if n1x!=n2x || n1y!=n2y
|
357
|
+
(FFTW.fftw( FFTW.fftw(a1,-1) * FFTW.fftw(a2,-1), 1).real) / (n1x*n1y)
|
358
|
+
end
|
359
|
+
module_function :convol
|
360
|
+
end
|
361
|
+
|
362
|
+
require 'nmatrix'
|