narray-bigmem 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +602 -0
- data/MANIFEST +54 -0
- data/README +41 -0
- data/README_NARRAY.en +49 -0
- data/README_NARRAY.ja +52 -0
- data/SPEC.en +327 -0
- data/SPEC.ja +307 -0
- data/ext/narray/depend +14 -0
- data/ext/narray/extconf.rb +123 -0
- data/ext/narray/mkmath.rb +792 -0
- data/ext/narray/mknafunc.rb +212 -0
- data/ext/narray/mkop.rb +734 -0
- data/ext/narray/na_array.c +659 -0
- data/ext/narray/na_func.c +1709 -0
- data/ext/narray/na_index.c +1021 -0
- data/ext/narray/na_linalg.c +635 -0
- data/ext/narray/na_random.c +444 -0
- data/ext/narray/narray.c +1341 -0
- data/ext/narray/narray.def +29 -0
- data/ext/narray/narray.h +231 -0
- data/ext/narray/narray_local.h +218 -0
- data/lib/narray.rb +4 -0
- data/lib/narray_ext.rb +362 -0
- data/lib/nmatrix.rb +248 -0
- metadata +94 -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/ext/narray/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
|
@@ -0,0 +1,123 @@
|
|
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
|
+
|
69
|
+
case RbConfig::CONFIG["CC"]
|
70
|
+
when "gcc"
|
71
|
+
omp_opt = "-fopenmp"
|
72
|
+
else
|
73
|
+
omp_opt = nil
|
74
|
+
end
|
75
|
+
omp_opt = arg_config("--openmp", omp_opt)
|
76
|
+
|
77
|
+
omp_opt = nil if omp_opt.to_s.empty?
|
78
|
+
|
79
|
+
if omp_opt
|
80
|
+
$CFLAGS << " " << omp_opt
|
81
|
+
$DLDFLAGS << " " << omp_opt
|
82
|
+
warn "OpenMP support: ON"
|
83
|
+
else
|
84
|
+
warn "OpenMP support: OFF"
|
85
|
+
warn "if you want to enable openmp, set --openmp=compile_option"
|
86
|
+
end
|
87
|
+
|
88
|
+
#$DEBUG = true
|
89
|
+
#$CFLAGS = ["-Wall",$CFLAGS].join(" ")
|
90
|
+
|
91
|
+
srcs = %w(
|
92
|
+
narray
|
93
|
+
na_array
|
94
|
+
na_func
|
95
|
+
na_index
|
96
|
+
na_random
|
97
|
+
na_op
|
98
|
+
na_math
|
99
|
+
na_linalg
|
100
|
+
)
|
101
|
+
|
102
|
+
header = "stdint.h"
|
103
|
+
unless have_header(header)
|
104
|
+
header = "sys/types.h"
|
105
|
+
unless have_header(header)
|
106
|
+
header = nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
have_type("u_int8_t", header)
|
111
|
+
have_type("uint8_t", header)
|
112
|
+
have_type("int16_t", header)
|
113
|
+
have_type("int32_t", header)
|
114
|
+
have_type("int64_t", header)
|
115
|
+
have_type("u_int32_t", header)
|
116
|
+
have_type("uint32_t", header)
|
117
|
+
have_type("u_int64_t", header)
|
118
|
+
have_type("uint64_t", header)
|
119
|
+
|
120
|
+
$objs = srcs.collect{|i| i+".o"}
|
121
|
+
|
122
|
+
create_conf_h("narray_config.h")
|
123
|
+
create_makefile("narray/narray")
|
@@ -0,0 +1,792 @@
|
|
1
|
+
require "mknafunc"
|
2
|
+
|
3
|
+
# File name
|
4
|
+
fname = "na_math.c"
|
5
|
+
$> = open(fname,"w")
|
6
|
+
|
7
|
+
print <<EOM
|
8
|
+
/*
|
9
|
+
#{fname}
|
10
|
+
Automatically generated code
|
11
|
+
Numerical Array Extention for Ruby
|
12
|
+
(C) Copyright 1999-2008 by Masahiro TANAKA
|
13
|
+
|
14
|
+
This program is free software.
|
15
|
+
You can distribute/modify this program
|
16
|
+
under the same terms as Ruby itself.
|
17
|
+
NO WARRANTY.
|
18
|
+
*/
|
19
|
+
#include <ruby.h>
|
20
|
+
#include "narray.h"
|
21
|
+
#include "narray_local.h"
|
22
|
+
|
23
|
+
#ifndef M_LOG2E
|
24
|
+
#define M_LOG2E 1.4426950408889634074
|
25
|
+
#endif
|
26
|
+
#ifndef M_LOG10E
|
27
|
+
#define M_LOG10E 0.43429448190325182765
|
28
|
+
#endif
|
29
|
+
|
30
|
+
VALUE rb_mNMath;
|
31
|
+
|
32
|
+
static void TpErr(void) {
|
33
|
+
rb_raise(rb_eTypeError,"illegal operation with this type");
|
34
|
+
}
|
35
|
+
|
36
|
+
#if 0
|
37
|
+
void sincos(double x, double *s, double *c)
|
38
|
+
{
|
39
|
+
*s=sin(x); *c=cos(x);
|
40
|
+
}
|
41
|
+
|
42
|
+
#ifndef HAVE_ACOSH
|
43
|
+
static double rb_log1p (const double x)
|
44
|
+
{
|
45
|
+
double y;
|
46
|
+
y = 1+x;
|
47
|
+
|
48
|
+
if (y==1)
|
49
|
+
return x;
|
50
|
+
else
|
51
|
+
return log(y)*(x/(y-1));
|
52
|
+
}
|
53
|
+
|
54
|
+
static double zero=0;
|
55
|
+
|
56
|
+
static double acosh(double x)
|
57
|
+
{
|
58
|
+
/* acosh(x) = log(x+sqrt(x*x-1)) */
|
59
|
+
if (x>2) {
|
60
|
+
return log(2*x-1/(sqrt(x*x-1)+x));
|
61
|
+
} else if (x>=1) {
|
62
|
+
x-=1;
|
63
|
+
return rb_log1p(x+sqrt(2*x+x*x));
|
64
|
+
}
|
65
|
+
return zero/(x-x); /* x<1: NaN */
|
66
|
+
}
|
67
|
+
|
68
|
+
static double asinh(double x)
|
69
|
+
{
|
70
|
+
double a, x2;
|
71
|
+
int neg;
|
72
|
+
|
73
|
+
/* asinh(x) = log(x+sqrt(x*x+1)) */
|
74
|
+
neg = x<0;
|
75
|
+
if (neg) {x=-x;}
|
76
|
+
x2 = x*x;
|
77
|
+
|
78
|
+
if (x>2) {
|
79
|
+
a = log(2*x+1/(x+sqrt(x2+1)));
|
80
|
+
} else {
|
81
|
+
a = rb_log1p(x+x2/(1+sqrt(x2+1)));
|
82
|
+
}
|
83
|
+
if (neg) {a=-a;}
|
84
|
+
return a;
|
85
|
+
}
|
86
|
+
|
87
|
+
static double atanh(double x)
|
88
|
+
{
|
89
|
+
double a, x2;
|
90
|
+
int neg;
|
91
|
+
|
92
|
+
/* atanh(x) = 0.5*log((1+x)/(1-x)) */
|
93
|
+
neg = x<0;
|
94
|
+
if (neg) {x=-x;}
|
95
|
+
x2 = x*2;
|
96
|
+
|
97
|
+
if (x<0.5) {
|
98
|
+
a = 0.5*rb_log1p(x2+x2*x/(1-x));
|
99
|
+
} else if (x<1) {
|
100
|
+
a = 0.5*rb_log1p(x2/(1-x));
|
101
|
+
} else if (x==1) {
|
102
|
+
a = 1/zero; /* Infinity */
|
103
|
+
} else {
|
104
|
+
return zero/(x-x); /* x>1: NaN */
|
105
|
+
}
|
106
|
+
if (neg) {a=-a;}
|
107
|
+
return a;
|
108
|
+
}
|
109
|
+
#endif
|
110
|
+
#endif
|
111
|
+
|
112
|
+
static void squareX(scomplex *x) {
|
113
|
+
float r=x->r;
|
114
|
+
x->r = r*r - x->i*x->i;
|
115
|
+
x->i = 2*r*x->i;
|
116
|
+
}
|
117
|
+
|
118
|
+
static void squareC(dcomplex *x) {
|
119
|
+
double r=x->r;
|
120
|
+
x->r = r*r - x->i*x->i;
|
121
|
+
x->i = 2*r*x->i;
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
static void mulX(scomplex *x, scomplex *y) {
|
126
|
+
scomplex z=*x;
|
127
|
+
x->r = z.r*y->r - z.i*y->i;
|
128
|
+
x->i = z.r*y->i + z.i*y->r;
|
129
|
+
}
|
130
|
+
|
131
|
+
static void mulC(dcomplex *x, dcomplex *y) {
|
132
|
+
dcomplex z=*x;
|
133
|
+
x->r = z.r*y->r - z.i*y->i;
|
134
|
+
x->i = z.r*y->i + z.i*y->r;
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
static void divX(scomplex *p1, scomplex *p2) {
|
139
|
+
scomplex x = *p1;
|
140
|
+
float a = p2->r*p2->r + p2->i*p2->i;
|
141
|
+
p1->r = (x.r*p2->r + x.i*p2->i)/a;
|
142
|
+
p1->i = (x.i*p2->r - x.r*p2->i)/a;
|
143
|
+
}
|
144
|
+
|
145
|
+
static void divC(dcomplex *p1, dcomplex *p2) {
|
146
|
+
dcomplex x = *p1;
|
147
|
+
double a = p2->r*p2->r + p2->i*p2->i;
|
148
|
+
p1->r = (x.r*p2->r + x.i*p2->i)/a;
|
149
|
+
p1->i = (x.i*p2->r - x.r*p2->i)/a;
|
150
|
+
}
|
151
|
+
|
152
|
+
|
153
|
+
static scomplex recipX(scomplex z)
|
154
|
+
{
|
155
|
+
scomplex r;
|
156
|
+
float n;
|
157
|
+
|
158
|
+
if ( (z.r<0 ? -z.r:z.r) > (z.i<0 ? -z.i:z.i) ) {
|
159
|
+
r.i = z.i/z.r;
|
160
|
+
n = (1+r.i*r.i)*z.r;
|
161
|
+
r.r = 1/n;
|
162
|
+
r.i /= -n;
|
163
|
+
} else {
|
164
|
+
r.r = z.r/z.i;
|
165
|
+
n = (1+r.r*r.r)*z.i;
|
166
|
+
r.r /= n;
|
167
|
+
r.i = -1/n;
|
168
|
+
}
|
169
|
+
return r;
|
170
|
+
}
|
171
|
+
|
172
|
+
static dcomplex recipC(dcomplex z)
|
173
|
+
{
|
174
|
+
dcomplex r;
|
175
|
+
double n;
|
176
|
+
|
177
|
+
if ( (z.r<0 ? -z.r:z.r) > (z.i<0 ? -z.i:z.i) ) {
|
178
|
+
r.i = z.i/z.r;
|
179
|
+
n = (1+r.i*r.i)*z.r;
|
180
|
+
r.r = 1/n;
|
181
|
+
r.i /= -n;
|
182
|
+
} else {
|
183
|
+
r.r = z.r/z.i;
|
184
|
+
n = (1+r.r*r.r)*z.i;
|
185
|
+
r.r /= n;
|
186
|
+
r.i = -1/n;
|
187
|
+
}
|
188
|
+
return r;
|
189
|
+
}
|
190
|
+
|
191
|
+
|
192
|
+
static int powInt(int x, int p)
|
193
|
+
{
|
194
|
+
int r=1;
|
195
|
+
|
196
|
+
switch(p) {
|
197
|
+
case 2: return x*x;
|
198
|
+
case 3: return x*x*x;
|
199
|
+
case 1: return x;
|
200
|
+
case 0: return 1;
|
201
|
+
}
|
202
|
+
if (p<0) return 0;
|
203
|
+
/* if(p>3) */
|
204
|
+
while (p) {
|
205
|
+
if ( (p%2) == 1 ) r *= x;
|
206
|
+
x *= x;
|
207
|
+
p /= 2;
|
208
|
+
}
|
209
|
+
return r;
|
210
|
+
}
|
211
|
+
|
212
|
+
|
213
|
+
static float powFi(float x, int p)
|
214
|
+
{
|
215
|
+
float r=1;
|
216
|
+
|
217
|
+
switch(p) {
|
218
|
+
case 2: return x*x;
|
219
|
+
case 3: return x*x*x;
|
220
|
+
case 1: return x;
|
221
|
+
case 0: return 1;
|
222
|
+
}
|
223
|
+
if (p<0) return 1/powFi(x,-p);
|
224
|
+
/* if(p>3) */
|
225
|
+
while (p) {
|
226
|
+
if ( (p%2) == 1 ) r *= x;
|
227
|
+
x *= x;
|
228
|
+
p /= 2;
|
229
|
+
}
|
230
|
+
return r;
|
231
|
+
}
|
232
|
+
|
233
|
+
|
234
|
+
static double powDi(double x, int p)
|
235
|
+
{
|
236
|
+
double r=1;
|
237
|
+
|
238
|
+
switch(p) {
|
239
|
+
case 2: return x*x;
|
240
|
+
case 3: return x*x*x;
|
241
|
+
case 1: return x;
|
242
|
+
case 0: return 1;
|
243
|
+
}
|
244
|
+
if (p<0) return 1/powDi(x,-p);
|
245
|
+
/* if(p>3) */
|
246
|
+
while (p) {
|
247
|
+
if ( (p%2) == 1 ) r *= x;
|
248
|
+
x *= x;
|
249
|
+
p /= 2;
|
250
|
+
}
|
251
|
+
return r;
|
252
|
+
}
|
253
|
+
|
254
|
+
|
255
|
+
static scomplex powXi(scomplex *x, int p)
|
256
|
+
{
|
257
|
+
scomplex y=*x, r={1,0};
|
258
|
+
|
259
|
+
if (p==2) { squareX(&y); return y; }
|
260
|
+
if (p==1) { return y; }
|
261
|
+
if (p==0) { return r; }
|
262
|
+
if (p<0) {
|
263
|
+
y = powXi(x,-p);
|
264
|
+
return recipX(y);
|
265
|
+
}
|
266
|
+
/* if (p>2) */
|
267
|
+
while (p) {
|
268
|
+
if ( (p%2) == 1 ) mulX(&r,&y);
|
269
|
+
squareX(&y);
|
270
|
+
p /= 2;
|
271
|
+
}
|
272
|
+
return r;
|
273
|
+
}
|
274
|
+
|
275
|
+
static dcomplex powCi(dcomplex *x, int p)
|
276
|
+
{
|
277
|
+
dcomplex y=*x, r={1,0};
|
278
|
+
|
279
|
+
if (p==2) { squareC(&y); return y; }
|
280
|
+
if (p==1) { return y; }
|
281
|
+
if (p==0) { return r; }
|
282
|
+
if (p<0) {
|
283
|
+
y = powCi(x,-p);
|
284
|
+
return recipC(y);
|
285
|
+
}
|
286
|
+
/* if (p>2) */
|
287
|
+
while (p) {
|
288
|
+
if ( (p%2) == 1 ) mulC(&r,&y);
|
289
|
+
squareC(&y);
|
290
|
+
p /= 2;
|
291
|
+
}
|
292
|
+
return r;
|
293
|
+
}
|
294
|
+
|
295
|
+
|
296
|
+
EOM
|
297
|
+
|
298
|
+
data = [
|
299
|
+
['sqrt',
|
300
|
+
[nil]*5 +
|
301
|
+
["{ *p1 = sqrt(*p2); }"]*2 +
|
302
|
+
["{
|
303
|
+
typer xr=p2->r/2, xi=p2->i/2, r=hypot(xr,xi);
|
304
|
+
if (xr>0) {
|
305
|
+
p1->r = sqrt(r+xr);
|
306
|
+
p1->i = xi/p1->r;
|
307
|
+
} else if ( (r-=xr) ) {
|
308
|
+
p1->i = (xi>=0) ? sqrt(r):-sqrt(r);
|
309
|
+
p1->r = xi/p1->i;
|
310
|
+
} else {
|
311
|
+
p1->r = p1->i = 0;
|
312
|
+
}
|
313
|
+
}"]*2 +
|
314
|
+
[nil] ],
|
315
|
+
|
316
|
+
['sin',
|
317
|
+
[nil]*5 +
|
318
|
+
["{ *p1 = sin(*p2); }"]*2 +
|
319
|
+
["{
|
320
|
+
p1->r = sin(p2->r)*cosh(p2->i);
|
321
|
+
p1->i = cos(p2->r)*sinh(p2->i); }"]*2 +
|
322
|
+
[nil] ],
|
323
|
+
|
324
|
+
['cos',
|
325
|
+
[nil]*5 +
|
326
|
+
["{ *p1 = cos(*p2); }"]*2 +
|
327
|
+
["{
|
328
|
+
p1->r = cos(p2->r)*cosh(p2->i);
|
329
|
+
p1->i = -sin(p2->r)*sinh(p2->i); }"]*2 +
|
330
|
+
[nil] ],
|
331
|
+
|
332
|
+
['tan',
|
333
|
+
[nil]*5 +
|
334
|
+
["{ *p1 = tan(*p2); }"]*2 +
|
335
|
+
["{
|
336
|
+
typer d, th;
|
337
|
+
p1->i = th = tanh(2*p2->i);
|
338
|
+
p1->r = sqrt(1-th*th); /* sech */
|
339
|
+
d = 1 + cos(2*p2->r) * p1->r;
|
340
|
+
p1->r *= sin(2*p2->r)/d;
|
341
|
+
p1->i /= d;
|
342
|
+
}"]*2 +
|
343
|
+
[nil] ],
|
344
|
+
|
345
|
+
['sinh',
|
346
|
+
[nil]*5 +
|
347
|
+
["{ *p1 = sinh(*p2); }"]*2 +
|
348
|
+
["{
|
349
|
+
p1->r = sinh(p2->r)*cos(p2->i);
|
350
|
+
p1->i = cosh(p2->r)*sin(p2->i);
|
351
|
+
}"]*2 +
|
352
|
+
[nil] ],
|
353
|
+
|
354
|
+
['cosh',
|
355
|
+
[nil]*5 +
|
356
|
+
["{ *p1 = cosh(*p2); }"]*2 +
|
357
|
+
["{
|
358
|
+
p1->r = cosh(p2->r)*cos(p2->i);
|
359
|
+
p1->i = sinh(p2->r)*sin(p2->i);
|
360
|
+
}"]*2 +
|
361
|
+
[nil] ],
|
362
|
+
|
363
|
+
['tanh',
|
364
|
+
[nil]*5 +
|
365
|
+
["{ *p1 = tanh(*p2); }"]*2 +
|
366
|
+
["{
|
367
|
+
typer d, th;
|
368
|
+
p1->r = th = tanh(2*p2->r);
|
369
|
+
p1->i = sqrt(1-th*th); /* sech */
|
370
|
+
d = 1 + cos(2*p2->i) * p1->i;
|
371
|
+
p1->r /= d;
|
372
|
+
p1->i *= sin(2*p2->i)/d;
|
373
|
+
}"]*2 +
|
374
|
+
[nil] ],
|
375
|
+
|
376
|
+
['exp',
|
377
|
+
[nil]*5 +
|
378
|
+
["{ *p1 = exp(*p2); }"]*2 +
|
379
|
+
["{
|
380
|
+
typer a = exp(p2->r);
|
381
|
+
p1->r = a*cos(p2->i);
|
382
|
+
p1->i = a*sin(p2->i);
|
383
|
+
}"]*2 +
|
384
|
+
[nil] ],
|
385
|
+
|
386
|
+
['log',
|
387
|
+
[nil]*5 +
|
388
|
+
["{ *p1 = log(*p2); }"]*2 +
|
389
|
+
["{
|
390
|
+
typed x = *p2;
|
391
|
+
p1->r = log(hypot(x.r, x.i));
|
392
|
+
p1->i = atan2(x.i, x.r);
|
393
|
+
}"]*2 +
|
394
|
+
[nil] ],
|
395
|
+
|
396
|
+
['log10',
|
397
|
+
[nil]*5 +
|
398
|
+
["{ *p1 = log10(*p2); }"]*2 +
|
399
|
+
["{
|
400
|
+
log#code(p1,p2);
|
401
|
+
p1->r *= (typer)M_LOG10E;
|
402
|
+
p1->i *= (typer)M_LOG10E;
|
403
|
+
}"]*2 +
|
404
|
+
[nil] ],
|
405
|
+
|
406
|
+
|
407
|
+
['log2',
|
408
|
+
[nil]*5 +
|
409
|
+
["{ *p1 = log(*p2)*M_LOG2E; }"]*2 +
|
410
|
+
["{
|
411
|
+
log#code(p1,p2);
|
412
|
+
p1->r *= (typer)M_LOG2E;
|
413
|
+
p1->i *= (typer)M_LOG2E;
|
414
|
+
}"]*2 +
|
415
|
+
[nil] ],
|
416
|
+
|
417
|
+
|
418
|
+
['asin',
|
419
|
+
[nil]*5 +
|
420
|
+
["{ *p1 = asin(*p2); }"]*2 +
|
421
|
+
# -i * log( sqrt(1-x**2) + x*i )
|
422
|
+
["{
|
423
|
+
typed x = *p2;
|
424
|
+
square#code(&x);
|
425
|
+
x.r = 1 - x.r;
|
426
|
+
x.i = - x.i;
|
427
|
+
sqrt#code(&x,&x);
|
428
|
+
x.r -= p2->i;
|
429
|
+
x.i += p2->r;
|
430
|
+
log#code(&x,&x);
|
431
|
+
p1->r = x.i;
|
432
|
+
p1->i = -x.r;
|
433
|
+
}"]*2 +
|
434
|
+
[nil]*1 ],
|
435
|
+
|
436
|
+
['asinh',
|
437
|
+
[nil]*5 +
|
438
|
+
["{ *p1 = asinh(*p2); }"]*2 +
|
439
|
+
# log(sqrt(x**2+1)+x)
|
440
|
+
["{
|
441
|
+
typed x = *p2;
|
442
|
+
square#code(&x);
|
443
|
+
x.r += 1;
|
444
|
+
sqrt#code(&x,&x);
|
445
|
+
x.r += p2->r;
|
446
|
+
x.i += p2->i;
|
447
|
+
log#code(p1,&x);
|
448
|
+
}"]*2 +
|
449
|
+
[nil]*1 ],
|
450
|
+
|
451
|
+
['acos',
|
452
|
+
[nil]*5 +
|
453
|
+
["{ *p1 = acos(*p2); }"]*2 +
|
454
|
+
# -i * log( sqrt(1-x**2)*i + x )
|
455
|
+
["{
|
456
|
+
typed x = *p2;
|
457
|
+
typer tmp;
|
458
|
+
square#code(&x);
|
459
|
+
x.r = 1 - x.r;
|
460
|
+
x.i = - x.i;
|
461
|
+
sqrt#code(&x,&x);
|
462
|
+
tmp = x.r + p2->i;
|
463
|
+
x.r = -x.i + p2->r;
|
464
|
+
x.i = tmp;
|
465
|
+
log#code(&x,&x);
|
466
|
+
p1->r = x.i;
|
467
|
+
p1->i = -x.r;
|
468
|
+
}"]*2 +
|
469
|
+
[nil]*1 ],
|
470
|
+
|
471
|
+
['acosh',
|
472
|
+
[nil]*5 +
|
473
|
+
["{ *p1 = acosh(*p2); }"]*2 +
|
474
|
+
# log(x+sqrt(x**2-1))
|
475
|
+
["{
|
476
|
+
typed x = *p2;
|
477
|
+
square#code(&x);
|
478
|
+
x.r -= 1;
|
479
|
+
sqrt#code(&x,&x);
|
480
|
+
x.r += p2->r;
|
481
|
+
x.i += p2->i;
|
482
|
+
log#code(p1,&x);
|
483
|
+
}"]*2 +
|
484
|
+
[nil]*1 ],
|
485
|
+
|
486
|
+
['atan',
|
487
|
+
[nil]*5 +
|
488
|
+
["{ *p1 = atan(*p2); }"]*2 +
|
489
|
+
# i/2 * log((i+x)/(i-x))
|
490
|
+
["{
|
491
|
+
typed x,y;
|
492
|
+
x.r=-p2->r; x.i=1-p2->i;
|
493
|
+
y.r= p2->r; y.i=1+p2->i;
|
494
|
+
div#code((void*)&y,(void*)&x);
|
495
|
+
log#code((void*)&x,(void*)&y);
|
496
|
+
p1->r = -x.i/2;
|
497
|
+
p1->i = x.r/2;
|
498
|
+
}"]*2 +
|
499
|
+
[nil]*1 ],
|
500
|
+
|
501
|
+
['atanh',
|
502
|
+
[nil]*5 +
|
503
|
+
["{ *p1 = atanh(*p2); }"]*2 +
|
504
|
+
# 1/2 * log((1+x)/(1-x))
|
505
|
+
["{
|
506
|
+
typed x,y;
|
507
|
+
x.r=1-p2->r; x.i=-p2->i;
|
508
|
+
y.r=1+p2->r; y.i= p2->i;
|
509
|
+
div#code((void*)&y,(void*)&x);
|
510
|
+
log#code((void*)&x,(void*)&y);
|
511
|
+
p1->r = x.r/2;
|
512
|
+
p1->i = x.i/2;
|
513
|
+
}"]*2 +
|
514
|
+
[nil]*1 ] ]
|
515
|
+
|
516
|
+
|
517
|
+
|
518
|
+
def mkmathfuncs(bsname,func)
|
519
|
+
|
520
|
+
print "
|
521
|
+
/* ------------------------- #{bsname} --------------------------- */\n"
|
522
|
+
c = $type_codes
|
523
|
+
tr = $real_types
|
524
|
+
td = $data_types
|
525
|
+
name = bsname
|
526
|
+
|
527
|
+
# Function Definition
|
528
|
+
head = "static void #{name}#code(void *p1, void *p2)"
|
529
|
+
for i in 0...c.size
|
530
|
+
if func[i] != nil && func[i]=~/^\{/
|
531
|
+
f = func[i].
|
532
|
+
gsub(/p1->/,"((#{td[i]}*)p1)->").
|
533
|
+
gsub(/p2->/,"((#{td[i]}*)p2)->").
|
534
|
+
gsub(/\*p1/,"*(#{td[i]}*)p1").
|
535
|
+
gsub(/\*p2/,"*(#{td[i]}*)p2").
|
536
|
+
gsub(/typer/, tr[i]).
|
537
|
+
gsub(/typed/, td[i])
|
538
|
+
puts( (head+f).gsub(/#code/,c[i]) )
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
# Function Array
|
543
|
+
|
544
|
+
print "\nna_mathfunc_t #{name}Funcs =\n{ "
|
545
|
+
m = []
|
546
|
+
for i in 0...c.size
|
547
|
+
if func[i] == nil
|
548
|
+
m += ['TpErr']
|
549
|
+
elsif func[i]=='copy'
|
550
|
+
m += ['Set'+c[i]*2]
|
551
|
+
elsif !( func[i] =~ /^\{/ )
|
552
|
+
m += [func[i]]
|
553
|
+
else
|
554
|
+
m += [name+c[i]]
|
555
|
+
end
|
556
|
+
end
|
557
|
+
print m.join(", ")+" };\n"
|
558
|
+
|
559
|
+
end
|
560
|
+
|
561
|
+
|
562
|
+
# Function Definitions
|
563
|
+
for i in data
|
564
|
+
mkmathfuncs( i[0], i[1] )
|
565
|
+
end
|
566
|
+
|
567
|
+
|
568
|
+
#
|
569
|
+
# Recip
|
570
|
+
#
|
571
|
+
$func_body =
|
572
|
+
"static void #name#C(int n, char *p1_0, int i1, char *p2_0, int i2)
|
573
|
+
{
|
574
|
+
type1* p1 = (type1*) p1_0;
|
575
|
+
typec* p2 = (typec*) p2_0;
|
576
|
+
int i;
|
577
|
+
|
578
|
+
#pragma omp parallel for
|
579
|
+
for (i=0; i<n; i++) {
|
580
|
+
OPERATION
|
581
|
+
}
|
582
|
+
}
|
583
|
+
"
|
584
|
+
mkfuncs('Rcp', $data_types, $data_types,
|
585
|
+
[nil] +
|
586
|
+
["p1[i] = 1/(p2[i]);"]*6 +
|
587
|
+
["p1[i] = recip#C(p2[i]);"]*2 +
|
588
|
+
["p1[i] = rb_funcall(INT2FIX(1),na_id_div,1,p2[i]);"]
|
589
|
+
)
|
590
|
+
|
591
|
+
|
592
|
+
#
|
593
|
+
# Power
|
594
|
+
#
|
595
|
+
def mkpowfuncs(name,funcs)
|
596
|
+
|
597
|
+
print "
|
598
|
+
/* ------------------------- #{name} --------------------------- */\n"
|
599
|
+
c = $type_codes
|
600
|
+
n = $type_codes.size
|
601
|
+
td = $data_types
|
602
|
+
tr = $real_types
|
603
|
+
|
604
|
+
# Function Definition
|
605
|
+
|
606
|
+
for i in 0...n
|
607
|
+
for j in 0...n
|
608
|
+
funcs.each do |k|
|
609
|
+
if c[i]=~k[0] && c[j]=~k[1]
|
610
|
+
tu = $data_types[$upcast[i][j]]
|
611
|
+
f = k[2].
|
612
|
+
gsub(/p1->/,"((#{tu}*)p1)->").
|
613
|
+
gsub(/p2->/,"((#{td[i]}*)p2)->").
|
614
|
+
gsub(/p3->/,"((#{td[j]}*)p3)->").
|
615
|
+
gsub(/\*p1/,"*(#{tu}*)p1").
|
616
|
+
gsub(/\*p2/,"*(#{td[i]}*)p2").
|
617
|
+
gsub(/\*p3/,"*(#{td[j]}*)p3").
|
618
|
+
gsub(/typed/,td[i]).
|
619
|
+
gsub(/typef/,tr[i])
|
620
|
+
puts $func_body.
|
621
|
+
gsub(/#t1/,tu).
|
622
|
+
gsub(/#t2/,td[i]).
|
623
|
+
gsub(/#t3/,td[j]).
|
624
|
+
gsub(/#name/,name).
|
625
|
+
sub(/OPERATION/,f).
|
626
|
+
gsub(/#CC/,c[i]+c[j]).
|
627
|
+
gsub(/#C/, c[i])
|
628
|
+
end
|
629
|
+
end
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
# function pointer array
|
634
|
+
print "\nna_setfunc_t "+name+"Funcs = {\n"
|
635
|
+
m = []
|
636
|
+
for i in 0...n
|
637
|
+
l = []
|
638
|
+
for j in 0...n
|
639
|
+
f = true
|
640
|
+
for k in funcs
|
641
|
+
if c[i]=~k[0] && c[j]=~k[1]
|
642
|
+
l += [name+c[i]+c[j]]
|
643
|
+
f = false
|
644
|
+
break
|
645
|
+
end
|
646
|
+
end
|
647
|
+
if f
|
648
|
+
l += ['TpErr']
|
649
|
+
end
|
650
|
+
end
|
651
|
+
m += [' { '+l.join(', ')+' }']
|
652
|
+
end
|
653
|
+
print m.join(",\n")+"\n};\n"
|
654
|
+
|
655
|
+
end
|
656
|
+
|
657
|
+
$func_body =
|
658
|
+
"static void #name#CC(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3)
|
659
|
+
{
|
660
|
+
for (; n; --n) {
|
661
|
+
OPERATION
|
662
|
+
p1+=i1; p2+=i2; p3+=i3;
|
663
|
+
}
|
664
|
+
}
|
665
|
+
"
|
666
|
+
mkpowfuncs('Pow',
|
667
|
+
[
|
668
|
+
[/[O]/,/[O]/, "*p1 = rb_funcall(*p2,na_id_power,1,*p3);"],
|
669
|
+
[/[BILG]/,/[BILG]/,"*p1 = powInt(*p2,*p3);"],
|
670
|
+
[/[FD]/,/[BILG]/, "*p1 = pow#Ci(*p2,*p3);"],
|
671
|
+
[/[BILGFD]/,/[FD]/,"*p1 = pow(*p2,*p3);"],
|
672
|
+
[/[XC]/,/[BILG]/, "*p1 = pow#Ci((typed*)p2,*p3);"],
|
673
|
+
[/[XC]/,/[FD]/,
|
674
|
+
"typed r;
|
675
|
+
if (*p3==0)
|
676
|
+
{ p1->r=1; p1->i=0; } else
|
677
|
+
if (p2->r==0 && p2->i==0 && *p3>0)
|
678
|
+
{ p1->r=0; p1->i=0; } else {
|
679
|
+
log#C(&r, p2);
|
680
|
+
r.r *= *p3;
|
681
|
+
r.i *= *p3;
|
682
|
+
exp#C(p1, &r); }"],
|
683
|
+
[/[XC]/,/[XC]/,
|
684
|
+
"typed l, r;
|
685
|
+
if (p3->r==0 && p3->i==0)
|
686
|
+
{ p1->r=1; p1->i=0; } else
|
687
|
+
if (p2->r==0 && p2->i==0 && p3->r>0 && p3->i==0)
|
688
|
+
{ p1->r=0; p1->i=0; } else {
|
689
|
+
log#C(&l, p2);
|
690
|
+
r.r = p3->r * l.r - p3->i * l.i;
|
691
|
+
r.i = p3->r * l.i + p3->i * l.r;
|
692
|
+
exp#C(p1, &r); }"]
|
693
|
+
])
|
694
|
+
|
695
|
+
|
696
|
+
# Execution
|
697
|
+
print <<EOM
|
698
|
+
|
699
|
+
|
700
|
+
/* ------------------------- Execution -------------------------- */
|
701
|
+
|
702
|
+
static void
|
703
|
+
na_exec_math(struct NARRAY *a1, struct NARRAY *a2, void (*func)())
|
704
|
+
{
|
705
|
+
na_shape_t i;
|
706
|
+
int s1, s2;
|
707
|
+
char *p1, *p2;
|
708
|
+
|
709
|
+
s1 = na_sizeof[a1->type];
|
710
|
+
s2 = na_sizeof[a2->type];
|
711
|
+
p1 = a1->ptr;
|
712
|
+
p2 = a2->ptr;
|
713
|
+
|
714
|
+
#pragma omp parallel for
|
715
|
+
for (i=0;i<a1->total; i++) {
|
716
|
+
(*func)( p1+s1*i, p2+s2*i );
|
717
|
+
}
|
718
|
+
}
|
719
|
+
|
720
|
+
|
721
|
+
static VALUE
|
722
|
+
na_math_func(volatile VALUE self, na_mathfunc_t funcs)
|
723
|
+
{
|
724
|
+
struct NARRAY *a1, *a2;
|
725
|
+
VALUE ans;
|
726
|
+
|
727
|
+
if (TYPE(self) == T_ARRAY) {
|
728
|
+
self = na_ary_to_nary(self,cNArray);
|
729
|
+
} else
|
730
|
+
if (!IsNArray(self)) {
|
731
|
+
self = na_make_scalar(self,na_object_type(self));
|
732
|
+
}
|
733
|
+
|
734
|
+
GetNArray(self,a2);
|
735
|
+
if (NA_IsINTEGER(a2)) {
|
736
|
+
self = na_upcast_type(self,NA_DFLOAT);
|
737
|
+
GetNArray(self,a2);
|
738
|
+
}
|
739
|
+
ans = na_make_object(a2->type, a2->rank, a2->shape, CLASS_OF(self));
|
740
|
+
GetNArray(ans,a1);
|
741
|
+
|
742
|
+
na_exec_math(a1, a2, funcs[a2->type]);
|
743
|
+
|
744
|
+
if (CLASS_OF(self) == cNArrayScalar)
|
745
|
+
SetFuncs[NA_ROBJ][a1->type](1,&ans,0,a1->ptr,0);
|
746
|
+
|
747
|
+
return ans;
|
748
|
+
}
|
749
|
+
EOM
|
750
|
+
|
751
|
+
|
752
|
+
# Module Methods
|
753
|
+
print <<EOM
|
754
|
+
|
755
|
+
/* ------------------------- Module Methods -------------------------- */
|
756
|
+
EOM
|
757
|
+
for i in data
|
758
|
+
bsname=i[0]
|
759
|
+
name=bsname
|
760
|
+
print <<EOM
|
761
|
+
|
762
|
+
/*
|
763
|
+
* call-seq:
|
764
|
+
* NMath.#{name}(arg) -> narray
|
765
|
+
*/
|
766
|
+
static VALUE na_math_#{bsname}(VALUE obj, VALUE x)
|
767
|
+
{ return na_math_func(x,#{name}Funcs); }
|
768
|
+
EOM
|
769
|
+
end
|
770
|
+
|
771
|
+
|
772
|
+
|
773
|
+
# Initializer
|
774
|
+
print <<EOM
|
775
|
+
|
776
|
+
|
777
|
+
/* Initialization of NMath module */
|
778
|
+
void Init_nmath(void)
|
779
|
+
{
|
780
|
+
/* define ExtMath module */
|
781
|
+
rb_mNMath = rb_define_module("NMath");
|
782
|
+
|
783
|
+
/* methods */
|
784
|
+
EOM
|
785
|
+
|
786
|
+
for i in data
|
787
|
+
print " rb_define_module_function(rb_mNMath,\"#{i[0]}\",na_math_#{i[0]},1);\n"
|
788
|
+
end
|
789
|
+
|
790
|
+
print <<EOM
|
791
|
+
}
|
792
|
+
EOM
|