narray-0.6.1.2/0000755000175000017500000000000012745364057013023 5ustar uwabamiuwabaminarray-0.6.1.2/SPEC.ja.txt0000644000175000017500000002536312745364057014720 0ustar uwabamiuwabami Ruby/NArray ver 0.6.0.7 (2013-02-01) by Masahiro TANAKA クラスメソッド: NArray.new(typecode, size, ...) 配列を生成する。要素は0で初期化。 NArray.byte(size,...) 1 byte unsigned integer NArray.sint(size,...) 2 byte signed integer NArray.int(size,...) 4 byte signed integer NArray.sfloat(size,...) single precision float NArray.float(size,...) double precision float NArray.scomplex(size,...) single precision complex NArray.complex(size,...) double precision complex NArray.object(size,...) Ruby object 以上要素は0またはnilで初期化。 NArray.to_na(array) NArrayに変換 NArray.to_na(string,type[,size,..]) NArray[...] NArray[1,5,10.0] #=> NArray.float(3):[1.0, 5.0, 10.0] NArray[1..10] #=> NArray.int(10):[1,2,3,4,5,6,7,8,9,10] クラス変数: CLASS_DIMENSION データとして扱われる次元。 NArrayは0。NVectorは1。NMatrixは2。 配列情報参照 self.dim 次元(インデックスの数)を返す。 self.rank 次元(インデックスの数)を返す。 self.shape 次元ごとのサイズを返す。 self.total 全要素数を返す。 インデックス参照 self[ dim0, dim1, ... ] -- インデックス引数に指定できるもの: 数値、範囲、配列、true, false -- インデックスの順序: FORTRAN 型 -- 添字引数が1つの場合、多次元配列はflattenされた1次元配列とみなされる。 例: a が 3x3 配列のとき、a[3] は a[0,1] の要素を指す。 a[ 1, 2, -1 ] 要素の取り出し。負数は最後から数える(-1が最後) 要素指定の次元は縮約される。 a[ 0..3, 4..1 ] 範囲取り出し。範囲の最後が最初より前ならば逆順になる。 a[ [1,4,2] ] インデックス配列。要素が[a[1],a[4],a[2]]のNArrayが返る。 a[] a.dup と同じ。 a[ 0, true ] a[0, 0..-1] と同じ。 a[ 0, false ] aが3次元のとき、a[0,true,true] と同じ。 省略された次元すべてにtrueを指定したのと同じ。 a[ mask ] マスキング. mask は長さが a と等しい byte 型 NArray. mask の各要素の値に応じて、a のそれぞ れは落される(0の場合)か、保持される(0以外の場合)。 例: a=NArray.float(2,2).indgen! p a[ a.lt 3 ] --> [ 0.0, 1.0, 2.0 ] (a.lt 3 は byte 型 NArray を返す) (同じことは a[ (a.lt 3).where ] でも出来る) -- self.slice(...) self[...] と同じだが、長さが1になった次元を落 さず(self[]は落す)、もとのランクを保つ。但し、 1次元インデックス付けとマスキングは例外([]と同 じ)。 インデックス代入。-- 取出しとほぼ同じルール。 a[ 1, 2, 3 ] = 1 a[ 0..3, 1..4, 2..5 ] = 2 a[ [1,3,2,4], true ] = 3 a[] = 4 a.fill!(4) と同じ。 a[0..2] = b[1..5] --> 要素数が異なるのでエラー。 a[1,2] = b[0..2,1..3] [1,2]を始点として代入。 a[0..2,0..3] = b[0..2,1] 繰り返し代入。 ( a[0,0]=b[0,1],..,a[0,3]=b[0,1] ) 行・列の削除 -- インデックス取り出しの逆 self.delete_at(...) 引数はインデクス参照と同じ。 参照: https://github.com/masa16/narray/issues/5 値のセット。 self.indgen!([start[,step]]) startからstepづつ増加した値をセット。 self.fill!(value) すべての要素にvalueをセット。 self.random!(max) 0<=x NArray.float(3,3) a = NArray.float(3,1).indgen b = NArray.float(1,3).fill(10) c = a*b # --> NArray.float(3,3) -- size=1の次元は拡張する。 算術演算子 -self self + other self - other self * other self / other self % other self ** other self.abs self.add! other self.sbt! other self.mul! other self.div! other self.mod! other self.mul_add(other,dim,...) (self * other).sum(dim,...)とほぼ同じ。 ただし途中で配列を作らない。 ビット演算子(整数のみ可能) ~self self & other self | other self ^ other 比較 -- 要素ごとに値を比較し、結果をBYTE型 NArrayを返す。 true/falseでないことに注意。 self.eq other ( == とは異なることに注意) self.ne other self.gt other self > other self.ge other self >= other self.lt other self < other self.le other self <= other self.and other 要素ごとの条件比較。 self.or other self.xor other self.not other self.all? 要素がすべて真ならば真。 self.any? 要素のどれかが真ならば真。 self.none? 要素のどれかが真ならば真。 self.where 要素が真のインデックス配列を返す。 self.where2 要素が真と偽のインデックス配列を含む(Ruby)配列を返す。 例: idx_t,idx_f = (a>12).where2 同値性 NArray[1] == NArray[1] #=> true NArray[1] == NArray[1.0] #=> true NArray[1].eql? NArray[1] #=> true NArray[1].eql? NArray[1.0] #=> false NArray[1].equal? NArray[1] #=> false a=b=NArray[1]; a.equal? b #=> true 統計 self.sum(dim,..) 指定した次元の和 self.cumsum 累積和(1次元配列のみ) self.prod(dim,..) 指定した次元の積 self.cumprod 累積積(1次元配列のみ) self.mean(dim,..) 指定した次元の平均。 self.stddev(dim,..) 指定した次元の標準偏差(標本標準偏差)。 self.rms(dim,..) 指定した次元のroot mean square。 self.rmsdev(dim,..) 指定した次元のroot mean square deviation。 self.min(dim,..) 指定した次元の最小。 self.max(dim,..) 指定した次元の最大。 (省略時は全ての次元。Range指定可。) self.median(dim) 0..dimの次元の中央値。省略時はすべての次元。 ソート self.sort(dim) 0..dimの次元でソート。省略時はすべての次元。 self.sort_index(dim) ソートしたインデックスを返す。 self[self.sort_index] は self.sort と同等。 転置 self.transpose( dim0, dim1, .. ) 配列の転置。selfの第(dim0)次元が新しい配列の第0次元になる。 負数は後からの順番。 transpose(-1,1..-2,0) で最初と最後を入れ換え。 インデックスの変更 (要素数は不変) self.reshape!(size,...) self.shape= size,... self.newdim!(dim,...) 指定位置にサイズ1の次元を挿入する。 データの参照 self.refer selfのデータを参照する別のオブジェクトを作成。 self.reshape(size,...) self.refer.reshape! と同様。 self.newdim(dim,...) self.refer.newdim! と同様。 反転・回転 self.reverse([dim,...]) 指定した次元を逆順にする self.rot90([k]) 2次元配列の90度の回転をk回行う 型変換 self.floor selfより小さい最大の整数を返す。 self.ceil selfより大きい最小の整数を返す。 self.round selfにもっとも近い整数を返す。 self.to_f 値を浮動小数点数に変換する。 self.to_i 値を整数に変換する。 self.to_a 値をRubyの配列に変換する。 self.to_s バイナリデータをそのままRubyの文字列データに変換する。 self.to_string 各要素を文字列に変換する。 イテレータ self.each {|i| ...} self.collect {|i| ...} self.collect! {|i| ...} バイトスワップ self.swap_byte バイトスワップ self.hton ネットワークバイトオーダーに変換 self.ntoh self.htov VAXバイトオーダーに変換 self.vtoh Boolean / マスク関係 self.count_false 値 == 0 の要素数 (byte型のみ) self.count_true 値 == 1 の要素数 (byte型のみ) self.mask( mask ) self[ mask ] と同じだかマスキング専用. [] と違い int, sint のマスクも使える. 複素数 self.real self.imag self.conj self.conj! self.angle atan2(self.imag, self.real) self.imag= other 虚数部分にotherをセット。 self.im 虚数倍。 NMath モジュール sqrt(x) exp(x) log(x) log10(x) log2(x) atan2(x,y) sin,cos,tan sinh,cosh,tanh asin,acos,atan asinh,acosh,atanh csc,sec,cot csch,sech,coth acsc,asec,acot acsch,asech,acoth covariance FFTW モジュール (fftw-2.1.3をshared libでコンパイルしたもので確認) (別モジュール) fftw(x,[1|-1]) convol(a,b) FFTWを用いた畳み込み。 NMatrix NArrayのサブクラス。最初の2次元をMatrixとして用いる。 残りの次元は多次元配列として扱われる。 次元の順序は、数学での表記とは逆: a_ij => a[j,i] メソッド: +,- 相手が NMatrix のときに演算可。 * 相手が NMatrix または NVector のときは Matrix積。 相手が Numeric または NArray のときは Scalar積。 例: NMatrix[[1,2],[3,4]] * [1,10] == NMatrix[ [[1,2],[3,4]], [[10,20],[30,40]] ] / 相手が Numeric または NArray のときはScalar除算。 相手が square NMatrix のときはLUにより線形方程式を解く。 a/b == b.lu.solve(a) transpose 引数を省略した場合は、最初のMatrix次元を交換。 diagonal(other) diagonal!(other) 対角要素に値をセット。引数省略時は1をセット。 I 対角要素に値に1をセット。 inverse 逆行列 lu LU分解を計算。NMatrixLU クラスのインスタンスを返す。 NVector NArrayのサブクラス。最初の1次元をVectorとして用いる。 残りの次元は多次元配列として扱われる。 メソッド: +,- 相手が NVector のときに演算可。 * 相手が NMatrix のときは Matrix積。 相手が NVector のときは 内積。 相手が Numeric または NArray のときは Scalar積。 / 相手が Numeric または NArray のときは Scalar除算。 相手が square NMatrix のときはLUにより線形方程式を解く。 v/m == m.lu.solve(v) NMatrixLU NMatrix#lu メソッドにより作られる。 LU (NMatrix) と pivot (NVector) を含む。 メソッド: solve(other) LU分解の結果を使って other を解く。 other は NMatrix または NVector のインスタンス。 narray-0.6.1.2/src/0000755000175000017500000000000012745364057013612 5ustar uwabamiuwabaminarray-0.6.1.2/src/extconf.rb0000644000175000017500000000423612745364057015612 0ustar uwabamiuwabamirequire "mkmf" def have_type(type, header=nil) printf "checking for %s... ", type STDOUT.flush src = <<"SRC" #include SRC unless header.nil? src << <<"SRC" #include <#{header}> SRC end r = try_link(src + <<"SRC") int main() { return 0; } int t() { #{type} a; return 0; } SRC unless r print "no\n" return false end $defs.push(format("-DHAVE_%s", type.upcase)) print "yes\n" return true end def create_conf_h(file) print "creating #{file}\n" hfile = open(file, "w") for line in $defs line =~ /^-D(.*)/ hfile.printf "#define %s 1\n", $1 end hfile.close end if RUBY_VERSION < '1.8' alias __install_rb :install_rb def install_rb(mfile, dest, srcdir = nil) __install_rb(mfile, dest, srcdir) archdir = dest.sub(/sitelibdir/,"sitearchdir").sub(/rubylibdir/,"archdir") path = ['$(srcdir)/narray.h','narray_config.h'] path << ['libnarray.a'] if /cygwin|mingw/ =~ RUBY_PLATFORM for f in path mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' %s %s\n", f, archdir end end else $INSTALLFILES = [['narray.h', '$(archdir)'], ['narray_config.h', '$(archdir)']] if /cygwin|mingw/ =~ RUBY_PLATFORM $INSTALLFILES << ['libnarray.a', '$(archdir)'] end end if /cygwin|mingw/ =~ RUBY_PLATFORM if RUBY_VERSION >= '1.9.0' $DLDFLAGS << " -Wl,--export-all,--out-implib=libnarray.a" elsif RUBY_VERSION > '1.8.0' $DLDFLAGS << ",--out-implib=libnarray.a" elsif RUBY_VERSION > '1.8' CONFIG["DLDFLAGS"] << ",--out-implib=libnarray.a" system("touch libnarray.a") else CONFIG["DLDFLAGS"] << " --output-lib libnarray.a" end end #$DEBUG = true #$CFLAGS = ["-Wall",$CFLAGS].join(" ") srcs = %w( narray na_array na_func na_index na_random na_op na_math na_linalg ) header = "stdint.h" unless have_header(header) header = "sys/types.h" unless have_header(header) header = nil end end have_type("u_int8_t", header) have_type("uint8_t", header) have_type("int16_t", header) have_type("int32_t", header) have_type("u_int32_t", header) have_type("uint32_t", header) $objs = srcs.collect{|i| i+".o"} create_conf_h("narray_config.h") create_makefile("narray") narray-0.6.1.2/src/narray.def0000644000175000017500000000060412745364057015566 0ustar uwabamiuwabamiEXPORTS Init_narray na_sizeof na_make_object na_make_scalar na_make_empty na_get_typecode na_clear_data na_clone na_fill na_copy_nary na_to_array na_ary_to_nary na_object_type na_cast_object na_cast_unless_narray na_cast_unless_array na_upcast_object na_dup_w_type na_change_type na_upcast_type na_to_narray na_aset na_aref na_slice na_count_true na_count_false na_aref_mask na_aset_mask narray-0.6.1.2/src/narray.h0000644000175000017500000001176012745364057015264 0ustar uwabamiuwabami/* narray.h Numerical Array Extention for Ruby (C) Copyright 1999-2011 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ #ifndef NARRAY_H #define NARRAY_H #include #include "narray_config.h" #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #define NARRAY_VERSION "0.6.1.2" #define NARRAY_VERSION_CODE 612 /* Data types used in NArray : Please modify these types if your system has any different type. */ /* NA_BYTE : unsigned 8-bit integer */ #ifndef HAVE_U_INT8_T # ifdef HAVE_UINT8_T typedef uint8_t u_int8_t; # else typedef unsigned char u_int8_t; # endif #endif #ifndef HAVE_INT16_T # if SIZEOF_SHORT == 2 typedef short int16_t; /* NA_SINT */ # else ---->> Please define int16_t manually because sizeof(short) != 2. <<---- # endif #endif /* HAVE_INT16_T */ #ifndef HAVE_INT32_T # if SIZEOF_LONG == 4 typedef long int32_t; /* NA_LINT */ # else # if SIZEOF_INT == 4 typedef int int32_t; /* NA_LINT */ # else ---->> Please define int32_t manually because sizeof(long) != 4. <<---- # endif # endif #endif /* HAVE_INT32_T */ /* unsigned 32-bit integer */ #ifndef HAVE_U_INT32_T # ifdef HAVE_UINT32_T typedef uint32_t u_int32_t; # else # if SIZEOF_LONG == 4 typedef unsigned long u_int32_t; # else # if SIZEOF_INT == 4 typedef unsigned int u_int32_t; # else ---->> Please define u_int32_t manually because sizeof(long) != 4. <<---- # endif # endif # endif #endif /* HAVE_U_INT32_T */ typedef struct { float r,i; } scomplex; typedef struct { double r,i; } dcomplex; enum NArray_Types { NA_NONE, NA_BYTE, /* 1 */ NA_SINT, /* 2 */ NA_LINT, /* 3 */ NA_SFLOAT, /* 4 */ NA_DFLOAT, /* 5 */ NA_SCOMPLEX, /* 6 */ NA_DCOMPLEX, /* 7 */ NA_ROBJ, /* 8 */ NA_NTYPES /* 9 */ }; /* struct for Numerical Array */ struct NARRAY { int rank; /* # of dimension */ int total; /* # of total element */ int type; /* data type */ int *shape; char *ptr; /* pointer to data */ VALUE ref; /* NArray object wrapping this structure */ }; #ifndef NARRAY_C extern VALUE cNArray; extern const int na_sizeof[NA_NTYPES+1]; #endif #define GetNArray(obj,var) Data_Get_Struct(obj, struct NARRAY, var) #define IsNArray(obj) (rb_obj_is_kind_of(obj,cNArray)==Qtrue) #define NA_PTR(a,p) ((a)->ptr+(p)*na_sizeof[(a)->type]) #define NA_STRUCT(val) ((struct NARRAY*)DATA_PTR(val)) #define NA_PTR_TYPE(val,type) (type)(((struct NARRAY*)DATA_PTR(val))->ptr) #define NA_RANK(val) (((struct NARRAY*)DATA_PTR(val))->rank) #define NA_TYPE(val) (((struct NARRAY*)DATA_PTR(val))->type) #define NA_TOTAL(val) (((struct NARRAY*)DATA_PTR(val))->total) #define NA_SHAPE0(val) (((struct NARRAY*)DATA_PTR(val))->shape[0]) #define NA_SHAPE1(val) (((struct NARRAY*)DATA_PTR(val))->shape[1]) #define NA_IsNArray(obj) \ (rb_obj_is_kind_of(obj,cNArray)==Qtrue) #define NA_IsArray(obj) \ (TYPE(obj)==T_ARRAY || rb_obj_is_kind_of(obj,cNArray)==Qtrue) #define NA_IsROBJ(d) ((d)->type==NA_ROBJ) #define NA_IsINTEGER(a) \ ((a)->type==NA_BYTE || (a)->type==NA_SINT || (a)->type==NA_LINT ) #define NA_IsCOMPLEX(a) \ ((a)->type==NA_SCOMPLEX || (a)->type==NA_DCOMPLEX) #define NA_MAX(a,b) (((a)>(b))?(a):(b)) #define NA_SWAP(a,b,tmp) {(tmp)=(a);(a)=(b);(b)=(tmp);} #define na_class_dim(klass) NUM2INT(rb_const_get(klass, na_id_class_dim)) #define NUM2REAL(v) NUM2DBL( rb_funcall((v),na_id_real,0) ) #define NUM2IMAG(v) NUM2DBL( rb_funcall((v),na_id_imag,0) ) #define NA_ALLOC_SLICE(slc,nc,shp,np) \ { slc = (struct slice*)xmalloc( sizeof(struct slice)*(nc) + \ sizeof(int)*(np) );\ shp = (int*)&( (slc)[nc] ); } /* Function Prototypes */ /* narray.c */ VALUE na_make_object(int type, int rank, int *shape, VALUE klass); VALUE na_make_scalar(VALUE obj, int type); VALUE na_make_empty(int type, VALUE klass); int na_get_typecode(VALUE v); void na_clear_data(struct NARRAY *ary); VALUE na_clone(VALUE self); VALUE na_fill(VALUE self, volatile VALUE obj); void na_copy_nary(struct NARRAY *dst, struct NARRAY *src); /* na_array.c */ VALUE na_to_array(VALUE obj); VALUE na_make_inspect(VALUE self); VALUE na_ary_to_nary(VALUE ary, VALUE klass); int na_object_type(VALUE v); VALUE na_cast_object(VALUE obj, int type); VALUE na_cast_unless_narray(VALUE obj, int type); VALUE na_cast_unless_array(VALUE obj, int type); VALUE na_upcast_object(VALUE obj, int type); VALUE na_dup_w_type(VALUE obj, int type); VALUE na_change_type(VALUE obj, int type); VALUE na_upcast_type(VALUE obj, int type); VALUE na_to_narray(VALUE obj); /* na_index.c */ VALUE na_aset(int argc, VALUE *argv, VALUE self); VALUE na_aref(int argc, VALUE *argv, VALUE self); VALUE na_slice(int argc, VALUE *argv, VALUE self); VALUE na_count_true(VALUE self); VALUE na_count_false(VALUE self); VALUE na_aref_mask(VALUE self, VALUE mask); void na_aset_mask(VALUE self, VALUE mask, VALUE v); #endif /* ifndef NARRAY_H */ narray-0.6.1.2/src/lib/0000755000175000017500000000000012745364057014360 5ustar uwabamiuwabaminarray-0.6.1.2/src/lib/narray/0000755000175000017500000000000012745364057015654 5ustar uwabamiuwabaminarray-0.6.1.2/src/lib/narray/nmatrix.rb0000644000175000017500000001264612745364057017674 0ustar uwabamiuwabami# Numerical Array Extention for Ruby # (C) Copyright 2000-2003 by Masahiro TANAKA # # # ------ NMatrix ------ # class NMatrix < NArray CLASS_DIMENSION = 2 def +(other) case other when NMatrix return super(NArray.refer(other)) when NArray unless other.instance_of?(NArray) return other.coerce_rev( self, :+ ) end end raise TypeError,"Illegal operation: NMatrix + %s" % other.class end def -(other) case other when NMatrix return super(NArray.refer(other)) when NArray unless other.instance_of?(NArray) return other.coerce_rev( self, :- ) end end raise TypeError,"Illegal operation: NMatrix - %s" % other.class end def *(other) case other when NMatrix NMatrix.mul_add( NArray.refer(self).newdim!(0),other.newdim(2), 1 ) #NMatrix.mul_add( NArray.refer(self).newdim!(0), # other.transpose(1,0).newdim!(2), 0 ) when NVector NVector.mul_add( NArray.refer(self), other.newdim(1), 0 ) when NArray if other.instance_of?(NArray) NMatrix.mul( NArray.refer(self), other.newdim(0,0) ) else other.coerce_rev( self, :* ) end when Numeric super #NMatrix.mul( NArray.refer(self), other ) when Array NMatrix.mul( self, NArray[*other].newdim!(0,0) ) else raise TypeError,"Illegal operation: NMatrix * %s" % other.class end end def /(other) case other when NMatrix other.lu.solve(self) when NVector raise TypeError,"Illegal operation: NMatrix / %s" % other.class when NArray if other.instance_of?(NArray) NMatrix.div( NArray.refer(self), other.newdim(0,0) ) else other.coerce_rev( self, :/ ) end when Numeric NMatrix.div( NArray.refer(self), other ) when Array NMatrix.div( self, NArray[*other].newdim!(0,0) ) else raise TypeError,"Illegal operation: NMatrix / %s" % other.class end end def **(n) case n when Integer if n==0 return 1.0 elsif n<0 m = self.inverse n = -n else m = self end (2..n).each{ m *= self } m else raise TypeError,"Illegal operation: NMatrix ** %s" % n.class end end def coerce_rev(other,id) case id when :* if other.instance_of?(NArray) return NMatrix.mul( other.newdim(0,0), self ) end if other.instance_of?(NArrayScalar) return NMatrix.mul( other.newdim(0), self ) end when :/ if other.instance_of?(NArray) return NMatrix.mul( other.newdim(0,0), self.inverse ) end if other.instance_of?(NArrayScalar) return NMatrix.mul( other.newdim(0), self.inverse ) end end raise TypeError,"Illegal operation: %s %s NMatrix" % [other.class, id.id2name] end def inverse self.lu.solve( NMatrix.new(self.typecode, *self.shape).fill!(0).unit ) end def transpose(*arg) if arg.size==0 super(1,0) else super end end def diagonal!(val=1) shp = self.shape idx = NArray.int(shp[0..1].min).indgen! * (shp[0]+1) ref = reshape(shp[0]*shp[1],true) if val.kind_of?(Numeric) ref[idx,true] = val else val = NArray.to_na(val) raise ArgumentError, "must be 1-d array" if val.dim!=1 ref[idx,true] = val.newdim!(-1) end self end def diagonal(val) self.dup.diagonal!(val) end def unit diagonal! end alias identity unit alias I unit end # class NMatrix # # ------ NVector ------ # class NVector < NArray CLASS_DIMENSION = 1 def +(other) case other when NVector return super(NArray.refer(other)) when NArray unless other.instance_of?(NArray) return other.coerce_rev( self, :+ ) end end raise TypeError,"Illegal operation: NVector + %s" % other.class end def -(other) case other when NVector return super(NArray.refer(other)) when NArray unless other.instance_of?(NArray) return other.coerce_rev( self, :- ) end end raise TypeError,"Illegal operation: NVector - %s" % other.class end def *(other) case other when NMatrix NVector.mul_add( NArray.refer(self).newdim!(0), other, 1 ) when NVector NArray.mul_add( NArray.refer(self), other, 0 ) # inner product when NArray if other.instance_of?(NArray) NVector.mul( NArray.refer(self), other.newdim(0) ) else other.coerce_rev( self, :* ) end when Numeric NVector.mul( NArray.refer(self), other ) else raise TypeError,"Illegal operation: NVector * %s" % other.class end end def /(other) case other when NMatrix other.lu.solve(self) when NVector raise TypeError,"Illegal operation: NVector / %s" % other.class when NArray if other.instance_of?(NArray) NVector.div( NArray.refer(self), other.newdim(0) ) else other.coerce_rev( self, :/ ) end when Numeric NVector.div( NArray.refer(self), other ) else raise TypeError,"Illegal operation: NVector / %s" % other.class end end def **(n) if n==2 self*self else raise ArgumentError,"Only v**2 is implemented" end end def coerce_rev(other,id) case id when :* if other.instance_of?(NArray) return NVector.mul( other.newdim(0), self ) end if other.instance_of?(NArrayScalar) return NVector.mul( other, self ) end end raise TypeError,"Illegal operation: %s %s NVector" % [other.class, id.id2name] end end # class NVector narray-0.6.1.2/src/lib/narray/narray_ext.rb0000644000175000017500000001622112745364057020357 0ustar uwabamiuwabami# Numerical Array Extention for Ruby # (C) Copyright 2000-2008 by Masahiro TANAKA # # This program is free software. # You can distribute/modify this program # under the same terms as Ruby itself. # NO WARRANTY. # class NArray def self.cast(array,type=nil) case array when NArray when Array array = NArray.to_na(array) else raise ArgumentError, "1st argument must be NArray or Array" end type = array.typecode if type.nil? shape = array.shape na = self.new(type,*shape) na[] = array na end def integer? self.typecode==NArray::BYTE || self.typecode==NArray::SINT || self.typecode==NArray::LINT end def complex? self.typecode==NArray::DCOMPLEX || self.typecode==NArray::SCOMPLEX end def all? where.size == size end def any? where.size > 0 end def none? where.size == 0 end def ==(other) other.kind_of?(NArray) && shape == other.shape && eq(other).all? end def eql?(other) self.class == other.class && typecode == other.typecode && shape == other.shape && case typecode when NArray::OBJECT to_a.eql? other.to_a else to_s.eql? other.to_s end end def hash case typecode when NArray::OBJECT [self.class, to_a].hash else [self.class, typecode, shape, to_s].hash end end def rank_total(*ranks) if ranks.size>0 idx = [] ranks.each{|i| idx.push(*i)} # ranks is expected to be, e.g., [1, 3..5, 7] a = self.shape n = 1 idx.each{|i| n *= a[i]} n else self.total end end # delete rows/columns def delete_at(*args) if args.size > self.rank raise ArgumentError, "too many arguments" end shp = self.shape ind = [] self.rank.times do |i| n = shp[i] case a=args[i] when Integer a = n+a if a<0 raise IndexError, "index(%d) out of range"%[a] if a<0 x = [0...a,a+1...n] when Range b = a.first b = n+b if b<0 raise IndexError, "index(%s) out of range"%[a] if b<0 e = a.last e = n+e if e<0 e -= 1 if a.exclude_end? raise IndexError, "index(%s) out of range"%[a] if e<0 x = [0...b,e+1...n] when Array x = (0...n).to_a x -= a.map do |j| raise IndexError, "contains non-integer" unless Integer===j (j<0) ? n+j : j end else if a raise ArgumentError, "invalid argument" else x = true end end ind << x end self[*ind] end # Statistics def mean(*ranks) if integer? a = self.to_type(NArray::DFLOAT) else a = self end a = NArray.ref(a) a.sum(*ranks) / (rank_total(*ranks)) end def stddev(*ranks) if integer? a = self.to_type(NArray::DFLOAT) else a = self end a = NArray.ref(a) n = rank_total(*ranks) if complex? NMath::sqrt( (( a-a.accum(*ranks).div!(n) ).abs**2).sum(*ranks)/(n-1) ) else NMath::sqrt( (( a-a.accum(*ranks).div!(n) )**2).sum(*ranks)/(n-1) ) end end def rms(*ranks) if integer? a = self.to_type(NArray::DFLOAT) else a = self end a = NArray.ref(a) n = rank_total(*ranks) if complex? NMath::sqrt( (a.abs**2).sum(*ranks)/n ) else NMath::sqrt( (a**2).sum(*ranks)/n ) end end def rmsdev(*ranks) if integer? a = self.to_type(NArray::DFLOAT) else a = self end a = NArray.ref(a) n = rank_total(*ranks) if complex? NMath::sqrt( (( a-a.accum(*ranks).div!(n) ).abs**2).sum(*ranks)/n ) else NMath::sqrt( (( a-a.accum(*ranks).div!(n) )**2).sum(*ranks)/n ) end end def median(rank=nil) shape = self.shape rank = shape.size-1 if rank==nil s = sort(rank).reshape!(true,*shape[rank+1..-1]) n = s.shape[0] if n%2==1 s[n/2,false] else s[n/2-1..n/2,false].sum(0)/2 end end # Normal distributed random number; valid for floating point types def randomn size = self.size case type = self.typecode when COMPLEX; type=FLOAT when SCOMPLEX; type=SFLOAT when FLOAT when SFLOAT else raise TypeError, "NArray type must be (S)FLOAT or (S)COMPLEX." end rr = NArray.new(type,size) xx = NArray.new(type,size) i = 0 while i < size n = size-i m = ((n+Math::sqrt(n))*1.27).to_i x = NArray.new(type,m).random!(1) * 2 - 1 y = NArray.new(type,m).random!(1) * 2 - 1 r = x**2 + y**2 idx = (r<1).where idx = idx[0...n] if idx.size > n if idx.size>0 rr[i] = r[idx] xx[i] = x[idx] i += idx.size end end # Box-Muller transform rr = ( xx * NMath::sqrt( -2 * NMath::log(rr) / rr ) ) # finish rr.reshape!(*self.shape) if self.rank > 1 rr = rr.to_type(self.typecode) if type!=self.typecode if RUBY_VERSION < "1.8.0" self.type.refer(rr) else self.class.refer(rr) end end #alias randomn! randomn def randomn! self[]= randomn self end def reverse(*ranks) if self.rank==0 return self.dup elsif ranks.size==0 idx = (0...self.rank).map{-1..0} else idx = [true]*self.rank ranks.each do |i| if !i.kind_of?(Integer) raise ArgumentError, "Argument must be Integer" end if i >= self.rank raise ArgumentError, "dimension(%s) out of range"%[i] end idx[i] = -1..0 end end self[*idx] end def rot90(n_times=1) if self.rank < 2 raise "must be >= 2 dimensional array" end case n_times%4 when 0 self.dup when 1 self.transpose(1,0).reverse(0) when 2 self.reverse(0,1) when 3 self.transpose(1,0).reverse(1) end end #SFloatOne = NArray.sfloat(1).fill!(1) end module NMath PI = Math::PI E = Math::E def recip x 1/x.to_f end # Trigonometric function def csc x 1/sin(x) end def csch x 1/sinh(x) end def acsc x asin(1/x.to_f) end def acsch x asinh(1/x.to_f) end def sec x 1/cos(x) end def sech x 1/cosh(x) end def asec x acos(1/x.to_f) end def asech x acosh(1/x.to_f) end def cot x 1/tan(x) end def coth x 1/tanh(x) end def acot x atan(1/x.to_f) end def acoth x atanh(1/x.to_f) end # Statistics def covariance(x,y,*ranks) x = NArray.to_na(x) unless x.kind_of?(NArray) x = x.to_type(NArray::DFLOAT) if x.integer? y = NArray.to_na(y) unless y.kind_of?(NArray) y = y.to_type(NArray::DFLOAT) if y.integer? n = x.rank_total(*ranks) xm = x.accum(*ranks).div!(n) ym = y.accum(*ranks).div!(n) ((x-xm)*(y-ym)).sum(*ranks) / (n-1) end module_function :recip module_function :csc,:sec,:cot,:csch,:sech,:coth module_function :acsc,:asec,:acot,:acsch,:asech,:acoth module_function :covariance end module FFTW def convol(a1,a2) n1x,n1y = a1.shape n2x,n2y = a2.shape raise "arrays must have same shape" if n1x!=n2x || n1y!=n2y (FFTW.fftw( FFTW.fftw(a1,-1) * FFTW.fftw(a2,-1), 1).real) / (n1x*n1y) end module_function :convol end require 'narray/nmatrix' narray-0.6.1.2/src/na_linalg.c0000644000175000017500000003345212745364057015711 0ustar uwabamiuwabami/* * na_linalg.c * Numerical Array Extention for Ruby * (C) Copyright 2000-2008 by Masahiro TANAKA */ #include #include "narray.h" #include "narray_local.h" #define ARRAY_BUF /* a_ij == a[j,i] j - > i 11 21 31 | 12 22 32 v 13 23 33 */ #define SWAPMEM(a,b,tmp,sz) \ { memcpy(tmp,a,sz); memcpy(a,b,sz); memcpy(b,tmp,sz); } typedef struct NARRAY_FUNCSET { int elmsz; char *zero; char *one; char *tiny; void (*set)(); void (*neg)(); void (*rcp)(); void (*abs)(); void (*add)(); void (*sbt)(); void (*mul)(); void (*div)(); void (*mod)(); void (*muladd)(); void (*mulsbt)(); void (*cmp)(); int (*sort)(); void (*min)(); void (*max)(); } na_funcset_t; VALUE cNMatrix, cNVector, cNMatrixLU; static na_funcset_t na_funcset[NA_NTYPES]; static ID id_lu, id_pivot; static void na_loop_linalg( int nd, char *p1, char *p2, char *p3, struct slice *s1, struct slice *s2, struct slice *s3, void (*func)(), int *shape, int type ) { int i; int ps1 = s1[0].pstep; int ps2 = s2[0].pstep; int ps3 = s3[0].pstep; int *si; if (nd==0) { (*func)(1, p1, 0, p2, 0, p3, 0, shape, type); return; } si = ALLOCA_N(int,nd); i = nd; s1[i].p = p1; s2[i].p = p2; s3[i].p = p3; for(;;) { /* set pointers */ while (i > 0) { --i; s3[i].p = s3[i].pbeg + s3[i+1].p; s2[i].p = s2[i].pbeg + s2[i+1].p; s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = s1[i].n; } /* rank 0 loop */ (*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2, s3[0].p, ps3, shape, type); /* rank up */ do { if ( ++i >= nd ) return; } while ( --si[i] == 0 ); /* next point */ s1[i].p += s1[i].pstep; s2[i].p += s2[i].pstep; s3[i].p += s3[i].pstep; } } static int na_shape_total( int n, int *shape ) { int total=1; for (; n>0; --n) total *= *(shape++); return total; } static void na_exec_linalg( struct NARRAY *a1, struct NARRAY *a2, struct NARRAY *a3, int ncd1, int ncd2, int ncd3, void (*func)() ) { int ndim, ncd, nsz1, nsz2, nsz3; int *itr, *shp1, *shp2, *shp3; struct slice *s1, *s2, *s3; ncd = na_max3(ncd1,ncd2,ncd3); /* class dim */ ndim = na_max3(a1->rank-ncd1, a2->rank-ncd2, a3->rank-ncd3) + ncd; NA_ALLOC_SLICE(s1,(ndim+1)*3,shp1,ndim*4); shp2 = &shp1[ndim]; shp3 = &shp2[ndim]; itr = &shp3[ndim]; s2 = &s1[ndim+1]; s3 = &s2[ndim+1]; na_shape_copy( ndim, shp1, a1 ); na_shape_copy( ndim, shp2, a2 ); na_shape_copy( ndim, shp3, a3 ); ndim -= ncd; shp1 += ncd1; shp2 += ncd2; shp3 += ncd3; na_shape_max3( ndim, itr, shp1, shp2, shp3 ); ndim = na_set_slice_3obj( ndim, s1, s2, s3, shp1, shp2, shp3, itr ); nsz1 = na_shape_total(a1->rank-ncd1,a1->shape+ncd1); nsz2 = na_shape_total(a2->rank-ncd2,a2->shape+ncd2); nsz3 = na_shape_total(a3->rank-ncd3,a3->shape+ncd3); na_init_slice(s1, ndim, shp1, na_sizeof[a1->type]*nsz1 ); na_init_slice(s2, ndim, shp2, na_sizeof[a2->type]*nsz2 ); na_init_slice(s3, ndim, shp3, na_sizeof[a3->type]*nsz3 ); na_loop_linalg( ndim, a1->ptr, a2->ptr, a3->ptr, s1, s2, s3, func, a2->shape, a2->type ); xfree(s1); } static int na_lu_fact_func_body(int ni, char *a, char *idx, int *shape, int type, char *buf) { int i, j, k; int imax; char *amax, *rtmp; char *aa, *aii, *aij, *ai0, *a0i, *a0j; char *v, *vi; na_funcset_t *f = &na_funcset[type]; na_funcset_t *r = &na_funcset[na_cast_real[type]]; int status = 0; int n = shape[0]; int relmsz = r->elmsz; int felmsz = f->elmsz; int rowsz = felmsz*n; int matsz = rowsz*n; int diagsz = rowsz + felmsz; v = buf + rowsz; amax = v + relmsz*n; while (ni-->0) { aa = a; vi = v; /* v[j] = 1/max( abs( a[i,j] ) ) */ for (j=0;jabs(n, buf, relmsz, aa, felmsz); r->set(1, amax,0, r->zero,0); rtmp = buf; for (i=0;isort(rtmp, amax) == 1) r->set(1, amax,0, rtmp,0); rtmp += relmsz; } if (r->sort(amax,r->tiny) != 1) status = 2; /* Singular Matrix */ r->rcp(1, vi,0, amax,0); vi += relmsz; } ai0 = a0i = aii = a; vi = v; for (i=0;iset(n, buf, felmsz, ai0, rowsz); aij = buf; a0j = a; /* a[i,j(mulsbt(j, aij, 0, buf, felmsz, a0j, felmsz); } /* a[i,j(>=i)] -= sum(kmulsbt(i, aij, 0, buf, felmsz, a0j, felmsz); } f->set(n, ai0, rowsz, buf, felmsz); /* pivoting imax = max_idx( abs( a[i,j(>=i)] ) * v[j(>=i)] ) */ f->abs(n-i, buf, relmsz, aii, rowsz); r->mul(n-i, buf, relmsz, vi, relmsz); r->set(1, amax,0, r->zero,0); rtmp = buf; imax = 0; for (j=i;jsort(rtmp,amax) == 1) { r->set(1, amax,0, rtmp,0); imax = j; } rtmp += relmsz; } if (r->sort(amax,r->tiny)!=1) status = 1; /* Singular Matrix */ if (i != imax) { /* a[*,i] <=> a[*,imax] */ SWAPMEM(a+i*rowsz, a+imax*rowsz, buf, rowsz); /* v[i] <=> v[imax] */ SWAPMEM(vi, v+imax*relmsz, buf, relmsz); NA_SWAP(((int32_t*)idx)[i],((int32_t*)idx)[imax],k); } /* a[i,j(>i)] = a[i,j]/a[i,i] */ f->div(n-i-1, aii+rowsz, rowsz, aii, 0); ai0 += felmsz; a0i += rowsz; aii += diagsz; vi += relmsz; } a += matsz; idx += sizeof(int32_t)*n; } return status; } static int na_lu_fact_func(int ni, char *a, char *idx, int *shape, int type) { volatile VALUE val; char *buf; int status, size, n=shape[0]; if (type==NA_ROBJ) { VALUE *mem; int i; size = n*2+1; mem = ALLOC_N(VALUE, size); for (i=0; irank<2) rb_raise(rb_eTypeError,"dim(=%i) < 2", ary->rank); n = ary->shape[0]; if (n != ary->shape[1]) rb_raise(rb_eTypeError,"not square matrix"); total=1; for (i=2; irank; ++i) total *= ary->shape[i]; piv = na_make_object(NA_LINT, ary->rank-1, ary->shape+1, cNVector); /* prepare pivot index */ func = IndGenFuncs[NA_LINT]; sz = na_sizeof[NA_LINT]; ptr = idx = ((struct NARRAY *)DATA_PTR(piv))->ptr; for (i=0; iptr, idx, ary->shape, ary->type); if (stat!=0) rb_raise(rb_eZeroDivError,"singular matrix, status=%i",stat); return rb_funcall(cNMatrixLU,na_id_new,2,self,piv); } /* :nodoc: */ static VALUE na_lu_fact(VALUE self) { return na_lu_fact_bang( na_clone(self) ); } static void na_lu_pivot_func( int ni, char *x, int ps1, char *y, int ps2, char *idx, int ps3, int *shape, int type ) { int i, n, sz; char *xi; na_funcset_t *f = &na_funcset[type]; n = shape[1]; sz = f->elmsz * shape[0]; for (; ni>0; --ni) { xi = x; for (i=0; i0; --ni) { xx = x; for (k=shape[0]; k>0; --k) { /* once if x is vector */ f->set(n, buf,sz, xx,xsz); xi = buf; a0i = a; /* solve Lx' = y' */ for (i=1; imulsbt(i, xi, 0, a0i, sz, buf, sz); } xi = buf + sz*(n-1); aii = a + (matsz-sz); /* solve Ux = x' */ f->div(1, xi,0, aii,0); for (i=n-1; i>0; --i) { xi -= sz; aii -= diagsz; /* x[i] -= a[j(>i),i] * x[j(>i)] */ f->mulsbt(n-i, xi,0, aii+sz, sz, xi+sz, sz); /* x[i] /= a[i,i] */ f->div(1, xi,0, aii,0); } f->set(n, xx,xsz, buf,sz); xx += sz; } x += ps1; a += ps2; } } static void na_lu_solve_func( int ni, char *z, int ps, char *x, int ps1, char *a, int ps2, int *shape, int type ) { volatile VALUE val; char *buf; int size; if (type==NA_ROBJ) { VALUE *mem; int i; size = shape[1]; mem = ALLOC_N(VALUE, size); for (i=0; i result * * Solve with the result of LU factorization. * arg should be NMatrix or NVector instance. * Returns an instance of same class with arg. */ static VALUE na_lu_solve(VALUE self, volatile VALUE other) { int n, ndim; int *shape; struct NARRAY *a1, *a2, *l, *p; VALUE pv, obj, klass; volatile VALUE lu; klass = CLASS_OF(other); if (klass==cNVector) other = na_newdim_ref(1,(VALUE*)na_funcset[NA_ROBJ].zero,other); else if (klass!=cNMatrix) rb_raise(rb_eTypeError,"neither NMatrix or NVector"); lu = rb_ivar_get(self, id_lu); pv = rb_ivar_get(self, id_pivot); GetNArray(lu,l); other = na_upcast_object(other,l->type); GetNArray(other,a1); lu = na_upcast_type(lu,a1->type); GetNArray(lu,l); GetNArray(pv,p); n = l->shape[0]; if (n != a1->shape[1]) rb_raise(rb_eTypeError,"size mismatch (%i!=%i)",n,a1->shape[1]); ndim = NA_MAX(l->rank, a1->rank); shape = ALLOCA_N(int, ndim); shape[0] = a1->shape[0]; na_shape_max2( ndim-1, shape+1, a1->rank-1, a1->shape+1, l->rank-1, l->shape+1 ); obj = na_make_object( a1->type, ndim, shape, klass ); GetNArray(obj,a2); na_exec_linalg( a2, a1, p, 2, 2, 1, na_lu_pivot_func ); na_exec_linalg( a2, a2, l, 2, 2, 2, na_lu_solve_func ); if (klass==cNVector) { shape = ALLOC_N(int, ndim-1); memcpy(shape,a2->shape+1,sizeof(int)*(ndim-1)); xfree(a2->shape); a2->shape = shape; --(a2->rank); } return obj; } /* :nodoc: */ static VALUE na_lu_init(VALUE self, VALUE lu, VALUE piv) { int i; struct NARRAY *l, *p; if (CLASS_OF(lu)!=cNMatrix) rb_raise(rb_eTypeError,"LU should be NMatrix"); if (CLASS_OF(piv)!=cNVector) rb_raise(rb_eTypeError,"pivot should be NVector"); GetNArray(lu,l); GetNArray(piv,p); if (p->type != NA_LINT) rb_raise(rb_eRuntimeError,"pivot type must be Integer"); if (l->rank != p->rank+1) rb_raise(rb_eRuntimeError,"array dimension mismatch %i!=%i+1", l->rank, p->rank); if (l->shape[0] != l->shape[1]) rb_raise(rb_eRuntimeError,"LU matrix (%i,%i) is not square", l->shape[0], l->shape[1]); for (i=1; irank; ++i) if (l->shape[i] != p->shape[i-1]) rb_raise(rb_eRuntimeError,"array size mismatch %i!=%i at %i", l->shape[i], p->shape[i-1], i); rb_ivar_set(self, id_lu, lu); rb_ivar_set(self, id_pivot, piv); return Qnil; } void Init_na_linalg() { static double tiny_d = 1e-15; static float tiny_f = (float)1e-7; int i, sz; int32_t one=1, zero=0; static VALUE zerov = INT2FIX(0); static VALUE onev = INT2FIX(1); char *a = malloc(NA_NTYPES*sizeof(dcomplex)*2); for (i=1;i((int)sizeof(int))) ? sz : (int)sizeof(int); SetFuncs[i][NA_LINT](1, a,0, &one, 0); na_funcset[i].one = a; a += sz; SetFuncs[i][NA_LINT](1, a,0, &zero,0); na_funcset[i].zero = a; na_funcset[i].tiny = a; a += sz; na_funcset[i].set = SetFuncs[i][i]; na_funcset[i].neg = NegFuncs[i]; na_funcset[i].rcp = RcpFuncs[i]; na_funcset[i].abs = AbsFuncs[i]; na_funcset[i].add = AddUFuncs[i]; na_funcset[i].sbt = SbtUFuncs[i]; na_funcset[i].mul = MulUFuncs[i]; na_funcset[i].div = DivUFuncs[i]; na_funcset[i].mod = ModUFuncs[i]; na_funcset[i].muladd = MulAddFuncs[i]; na_funcset[i].mulsbt = MulSbtFuncs[i]; na_funcset[i].cmp = CmpFuncs[i]; na_funcset[i].min = MinFuncs[i]; na_funcset[i].max = MaxFuncs[i]; na_funcset[i].sort = SortFuncs[i]; } na_funcset[NA_SFLOAT].tiny = (char*)&tiny_f; na_funcset[NA_DFLOAT].tiny = (char*)&tiny_d; na_funcset[NA_ROBJ].zero = (char*)&zerov; na_funcset[NA_ROBJ].one = (char*)&onev; cNVector = rb_define_class("NVector",cNArray); cNMatrix = rb_define_class("NMatrix",cNArray); cNMatrixLU = rb_define_class("NMatrixLU",rb_cObject); rb_define_method(cNMatrix, "lu_fact!", na_lu_fact_bang, 0); rb_define_alias(cNMatrix, "lu!","lu_fact!"); rb_define_method(cNMatrix, "lu_fact", na_lu_fact, 0); rb_define_alias(cNMatrix, "lu","lu_fact"); rb_define_method(cNMatrixLU, "initialize", na_lu_init, 2); rb_define_method(cNMatrixLU, "solve", na_lu_solve, 1); id_lu = rb_intern("@lu"); id_pivot = rb_intern("@pivot"); } narray-0.6.1.2/src/narray.c0000644000175000017500000007411712745364057015264 0ustar uwabamiuwabami/* narray.c Numerical Array Extention for Ruby (C) Copyright 1999-2008 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ #define NARRAY_C #include #include "narray.h" #include "narray_local.h" /* global variables within this module */ VALUE cNArray, cNArrayScalar, cComplex; ID na_id_beg, na_id_end, na_id_exclude_end; ID na_id_minus, na_id_abs, na_id_power; ID na_id_compare, na_id_ne, na_id_and, na_id_or; ID na_id_class_dim; ID na_id_add, na_id_sbt, na_id_mul, na_id_div, na_id_mod; ID na_id_real, na_id_imag; ID na_id_coerce_rev; ID na_id_new; ID na_id_Complex; static ID na_id_to_i, na_id_usec, na_id_now; const int na_sizeof[NA_NTYPES+1] = { 0, sizeof(u_int8_t), sizeof(int16_t), sizeof(int32_t), sizeof(float), sizeof(double), sizeof(scomplex), sizeof(dcomplex), sizeof(VALUE), 0 }; const char *na_typestring[] = { "none", "byte", /* 1 */ "sint", /* 2 */ "int", /* 3 */ "sfloat", /* 4 */ "float", /* 5 */ "scomplex", /* 6 */ "complex", /* 7 */ "object", /* 8 */ "ntypes" /* 9 */ }; #ifdef NARRAY_GC static int mem_count = 0; static int na_gc_freq = 2500000; /* Frequency of Garbage Collection */ #endif void Init_na_array(void); void Init_na_index(void); void Init_nmath(void); void Init_na_funcs(void); void Init_na_linalg(void); void Init_na_random(void); #ifdef DEBUG void na_xfree(void *ptr) { if (!ptr) abort(); free(ptr); } #endif /* mark items */ static void na_mark_obj(struct NARRAY *ary) { int i; VALUE *ptr; ptr = (VALUE*) ary->ptr; for (i=ary->total; i>0; --i) rb_gc_mark(*ptr++); } static void na_mark_ref(struct NARRAY *ary) { struct NARRAY *a2; rb_gc_mark( ary->ref ); GetNArray(ary->ref,a2); if (a2->type == NA_ROBJ) na_mark_obj(a2); } static void na_free(struct NARRAY* ary) { if ( ary->total > 0 ) { if (ary->ref == Qnil || ary->ref == Qtrue) { /* non reference */ xfree(ary->ptr); } xfree(ary->shape); #ifdef DEBUG ary->shape = NULL; ary->ptr = NULL; #endif } xfree(ary); } /* allocation of NARRAY */ struct NARRAY* na_alloc_struct(int type, int rank, int *shape) { int total=1, total_bak; int i, memsz; struct NARRAY *ary; for (i=0; i 2147483647 || total/shape[i] != total_bak) { rb_raise(rb_eArgError, "array size is too large"); } } if (rank<=0 || total<=0) { /* empty array */ ary = ALLOC(struct NARRAY); ary->rank = ary->total = 0; ary->shape = NULL; ary->ptr = NULL; ary->type = type; } else { memsz = na_sizeof[type] * total; if (memsz < 1 || memsz > 2147483647 || memsz/na_sizeof[type] != total) { rb_raise(rb_eArgError, "allocation size is too large"); } /* Garbage Collection */ #ifdef NARRAY_GC mem_count += memsz; if ( mem_count > na_gc_freq ) { rb_gc(); mem_count=0; } #endif ary = ALLOC(struct NARRAY); ary->shape = ALLOC_N(int, rank); ary->ptr = ALLOC_N(char, memsz); ary->rank = rank; ary->total = total; ary->type = type; for (i=0; ishape[i] = shape[i]; } ary->ref = Qtrue; return ary; } #if !defined RCLASS_SUPER #define RCLASS_SUPER(v) (RCLASS(v)->super) #endif static void na_check_class_narray(VALUE v) { if (TYPE(v) != T_CLASS) { rb_raise(rb_eRuntimeError, "class required"); } if (v == cNArray) return; if (RTEST(rb_funcall(v, rb_intern("<="), 1, cNArray))) return; rb_raise(rb_eRuntimeError, "need NArray or its subclass"); } static VALUE na_wrap_struct_class(struct NARRAY *ary, VALUE klass) { VALUE v; int class_dim; /* Extract element */ if (ary->rank==0 && ary->total==1) { SetFuncs[NA_ROBJ][ary->type](1,&v,0,ary->ptr,0); na_free(ary); return v; } /* check NArray >= klass */ na_check_class_narray(klass); /* Check dimension */ class_dim = NUM2INT(rb_const_get(klass, na_id_class_dim)); if (ary->rank < class_dim) rb_raise(rb_eTypeError, "array.dim(=%i) < CLASS_DIMENSION(=%i)", ary->rank, class_dim); if (ary->ref == Qnil) rb_raise(rb_eRuntimeError, "already wrapped object"); /* Turn on WRAPPED flag */ if (ary->ref == Qtrue) { ary->ref = Qnil; if (NA_IsROBJ(ary)) return Data_Wrap_Struct(klass, na_mark_obj, na_free, ary); else return Data_Wrap_Struct(klass, 0, na_free, ary); } /* reference to another NArray*/ return Data_Wrap_Struct(klass, na_mark_ref, na_free, ary); } static VALUE na_wrap_struct(struct NARRAY *ary, VALUE obj) { return na_wrap_struct_class(ary,CLASS_OF(obj)); } VALUE na_make_object(int type, int rank, int *shape, VALUE klass) { struct NARRAY *na; na = na_alloc_struct(type, rank, shape); if (type==NA_ROBJ) { rb_mem_clear((VALUE*)(na->ptr), na->total); } return na_wrap_struct_class(na, klass); } /* restriction: Integer, Float, Complex === obj */ VALUE na_make_scalar(VALUE obj, int type) { static int shape=1; VALUE v; struct NARRAY *ary; v = na_make_object(type,1,&shape,cNArrayScalar); GetNArray(v,ary); SetFuncs[ary->type][NA_ROBJ](1, ary->ptr,0, &obj,0); return v; } VALUE na_make_empty(int type, VALUE klass) { struct NARRAY *na; na = na_alloc_struct(type, 0, NULL); return na_wrap_struct_class(na, klass); } /* allocate reference to NArray */ struct NARRAY* na_ref_alloc_struct(VALUE obj) { int i; struct NARRAY *orig, *ary; GetNArray(obj,orig); if (orig->rank<=0) rb_raise(rb_eRuntimeError, "cannot create NArrayRefer of Empty NArray"); ary = ALLOC(struct NARRAY); ary->shape = ALLOC_N(int, orig->rank); ary->ptr = orig->ptr; ary->rank = orig->rank; ary->total = orig->total; ary->type = orig->type; for (i=0; irank; ++i) ary->shape[i] = orig->shape[i]; ary->ref = obj; return ary; } /* method: self.refer */ static VALUE na_refer(VALUE self) { return na_wrap_struct(na_ref_alloc_struct(self), self); } /* singleton method: NArray.refer( other ) */ static VALUE na_s_refer(VALUE klass, VALUE self) { return na_wrap_struct_class(na_ref_alloc_struct(self), klass); } /* method: self.original */ static VALUE na_original(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); return ary->ref; } void na_clear_data(struct NARRAY *ary) { if (NA_IsROBJ(ary)) rb_mem_clear((VALUE*)(ary->ptr), ary->total); else MEMZERO(ary->ptr, char, na_sizeof[ary->type]*ary->total); } /* local function for new array creation */ static VALUE na_new2(int argc, VALUE *argv, int type, VALUE klass) { int i, *shape; struct NARRAY *ary; VALUE v; if (argc == 0) rb_raise(rb_eArgError, "Argument required"); shape = ALLOCA_N(int,argc); for (i=0; itype != NA_ROBJ) na_clear_data(ary); /* rb_obj_call_init(v, 0, 0); */ return v; } /* Convert type arguments -> typecode */ int na_get_typecode(VALUE v) { struct NARRAY *na; int i; if (v==rb_cFloat) return NA_DFLOAT; if (v==rb_cInteger) return NA_LINT; if (v==cComplex) return NA_DCOMPLEX; if (v==rb_cObject) return NA_ROBJ; if (FIXNUM_P(v)) { i = NUM2INT(v); if (i<=NA_NONE || i>=NA_NTYPES) rb_raise(rb_eArgError, "Wrong type code"); return i; } if (NA_IsNArray(v)) { GetNArray(v,na); return na->type; } if (TYPE(v)==T_STRING) { for (i=1; itype,org->rank,org->shape); memcpy(cpy->ptr, org->ptr, na_sizeof[org->type] * org->total); return na_wrap_struct(cpy,self); } /* local function */ void na_copy_nary(struct NARRAY *dst, struct NARRAY *src) { if (dst->total != src->total) rb_raise(rb_eRuntimeError, "src and dst array sizes mismatch"); if (dst->type == src->type) memcpy(dst->ptr, src->ptr, src->total*na_sizeof[src->type]); else { SetFuncs[dst->type][src->type]( src->total, dst->ptr, na_sizeof[dst->type], src->ptr, na_sizeof[src->type] ); } } /* method: to_type(type) */ static VALUE na_to_type(VALUE self, VALUE vtype) { struct NARRAY *a1, *a2; VALUE v; GetNArray(self,a1); v = na_make_object(na_get_typecode(vtype), a1->rank, a1->shape, CLASS_OF(self)); GetNArray(v,a2); na_copy_nary(a2,a1); return v; } /* method: to_f() */ static VALUE na_to_float(VALUE self) { struct NARRAY *a1, *a2; VALUE v; GetNArray(self,a1); v = na_make_object(na_upcast[NA_SFLOAT][a1->type], a1->rank, a1->shape, CLASS_OF(self)); GetNArray(v,a2); na_copy_nary(a2,a1); return v; } /* method: to_i() */ static VALUE na_to_integer(VALUE self) { int type; struct NARRAY *a1, *a2; VALUE v; GetNArray(self,a1); if (!NA_IsINTEGER(a1)) type = NA_LINT; else type = a1->type; v = na_make_object(type, a1->rank, a1->shape, CLASS_OF(self)); GetNArray(v,a2); na_copy_nary(a2,a1); return v; } /* method: shape() -- returns an array of shape of each rank */ static VALUE na_shape(VALUE self) { struct NARRAY *ary; VALUE *shape; int i; GetNArray(self,ary); shape = ALLOCA_N(VALUE,ary->rank); for (i = 0; i < ary->rank; ++i) shape[i] = INT2FIX(ary->shape[i]); return rb_ary_new4(ary->rank,shape); } /* method: rank() -- returns the rank of the array */ static VALUE na_rank(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); return INT2FIX(ary->rank); } /* method: size() -- returns the total number of elements */ static VALUE na_size(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); return INT2FIX(ary->total); } /* method: typecode -- returns the type of the array */ static VALUE na_typecode(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); return INT2FIX(ary->type); } /* method: element_size -- returns the element size of the array type */ static VALUE na_element_size(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); return INT2FIX(na_sizeof[ary->type]); } /* method: empty? -- returns true if empty array */ static VALUE na_is_empty(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); if (ary->total==0) return Qtrue; return Qfalse; } /* Binary copy of String => NArray */ static VALUE na_str_to_na(int argc, VALUE *argv, VALUE str) { struct NARRAY *ary; VALUE v; int i, type, len=1, str_len, *shape, rank=argc-1; if (argc < 1) rb_raise(rb_eArgError, "Type and Size Arguments required"); type = na_get_typecode(argv[0]); str_len = RSTRING_LEN(str); if (argc == 1) { rank = 1; shape = ALLOCA_N(int,rank); if ( str_len % na_sizeof[type] != 0 ) rb_raise(rb_eArgError, "string size mismatch"); shape[0] = str_len / na_sizeof[type]; } else { shape = ALLOCA_N(int,rank); for (i=0; iptr, RSTRING_PTR(str), ary->total*na_sizeof[type] ); return v; } /* method: to_s -- convert the data contents to a binary string */ static VALUE na_to_s(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); if (NA_IsROBJ(ary)) rb_raise(rb_eTypeError,"cannot convert object-type NArray"); return rb_str_new(ary->ptr,ary->total*na_sizeof[ary->type]); } /* method: to_binary -- convert the data contents to a BYTE type NArray */ static VALUE na_to_binary(VALUE self) { struct NARRAY *a1, *a2; int i, *shape, rank; VALUE v; GetNArray(self,a1); rank = a1->rank+1; shape = ALLOCA_N(int,rank); shape[0] = na_sizeof[a1->type]; for (i=1; ishape[i-1]; v = na_make_object( NA_BYTE, rank, shape, cNArray ); GetNArray(v,a2); MEMCPY(a2->ptr,a1->ptr,char,a2->total); return v; } /* method: to_type_as_binary(type) */ static VALUE na_to_type_as_binary(VALUE self, VALUE vtype) { struct NARRAY *a1, *a2; int size, total, type; VALUE v; type = na_get_typecode(vtype); GetNArray(self,a1); size = a1->total * na_sizeof[a1->type]; if ( size % na_sizeof[type] != 0 ) rb_raise(rb_eRuntimeError, "bina1 size mismatch"); total = size / na_sizeof[type]; v = na_make_object( type, 1, &total, cNArray ); GetNArray(v,a2); MEMCPY(a2->ptr,a1->ptr,char,size); return v; } static void na_to_string_binary(int n, char *p1, int i1, char *p2, int i2) { for (; n>0; --n) { *(VALUE*)p1 = rb_str_new(p2,i2); p1+=i1; p2+=i2; } } /* method: to_string */ static VALUE na_to_string(VALUE self) { VALUE v; struct NARRAY *a1, *a2; GetNArray(self,a1); if (a1->total==0) v = na_make_empty(NA_ROBJ, CLASS_OF(self)); else if (a1->type==NA_BYTE) { if (a1->rank==1) return rb_str_new(a1->ptr,a1->shape[0]); v = na_make_object(NA_ROBJ, a1->rank-1, a1->shape+1, cNArray); GetNArray(v,a2); na_to_string_binary( a2->total, a2->ptr, sizeof(VALUE), a1->ptr, a1->shape[0] ); } else { v = na_make_object(NA_ROBJ, a1->rank, a1->shape, CLASS_OF(self)); GetNArray(v,a2); ToStrFuncs[a1->type]( a2->total, a2->ptr, sizeof(VALUE), a1->ptr, na_sizeof[a1->type] ); } return v; } /* singleton method: NArray.to_na( string, type, size1,size2,...,sizeN ) NArray.to_na( array ) */ static VALUE na_s_to_na(int argc, VALUE *argv, VALUE klass) { if (argc < 1) { rb_raise(rb_eArgError, "Argument is required"); } if (TYPE(argv[0]) == T_STRING) { return na_str_to_na(argc-1,argv+1,argv[0]); } if (argc > 1) { rb_raise(rb_eArgError, "Only one array argument must be provided"); } if (TYPE(argv[0]) == T_ARRAY) { return na_ary_to_nary( argv[0], klass ); } if (NA_IsNArray(argv[0])) { return argv[0]; } rb_raise(rb_eTypeError, "Argument must be Array or String (or NArray)"); return Qnil; } /* singleton method: NArray[object] */ static VALUE na_s_bracket(int argc, VALUE *argv, VALUE klass) { VALUE v = rb_ary_new4(argc, argv); return na_ary_to_nary( v, klass ); } /* method: coerce(other) */ static VALUE na_coerce(VALUE self, VALUE other) { struct NARRAY *a1; GetNArray(self,a1); return rb_assoc_new( na_cast_object(other,a1->type), self ); } /* method: inspect() -- returns the inspect of the array */ static VALUE na_inspect(VALUE self) { VALUE str; struct NARRAY *ary; int i; char buf[256]; const char *classname; const char *ref = "%s(ref).%s(%i"; const char *org = "%s.%s(%i"; GetNArray(self,ary); classname = rb_class2name(CLASS_OF(self)); str = rb_str_new(0,0); if (ary->rank < 1) { sprintf(buf, "%s.%s(): []", classname, na_typestring[ary->type]); rb_str_cat(str,buf,strlen(buf)); } else { sprintf(buf, (ary->ref==Qnil) ? org:ref, classname, na_typestring[ary->type], ary->shape[0]); rb_str_cat(str,buf,strlen(buf)); for (i=1; irank; ++i) { sprintf(buf,",%i",ary->shape[i]); rb_str_cat(str,buf,strlen(buf)); } rb_str_cat(str,")",1); rb_str_cat(str,": \n",3); rb_str_concat(str, na_make_inspect(self)); } return str; } /* private function for reshape */ static void na_reshape(int argc, VALUE *argv, struct NARRAY *ary, VALUE self) { int *shape, class_dim; int i, total=1, unfixed=-1; VALUE klass; if (ary->total==0) rb_raise(rb_eRuntimeError, "cannot reshape empty array"); klass = CLASS_OF(self); class_dim = NUM2INT(rb_const_get(klass, na_id_class_dim)); if (argc == 0) { /* trim ranks of size=1 */ shape = ALLOCA_N(int,ary->rank+1); for (i=0; irank; ++i) shape[i]=1; na_shrink_rank( self, class_dim, shape ); if (ary->rank==0) ary->rank=1; return; } /* get shape from argument */ shape = ALLOC_N(int,argc); for (i=0; i=0) { if (ary->total % total != 0) rb_raise(rb_eArgError, "Total size size must be divisor"); shape[unfixed] = ary->total / total; } else if (total != ary->total) rb_raise(rb_eArgError, "Total size must be same"); /* exchange */ xfree(ary->shape); ary->shape = shape; ary->rank = argc; } /* method: reshape!(size1,size2,...,sizeN) */ static VALUE na_reshape_bang(int argc, VALUE *argv, VALUE self) { struct NARRAY *ary; GetNArray(self,ary); na_reshape(argc, argv, ary, self); return self; } /* method: reshape(size1,size2,...,sizeN) */ static VALUE na_reshape_ref(int argc, VALUE *argv, VALUE self) { struct NARRAY *ary; GetNArray(self,ary); ary = na_ref_alloc_struct(self); na_reshape(argc, argv, ary, self); return na_wrap_struct(ary,self); } /* method: flatten! */ static VALUE na_flatten_bang(VALUE self) { struct NARRAY *ary; GetNArray(self,ary); if (ary->total==0 || ary->rank==0) rb_raise(rb_eRuntimeError, "cannot reshape empty array"); ary->shape[0] = ary->total; ary->rank = 1; return self; } /* method: flatten */ static VALUE na_flatten_ref(VALUE self) { return na_flatten_bang( na_wrap_struct( na_ref_alloc_struct(self), self )); } /* private function for newdim */ static void na_newdim(int argc, VALUE *argv, struct NARRAY *ary) { int *shape, *count; int i, j; if (argc==0) rb_raise(rb_eArgError, "Argument required"); if (ary->total==0) rb_raise(rb_eRuntimeError, "cannot extend empty array"); /* count new rank */ count = ALLOCA_N(int,ary->rank+1); for (i=0; i<=ary->rank; ++i) count[i]=0; for (i=0; iappend after last rank */ j += ary->rank+1; if (j<0 || j>ary->rank) /* range check */ rb_raise(rb_eArgError, "rank out of range"); ++count[j]; } /* extend shape shape */ shape = ALLOC_N(int,ary->rank+argc); for (j=i=0; irank; ++i) { while (count[i]-->0) shape[j++] = 1; shape[j++] = ary->shape[i]; } while (count[i]-->0) shape[j++] = 1; /* exchange shape */ xfree(ary->shape); ary->shape = shape; ary->rank += argc; } /* method: newdim!(size1,size2,...,sizeN) */ static VALUE na_newdim_bang(int argc, VALUE *argv, VALUE self) { struct NARRAY *ary; GetNArray(self,ary); na_newdim(argc, argv, ary); return self; } /* method: newdim(size1,size2,...,sizeN) */ VALUE na_newdim_ref(int argc, VALUE *argv, VALUE self) { struct NARRAY *ary; GetNArray(self,ary); ary = na_ref_alloc_struct(self); na_newdim(argc, argv, ary); return na_wrap_struct(ary,self); } /* method: fill!(val) */ VALUE na_fill(VALUE self, volatile VALUE val) { struct NARRAY *a1, *a2; GetNArray(self,a1); val = na_cast_unless_narray(val,a1->type); GetNArray(val,a2); if (a2->total != 1) rb_raise(rb_eArgError, "single-element argument required"); SetFuncs[a1->type][a2->type]( a1->total, a1->ptr, na_sizeof[a1->type], a2->ptr, 0 ); return self; } /* method: indgen!([start,[step]]) */ VALUE na_indgen(int argc, VALUE *argv, VALUE self) { int start=0, step=1; struct NARRAY *ary; if (argc>0) { start = NUM2INT(argv[0]); if (argc==2) step = NUM2INT(argv[1]); else if (argc>2) rb_raise(rb_eArgError, "wrong # of arguments (%d for <= 2)", argc); } GetNArray(self,ary); IndGenFuncs[ary->type]( ary->total, ary->ptr, na_sizeof[ary->type], start, step ); return self; } /* method: where2 idx_true, idx_false = narray.where2 */ static VALUE na_where2(volatile VALUE obj) { VALUE v1, v0; int n, i, n1, n0; char *c; int32_t *idx1, *idx0; struct NARRAY *ary, *a1, *a0; /* a1=true, a0=false */ GetNArray(obj,ary); /* Convert to NA_BYTE by calling "obj.ne(0)", if needed */ if(ary->type != NA_BYTE) { obj = rb_funcall(obj, na_id_ne, 1, INT2FIX(0)); GetNArray(obj,ary); } n = ary->total; /* Count true */ c = ary->ptr; n1 = 0; for (i=0; iptr; v0 = na_make_object( NA_LINT, 1, &n0, cNArray ); GetNArray(v0,a0); idx0 = (int32_t*) a0->ptr; /* Get Indices */ c = ary->ptr; for ( i=0; iptr; sz = na_sizeof[ary->type]; func = SetFuncs[NA_ROBJ][ary->type]; for ( i=ary->total; i-->0; ) { (*func)( 1, &v, 0, p, 0 ); rb_yield(v); p += sz; } return Qnil; } else { return rb_funcall(obj, rb_intern("to_enum"), 0); } } /* iterator: collect() */ static VALUE na_collect(VALUE obj1) { int i, sz; VALUE v, obj2; struct NARRAY *a1, *a2; char *p1, *p2; void (*get)(), (*set)(); GetNArray(obj1,a1); obj2 = na_make_object(a1->type, a1->rank, a1->shape, CLASS_OF(obj1)); GetNArray(obj2,a2); p1 = a1->ptr; p2 = a2->ptr; sz = na_sizeof[a1->type]; get = SetFuncs[NA_ROBJ][a1->type]; set = SetFuncs[a1->type][NA_ROBJ]; for ( i=a1->total; i-->0; ) { (*get)( 1, &v, 0, p1, 0 ); v = rb_yield(v); (*set)( 1, p2, 0, &v, 0 ); p1 += sz; p2 += sz; } return obj2; } /* iterator: collect!() */ static VALUE na_collect_bang(VALUE self) { int i, sz; VALUE v; struct NARRAY *a1; char *p1; void (*get)(), (*set)(); GetNArray(self,a1); p1 = a1->ptr; sz = na_sizeof[a1->type]; get = SetFuncs[NA_ROBJ][a1->type]; set = SetFuncs[a1->type][NA_ROBJ]; for ( i=a1->total; i-->0; ) { (*get)( 1, &v, 0, p1, 0 ); v = rb_yield(v); (*set)( 1, p1, 0, &v, 0 ); p1 += sz; } return self; } /* initialization of NArray Class */ void Init_narray() { ID id_Complex = rb_intern("Complex"); if (!rb_const_defined( rb_cObject, id_Complex)) { /* require Complex class */ rb_require("complex"); } cComplex = rb_const_get( rb_cObject, rb_intern("Complex") ); /* define NArray class */ cNArray = rb_define_class("NArray",rb_cObject); /* class methods */ rb_define_singleton_method(cNArray,"new",na_s_new,-1); rb_define_singleton_method(cNArray,"byte",na_s_new_byte,-1); rb_define_singleton_method(cNArray,"sint",na_s_new_sint,-1); rb_define_singleton_method(cNArray,"lint",na_s_new_int,-1); rb_define_singleton_method(cNArray,"int", na_s_new_int,-1); rb_define_singleton_method(cNArray,"sfloat",na_s_new_sfloat,-1); rb_define_singleton_method(cNArray,"dfloat",na_s_new_float,-1); rb_define_singleton_method(cNArray,"float", na_s_new_float,-1); rb_define_singleton_method(cNArray,"scomplex",na_s_new_scomplex,-1); rb_define_singleton_method(cNArray,"dcomplex",na_s_new_complex,-1); rb_define_singleton_method(cNArray,"complex", na_s_new_complex,-1); rb_define_singleton_method(cNArray,"object",na_s_new_object,-1); rb_define_singleton_method(cNArray,"to_na",na_s_to_na,-1); rb_define_singleton_method(cNArray,"to_narray",na_s_to_na,-1); rb_define_singleton_method(cNArray,"[]",na_s_bracket,-1); /* methods */ rb_define_method(cNArray, "shape", na_shape,0); rb_define_alias(cNArray, "sizes","shape"); rb_define_method(cNArray, "size", na_size,0); rb_define_alias(cNArray, "total","size"); rb_define_alias(cNArray, "length","size"); rb_define_method(cNArray, "rank", na_rank,0); rb_define_alias(cNArray, "dim","rank"); rb_define_alias(cNArray, "dimension","rank"); rb_define_method(cNArray, "typecode", na_typecode,0); rb_define_method(cNArray, "element_size", na_element_size,0); rb_define_method(cNArray, "empty?", na_is_empty,0); rb_define_method(cNArray, "clone", na_clone,0); rb_define_alias(cNArray, "dup","clone"); rb_define_method(cNArray, "inspect", na_inspect,0); rb_define_method(cNArray, "coerce", na_coerce,1); rb_define_method(cNArray, "reshape", na_reshape_ref,-1); rb_define_method(cNArray, "reshape!", na_reshape_bang,-1); rb_define_alias(cNArray, "shape=","reshape!"); rb_define_method(cNArray, "newdim", na_newdim_ref,-1); rb_define_alias(cNArray, "newrank","newdim"); rb_define_method(cNArray, "newdim!", na_newdim_bang,-1); rb_define_alias(cNArray, "newdim=","newdim!"); rb_define_alias(cNArray, "newrank!","newdim!"); rb_define_alias(cNArray, "newrank=","newdim!"); rb_define_method(cNArray, "flatten", na_flatten_ref,0); rb_define_method(cNArray, "flatten!", na_flatten_bang,0); rb_define_method(cNArray, "fill!", na_fill,1); rb_define_alias(cNArray, "fill","fill!"); rb_define_method(cNArray, "indgen!", na_indgen,-1); rb_define_alias(cNArray, "indgen","indgen!"); rb_define_method(cNArray, "where", na_where, 0); rb_define_method(cNArray, "where2", na_where2, 0); rb_define_method(cNArray, "each", na_each,0); rb_define_method(cNArray, "collect", na_collect,0); rb_define_method(cNArray, "collect!", na_collect_bang,0); rb_define_alias(cNArray, "map", "collect"); rb_define_alias(cNArray, "map!", "collect!"); rb_define_method(cNArray, "to_s", na_to_s, 0); rb_define_method(cNArray, "to_f", na_to_float, 0); rb_define_method(cNArray, "to_i", na_to_integer, 0); rb_define_method(cNArray, "to_type", na_to_type, 1); rb_define_method(cNArray, "to_binary", na_to_binary, 0); rb_define_method(cNArray, "to_type_as_binary", na_to_type_as_binary, 1); rb_define_method(cNArray, "to_string", na_to_string, 0); rb_define_const(cNArray, "NARRAY_VERSION", rb_str_new2(NARRAY_VERSION)); rb_define_const(cNArray, "BYTE", INT2FIX(NA_BYTE)); rb_define_const(cNArray, "SINT", INT2FIX(NA_SINT)); rb_define_const(cNArray, "LINT", INT2FIX(NA_LINT)); rb_define_const(cNArray, "INT", INT2FIX(NA_LINT)); rb_define_const(cNArray, "SFLOAT", INT2FIX(NA_SFLOAT)); rb_define_const(cNArray, "DFLOAT", INT2FIX(NA_DFLOAT)); rb_define_const(cNArray, "FLOAT", INT2FIX(NA_DFLOAT)); rb_define_const(cNArray, "SCOMPLEX", INT2FIX(NA_SCOMPLEX)); rb_define_const(cNArray, "DCOMPLEX", INT2FIX(NA_DCOMPLEX)); rb_define_const(cNArray, "COMPLEX", INT2FIX(NA_DCOMPLEX)); rb_define_const(cNArray, "ROBJ", INT2FIX(NA_ROBJ)); rb_define_const(cNArray, "OBJECT", INT2FIX(NA_ROBJ)); rb_define_const(cNArray, "NONE", INT2FIX(NA_NONE)); rb_define_const(cNArray, "CLASS_DIMENSION", INT2FIX(0)); #ifdef WORDS_BIGENDIAN rb_define_const(cNArray, "ENDIAN", INT2FIX(1)); #else #ifdef DYNAMIC_ENDIAN /* not supported yet */ rb_define_const(cNArray, "ENDIAN", INT2FIX(-1)); #else /* LITTLE_ENDIAN */ rb_define_const(cNArray, "ENDIAN", INT2FIX(0)); #endif #endif /* Reference */ rb_define_singleton_method(cNArray, "refer", na_s_refer,1); rb_define_singleton_method(cNArray, "ref", na_s_refer,1); rb_define_method(cNArray, "refer", na_refer,0); rb_define_method(cNArray, "original", na_original,0); Init_na_array(); Init_na_index(); Init_nmath(); Init_na_funcs(); Init_na_random(); cNArrayScalar = rb_define_class("NArrayScalar", cNArray); na_id_beg = rb_intern("begin"); na_id_end = rb_intern("end"); na_id_exclude_end = rb_intern("exclude_end?"); na_id_real = rb_intern("real"); na_id_imag = rb_intern("imag"); na_id_new = rb_intern("new"); na_id_to_i = rb_intern("to_i"); na_id_usec = rb_intern("usec"); na_id_now = rb_intern("now"); na_id_compare = rb_intern("<=>"); na_id_ne = rb_intern("ne"); na_id_and = rb_intern("&&"); na_id_or = rb_intern("||"); na_id_minus = rb_intern("-@"); na_id_abs = rb_intern("abs"); na_id_power = rb_intern("**"); na_id_add = rb_intern("+"); na_id_sbt = rb_intern("-"); na_id_mul = rb_intern("*"); na_id_div = rb_intern("/"); na_id_mod = rb_intern("%"); na_id_coerce_rev = rb_intern("coerce_rev"); na_id_Complex = rb_intern("Complex"); na_id_class_dim = rb_intern("CLASS_DIMENSION"); Init_na_linalg(); /* NArray extention script */ rb_require("narray/narray_ext"); } narray-0.6.1.2/src/na_func.c0000644000175000017500000011354712745364057015402 0ustar uwabamiuwabami/* na_func.c Numerical Array Extention for Ruby (C) Copyright 1999-2008 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ #include #include "narray.h" #include "narray_local.h" int na_max3(int a, int b, int c) { int m; if ((a) > (b)) m = a; else m = b; if ((c) > m) m = c; return m; } void na_shape_max3(int ndim, int *max_shp, int *shp1, int *shp2, int *shp3) { int i; for (i=0; i0; ) { *(idx++)*=b; } else for (idx=s[r].idx,i=s[r].n; i-->0; ) { *(idx++)<<=b; } } } /* set termination mark */ s[rank].n = 0; s[rank].idx = NULL; for (r=rank-1;r>=0;--r) { /* set beginning pointers */ if ( s[r].idx == NULL ) s[r].pbeg = s[r].stride * s[r].beg * elmsz; else s[r].pbeg = s[r].idx[0]; } } static void na_do_loop_unary( int nd, char *p1, char *p2, struct slice *s1, struct slice *s2, void (*func)() ) { int *si; int i; int ps1 = s1[0].pstep; int ps2 = s2[0].pstep; i = nd; si = ALLOCA_N(int,nd); s1[i].p = p1; s2[i].p = p2; for(;;) { /* set pointers */ while (i > 0) { --i; s2[i].p = s2[i].pbeg + s2[i+1].p; s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = s1[i].n; } (*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2); /* rank up */ do { if ( ++i >= nd ) return; } while ( --si[i] == 0 ); /* next point */ s1[i].p += s1[i].pstep; s2[i].p += s2[i].pstep; } } static void na_do_loop_binary( int nd, char *p1, char *p2, char *p3, struct slice *s1, struct slice *s2, struct slice *s3, void (*func)() ) { int i; int ps1 = s1[0].pstep; int ps2 = s2[0].pstep; int ps3 = s3[0].pstep; int *si; si = ALLOCA_N(int,nd); i = nd; s1[i].p = p1; s2[i].p = p2; s3[i].p = p3; for(;;) { /* set pointers */ while (i > 0) { --i; s3[i].p = s3[i].pbeg + s3[i+1].p; s2[i].p = s2[i].pbeg + s2[i+1].p; s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = s1[i].n; } /* rank 0 loop */ (*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2, s3[0].p, ps3); /* rank up */ do { if ( ++i >= nd ) return; } while ( --si[i] == 0 ); /* next point */ s1[i].p += s1[i].pstep; s2[i].p += s2[i].pstep; s3[i].p += s3[i].pstep; } } void na_loop_index_ref( struct NARRAY *a1, struct NARRAY *a2, struct slice *s1, struct slice *s2, void (*func)() ) { char *p1, *p2; int nr, i, ii; int ps1 = s1[0].pstep; int ps2 = s2[0].pstep; int *si; na_index_t *idx; /* int copy; if (a1->type==a2->type && s1[0].step==1 && s2[0].step==1) copy = s1[0].n * na_sizeof[a1->type]; else copy = 0; */ /* Initialize */ nr = i = a1->rank; si = ALLOCA_N(int,nr); s1[i].p = a1->ptr; s2[i].p = a2->ptr; for(;;) { /* set pointers */ while (i > 0) { --i; s2[i].p = s2[i].pbeg + s2[i+1].p; s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = 0; } /* rank 0 loop */ if ( s2[0].idx == NULL ) { /* regular interval */ /* if (copy) { memcpy(s1[0].p, s2[0].p, copy); } else */ (*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2); } else { /* a2 has index */ p1 = s1[0].p; p2 = s2[1].p; for ( idx=s2[0].idx, ii=s2[0].n; ii-->0;) { (*func)( 1, p1, 0, p2+*(idx++), 0 ); p1 += ps1; } } /* rank up */ do { if ( ++i >= nr ) return; } while ( ++si[i] == s1[i].n ); /* next point */ s1[i].p += s1[i].pstep; /* array2 may have index */ if ( s2[i].idx == NULL ) s2[i].p += s2[i].pstep; else s2[i].p = s2[i+1].p + s2[i].idx[si[i]]; /* * s2[i].pstep; */ } } void na_loop_general( struct NARRAY *a1, struct NARRAY *a2, struct slice *s1, struct slice *s2, void (*func)() ) { char *p1, *p2; int nr, i, ii; int ps1 = s1[0].pstep; int ps2 = s2[0].pstep; int *si; na_index_t *idx1, *idx2; /* Initialize */ nr = i = a1->rank; si = ALLOCA_N(int,nr); s1[i].p = a1->ptr; s2[i].p = a2->ptr; for(;;) { /* set pointers */ while (i > 0) { --i; s2[i].p = s2[i].pbeg + s2[i+1].p; s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = 0; } /* rank 0 loop */ if ( s1[0].idx == NULL ) { if ( s2[0].idx == NULL ) { /* normal interval */ (*func)(s2[0].n, s1[0].p, ps1, s2[0].p, ps2); } else { /* s2 has index */ p1 = s1[0].p; p2 = s2[1].p; for ( idx2=s2[0].idx, ii=s2[0].n; ii-->0; ) { (*func)( 1, p1, 0, p2+*(idx2++), 0 ); p1 += ps1; } } } else { if ( s2[0].idx == NULL ) { /* s1 has index */ p1 = s1[1].p; p2 = s2[0].p; for ( idx1=s1[0].idx, ii=s2[0].n; ii-->0; ) { (*func)( 1, p1+*(idx1++), 0, p2, 0 ); p2 += ps2; } } else { /* s1 & s2 has index */ p1 = s1[1].p; p2 = s2[1].p; for ( idx1=s1[0].idx, idx2=s2[0].idx, ii=s2[0].n; ii-->0; ) { (*func)( 1, p1+*(idx1++), 0, p2+*(idx2++), 0 ); } } } /* rank up */ do { if ( ++i >= nr ) return; } while ( ++si[i] == s1[i].n ); /* next point for a1 */ if ( s1[i].idx == NULL ) s1[i].p += s1[i].pstep; else s1[i].p = s1[i+1].p + s1[i].idx[si[i]]; /* next point for a2 */ if ( s2[i].idx == NULL ) s2[i].p += s2[i].pstep; else s2[i].p = s2[i+1].p + s2[i].idx[si[i]]; } } void na_shape_copy( int ndim, int *shape, struct NARRAY *a ) { int i; for (i=0; irank; ++i) shape[i] = a->shape[i]; for ( ; i1 ) { s1[j].n = s2[j].n = shp2[i]; s1[j].step = 0; s2[j].step = 1; } else if ( shp2[i]==1 && shp1[i]>1 ) { s1[j].n = s2[j].n = shp1[i]; s1[j].step = 1; s2[j].step = 0; } else if ( shp1[i] == shp2[i] ) { s1[j].n = s2[j].n = shp1[i]; s1[j].step = 1; s2[j].step = 1; } else rb_raise(rb_eRuntimeError, "Array size mismatch: %i != %i in %i-th dim", shp1[i], shp2[i], i); if (j0) if ( s1[j].step == s1[j-1].step && s2[j].step == s2[j-1].step ) { /* contract dimension */ s1[j-1].n = s2[j-1].n *= s2[j].n; shp1[j-1] *= shp1[j]; shp2[j-1] *= shp2[j]; continue; } s1[j].beg = s2[j].beg = 0; s1[j].idx = s2[j].idx = NULL; ++j; } return j; } static int na_set_slice_check(int ary_sz, int itr_sz, int i) { if ( ary_sz == itr_sz ) return 1; else if ( ary_sz == 1 ) return 0; else rb_raise(rb_eRuntimeError, "Array size mismatch: %i != %i at %i-th dim", ary_sz, itr_sz, i); } int na_set_slice_3obj( int ndim, struct slice *s1, struct slice *s2, struct slice *s3, int *shp1, int *shp2, int *shp3, int *shape ) { int i, j; /* for repetitous access */ for (i=j=0; i0) { if ( s1[j].step == s1[j-1].step && s2[j].step == s2[j-1].step && s3[j].step == s3[j-1].step ) /* contract dimension */ { s1[j-1].n = s2[j-1].n = s3[j-1].n *= shape[i]; shp1[j-1] *= shp1[j]; shp2[j-1] *= shp2[j]; shp3[j-1] *= shp3[j]; continue; } } s1[j].n = s2[j].n = s3[j].n = shape[i]; s1[j].beg = s2[j].beg = s3[j].beg = 0; s1[j].idx = s2[j].idx = s3[j].idx = NULL; ++j; } return j; } static void na_exec_unary(struct NARRAY *a1, struct NARRAY *a2, void (*func)()) { int ndim; int *shp1, *shp2; struct slice *s1, *s2; /* empty check */ if ( a1->total==0 || a2->total==0 ) /* rb_raise( rb_eTypeError, "cannot execute for empty array" ); */ return; /* do nothing */ ndim = NA_MAX(a1->rank,a2->rank); NA_ALLOC_SLICE(s1,(ndim+1)*2,shp1,ndim*2); shp2 = &shp1[ndim]; s2 = &s1[ndim+1]; na_shape_copy( ndim, shp1, a1 ); na_shape_copy( ndim, shp2, a2 ); ndim = na_set_slice_2obj( ndim, s1, s2, shp1, shp2 ); na_init_slice( s1, ndim, shp1, na_sizeof[a1->type] ); na_init_slice( s2, ndim, shp2, na_sizeof[a2->type] ); na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2, func ); xfree(s1); } /* a1 and/or a2 and/or a3 have extensible index */ static void na_exec_binary( struct NARRAY *a1, struct NARRAY *a2, struct NARRAY *a3, void (*func)() ) { int ndim; int *itr, *shp1, *shp2, *shp3; struct slice *s1, *s2, *s3; /* empty check */ if (a1->total==0) return; /* do nothing */ ndim = na_max3(a1->rank, a2->rank, a3->rank); NA_ALLOC_SLICE(s1,(ndim+1)*3,shp1,ndim*4); shp2 = &shp1[ndim]; shp3 = &shp2[ndim]; itr = &shp3[ndim]; s2 = &s1[ndim+1]; s3 = &s2[ndim+1]; na_shape_copy( ndim, shp1, a1 ); na_shape_copy( ndim, shp2, a2 ); na_shape_copy( ndim, shp3, a3 ); na_shape_max3( ndim, itr, shp1, shp2, shp3 ); ndim = na_set_slice_3obj( ndim, s1, s2, s3, shp1, shp2, shp3, itr ); na_init_slice(s1, ndim, shp1, na_sizeof[a1->type] ); na_init_slice(s2, ndim, shp2, na_sizeof[a2->type] ); na_init_slice(s3, ndim, shp3, na_sizeof[a3->type] ); na_do_loop_binary( ndim, a1->ptr, a2->ptr, a3->ptr, s1, s2, s3, func ); xfree(s1); } static void na_shape_max_2obj(int ndim, int *shape, struct NARRAY *a1, struct NARRAY *a2) { struct NARRAY *tmp; int i; /* empty check */ if ( a1->total==0 || a2->total==0 ) rb_raise( rb_eTypeError, "cannot execute for empty array" ); if (a1->rank < a2->rank) { NA_SWAP(a1,a2,tmp); } for (i=0; irank; ++i) { shape[i] = NA_MAX(a1->shape[i],a2->shape[i]); } for ( ; irank; ++i) { shape[i] = a1->shape[i]; } for ( ; itotal==0 || a2->total==0 ) return na_make_empty(type, klass); /* return empty */ ndim = NA_MAX(a1->rank, a2->rank); shape = ALLOCA_N(int, ndim); na_shape_max_2obj( ndim, shape, a1, a2 ); return na_make_object( type, ndim, shape, klass ); } static ID na_bifunc_to_id(na_bifunc_t funcs) { if (funcs==AddBFuncs) return na_id_add; if (funcs==SbtBFuncs) return na_id_sbt; if (funcs==MulBFuncs) return na_id_mul; if (funcs==DivBFuncs) return na_id_div; if (funcs==ModBFuncs) return na_id_mod; return 0; /* if (funcs==PowFuncs) return na_id_power; rb_raise(rb_eRuntimeError, "coerce_rev: function not soppurted"); */ } static VALUE na_bifunc_class(VALUE klass1, VALUE klass2) { if ( klass2==cNArray || klass2==cNArrayScalar ) { if ( klass1==cNArrayScalar ) return cNArray; else return klass1; } return Qnil; } static VALUE na_bifunc(VALUE obj1, VALUE obj2, VALUE klass, na_bifunc_t funcs) { VALUE obj3; ID id; int type; Check_Type(obj1, T_DATA); obj2 = na_upcast_object(obj2,NA_STRUCT(obj1)->type); obj1 = na_upcast_type(obj1,type=NA_STRUCT(obj2)->type); if (klass==Qnil) { klass = na_bifunc_class(CLASS_OF(obj1),CLASS_OF(obj2)); if (klass==Qnil) { /* coerce_rev */ if ((id=na_bifunc_to_id(funcs))!=0) return rb_funcall( obj2, na_id_coerce_rev, 2, obj1, ID2SYM(id) ); else klass = cNArray; } } obj3 = na_make_object_extend(NA_STRUCT(obj1),NA_STRUCT(obj2),type,klass); na_exec_binary( NA_STRUCT(obj3), NA_STRUCT(obj1), NA_STRUCT(obj2), funcs[type] ); return obj3; } static VALUE na_power(VALUE val1, VALUE val2) { volatile VALUE obj1, obj2, obj3; struct NARRAY *a1, *a2; obj1 = val1; obj2 = val2; GetNArray(obj1,a1); obj2 = na_to_narray(obj2); GetNArray(obj2,a2); if (a1->type==NA_ROBJ && a2->type!=NA_ROBJ) { obj2 = na_change_type(obj2,NA_ROBJ); GetNArray(obj2,a2); } else if (a2->type==NA_ROBJ && a1->type!=NA_ROBJ) { obj1 = na_change_type(obj1,NA_ROBJ); GetNArray(obj1,a1); } else if (!NA_IsCOMPLEX(a1) && NA_IsCOMPLEX(a2)) { obj1 = na_upcast_type(obj1,a2->type); GetNArray(obj1,a1); } obj3 = na_make_object_extend( a1, a2, na_upcast[a1->type][a2->type], CLASS_OF(obj1) ); na_exec_binary( NA_STRUCT(obj3), a1, a2, PowFuncs[a1->type][a2->type] ); return obj3; } static VALUE na_set_func(VALUE obj1, volatile VALUE obj2, na_ufunc_t funcs) { struct NARRAY *a1; GetNArray(obj1,a1); obj2 = na_cast_object(obj2,a1->type); na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), funcs[a1->type] ); return obj1; } static VALUE na_imag_set(VALUE obj1, volatile VALUE obj2) { struct NARRAY *a1; GetNArray(obj1,a1); obj2 = na_cast_object(obj2, na_cast_real[a1->type]); na_exec_unary( NA_STRUCT(obj1), NA_STRUCT(obj2), ImgSetFuncs[a1->type] ); return obj1; } static VALUE na_unary_func(VALUE self, const int *cast, na_ufunc_t funcs) { VALUE ans; struct NARRAY *a2; GetNArray(self,a2); ans = na_make_object(cast[a2->type], a2->rank, a2->shape, CLASS_OF(self)); na_exec_unary( NA_STRUCT(ans), a2, funcs[a2->type] ); return ans; } /* local function for comparison */ static VALUE na_compare_func(VALUE self, VALUE other, na_bifunc_t funcs) { VALUE ans; int type; Check_Type(self, T_DATA); /*if (NA_IsComplex(a1)) rb_raise();*/ other = na_upcast_object(other,NA_STRUCT(self)->type); self = na_upcast_type(self,type=NA_STRUCT(other)->type); ans = na_make_object_extend( NA_STRUCT(self), NA_STRUCT(other), NA_BYTE, cNArray ); na_exec_binary( NA_STRUCT(ans), NA_STRUCT(self), NA_STRUCT(other), funcs[type] ); return ans; } /* method: self + other */ static VALUE na_add(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, AddBFuncs ); } /* method: self - other */ static VALUE na_sbt(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, SbtBFuncs ); } /* method: self * other */ static VALUE na_mul(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, MulBFuncs ); } /* method: self / other */ static VALUE na_div(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, DivBFuncs ); } /* method: self / other */ static VALUE na_mod(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, ModBFuncs ); } /* method: self & other */ static VALUE na_bit_and(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, BAnFuncs ); } /* method: self | other */ static VALUE na_bit_or(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, BOrFuncs ); } /* method: self ^ other */ static VALUE na_bit_xor(VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, Qnil, BXoFuncs ); } /* method: atan2(y,x) */ static VALUE na_math_atan2(VALUE module, volatile VALUE y, volatile VALUE x) { VALUE ans; struct NARRAY *ya, *xa, *aa; if (TYPE(y) == T_ARRAY) { y = na_ary_to_nary(y,cNArray); } else if (!IsNArray(y)) { y = na_make_scalar(y,na_object_type(y)); } if (TYPE(x) == T_ARRAY) { x = na_ary_to_nary(x,cNArray); } else if (!IsNArray(x)) { x = na_make_scalar(x,na_object_type(x)); } GetNArray(y,ya); GetNArray(x,xa); if (NA_IsINTEGER(ya) && NA_IsINTEGER(xa)) { y = na_upcast_type(y,NA_DFLOAT); x = na_upcast_type(x,NA_DFLOAT); } ans = na_bifunc( y, x, Qnil, atan2Funcs ); GetNArray(ans,aa); if (CLASS_OF(y) == cNArrayScalar && CLASS_OF(x) == cNArrayScalar) SetFuncs[NA_ROBJ][aa->type](1,&ans,0,aa->ptr,0); return ans; } /* singleton method: NArray.mul( obj1, obj2 ) */ static VALUE na_s_mul(VALUE klass, VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, klass, MulBFuncs ); } /* singleton method: NArray.div( obj1, obj2 ) */ static VALUE na_s_div(VALUE klass, VALUE obj1, VALUE obj2) { return na_bifunc( obj1, obj2, klass, DivBFuncs ); } /* method: self.add!(other) */ static VALUE na_add_bang(VALUE obj1, VALUE obj2) { return na_set_func( obj1, obj2, AddUFuncs ); } /* method: self.sbt!(other) */ static VALUE na_sbt_bang(VALUE obj1, VALUE obj2) { return na_set_func( obj1, obj2, SbtUFuncs ); } /* method: self.div!(other) */ static VALUE na_div_bang(VALUE obj1, VALUE obj2) { return na_set_func( obj1, obj2, DivUFuncs ); } /* method: self.mul!(other) */ static VALUE na_mul_bang(VALUE obj1, VALUE obj2) { return na_set_func( obj1, obj2, MulUFuncs ); } /* method: self.mod!(other) */ static VALUE na_mod_bang(VALUE obj1, VALUE obj2) { return na_set_func( obj1, obj2, ModUFuncs ); } /* method: self.conj! */ static VALUE na_conj_bang(VALUE self) { return na_set_func( self, self, ConjFuncs ); } /* method: self.swap_byte */ static VALUE na_swap_byte(VALUE self) { return na_unary_func( self, na_no_cast, SwpFuncs ); } /* method: self.hton , self.ntoh */ static VALUE na_hton(VALUE self) { return na_unary_func( self, na_no_cast, H2NFuncs ); } /* method: self.htov , self.vtoh */ static VALUE na_htov(VALUE self) { return na_unary_func( self, na_no_cast, H2VFuncs ); } /* method: ~self */ static VALUE na_bit_rev(VALUE self) { return na_unary_func( self, na_no_cast, BRvFuncs ); } /* method: -self */ static VALUE na_neg(VALUE self) { return na_unary_func( self, na_no_cast, NegFuncs ); } /* method: self.recip */ static VALUE na_recip(VALUE self) { return na_unary_func( self, na_no_cast, RcpFuncs ); } /* method: self.abs */ static VALUE na_abs(VALUE self) { return na_unary_func( self, na_cast_real, AbsFuncs ); } /* method: self.real */ static VALUE na_real(VALUE self) { return na_unary_func( self, na_cast_real, RealFuncs ); } /* method: self.imag */ static VALUE na_imag(VALUE self) { return na_unary_func( self, na_cast_real, ImagFuncs ); } /* method: self.imag */ static VALUE na_angle(VALUE self) { return na_unary_func( self, na_cast_real, AnglFuncs ); } /* method: self.im */ static VALUE na_imag_mul(VALUE self) { return na_unary_func( self, na_cast_comp, ImagMulFuncs ); } /* method: self.conj */ static VALUE na_conj(VALUE self) { return na_unary_func( self, na_no_cast, ConjFuncs ); } /* method: self.floor */ static VALUE na_floor(VALUE self) { return na_unary_func( self, na_cast_round, FloorFuncs ); } /* method: self.ceil */ static VALUE na_ceil(VALUE self) { return na_unary_func( self, na_cast_round, CeilFuncs ); } /* method: self.round */ static VALUE na_round(VALUE self) { return na_unary_func( self, na_cast_round, RoundFuncs ); } /* method: self.not */ static VALUE na_not(VALUE self) { return na_unary_func( self, na_cast_byte, NotFuncs ); } /* method: self.and other */ static VALUE na_cond_and(VALUE obj1, VALUE obj2) { return na_compare_func( obj1, obj2, AndFuncs ); } /* method: self.or other */ static VALUE na_cond_or(VALUE obj1, VALUE obj2) { return na_compare_func( obj1, obj2, Or_Funcs ); } /* method: self.xor other */ static VALUE na_cond_xor(VALUE obj1, VALUE obj2) { return na_compare_func( obj1, obj2, XorFuncs ); } /* method: self <=> other */ static VALUE na_compare(VALUE obj1, VALUE obj2) { return na_compare_func( obj1, obj2, CmpFuncs ); } /* method: self.eq(other) */ static VALUE na_equal(VALUE obj1, VALUE obj2) { return na_compare_func( obj1, obj2, EqlFuncs ); } /* method: self.ne(other) */ static VALUE na_not_equal(VALUE obj1, VALUE obj2) { VALUE obj; int i; char *p; struct NARRAY *a; obj = na_compare_func( obj1, obj2, EqlFuncs ); GetNArray(obj,a); p = a->ptr; for( i=a->total; i-->0; ) { *p = *p==0 ? 1 : 0; ++p; } return obj; } /* method: self > other */ static VALUE na_greater_than(VALUE self, VALUE obj2) { int i; char *p; struct NARRAY *a; self = na_compare_func( self, obj2, CmpFuncs ); GetNArray(self,a); p = a->ptr; for( i=a->total; i-->0; ) { if (*p!=1) *p=0; ++p; } return self; } /* method: self >= other */ static VALUE na_greater_equal(VALUE obj1, VALUE obj2) { VALUE obj; int i; char *p; struct NARRAY *a; obj = na_compare_func( obj1, obj2, CmpFuncs ); GetNArray(obj,a); p = a->ptr; for( i=a->total; i-->0; ) { if (*p==1 || *p==0) *p=1; else *p=0; ++p; } return obj; } /* method: self < other */ static VALUE na_less_than(VALUE obj1, VALUE obj2) { VALUE obj; int i; char *p; struct NARRAY *a; obj = na_compare_func( obj1, obj2, CmpFuncs ); GetNArray(obj,a); p = a->ptr; for( i=a->total; i-->0; ) { if (*p==2) *p=1; else *p=0; ++p; } return obj; } /* method: self <= other */ static VALUE na_less_equal(VALUE obj1, VALUE obj2) { VALUE obj; int i; char *p; struct NARRAY *a; obj = na_compare_func( obj1, obj2, CmpFuncs ); GetNArray(obj,a); p = a->ptr; for( i=a->total; i-->0; ) { if (*p==2 || *p==0) *p=1; else *p=0; ++p; } return obj; } /* ------- Sum, Min, Max, Transpose -------- */ VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err ); static int na_arg_to_rank(int argc, VALUE *argv, int rankc, int *rankv, int flag) /* e.g.: argv=[1,3..5] if flag==0 rankv = [0,1,0,1,1,1,0,..] else rankv = [1,3,4,5] */ { int i, j, c=0; long r, n; VALUE v; volatile VALUE s; if (flag==0) MEMZERO(rankv,int,rankc); for (i=0;i= rankc ) rb_raise(rb_eArgError, "too many ranks"); v = argv[i]; if (TYPE(v)==T_FIXNUM) { r = NUM2INT(v); if (r<0) r += rankc; /* negative for from end */ if (r<0 || r>=rankc) rb_raise(rb_eArgError, "rank %ld out of range", r); if (flag) rankv[c] = r; else rankv[r] = 1; ++c; } else if (CLASS_OF(v)==rb_cRange) { rb_range_beg_len( v, &r, &n, rankc, 1 ); if ( c+n > rankc ) { s = rb_inspect(v); rb_raise(rb_eArgError,"invalid dimension range: %s",StringValueCStr(s)); } if (flag) { for(j=0; jrank; struct slice *s1, *s2; s1 = ALLOC_N(struct slice, (ndim+1)*2); s2 = &s1[ndim+1]; /* for Source array -- s1 is temporarily used */ na_set_slice_1obj(a2->rank,s1,a2->shape); na_init_slice( s1, ndim, a2->shape, na_sizeof[a2->type] ); /* Transpose Slice */ for (i=0; irank,s1,a1->shape); na_init_slice( s1, ndim, a1->shape, na_sizeof[a1->type] ); /* Loop */ na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2, SetFuncs[a1->type][a2->type] ); xfree(s1); return a1; } /* method: self.transpose( ... ) */ static VALUE na_transpose(int argc, VALUE *argv, VALUE self) { struct NARRAY *a2; int i, rankc, *rankv, *shape; VALUE obj; GetNArray(self,a2); /* Parse Argument */ rankv = ALLOC_N( int, a2->rank*2 ); shape = &rankv[a2->rank]; rankc = na_arg_to_rank( argc, argv, a2->rank, rankv, 1 ); for ( ;rankcrank; ++rankc) rankv[rankc] = rankc; /* Argument Check */ MEMZERO(shape,int,rankc); for (i=0; irank; ++i) shape[i] = a2->shape[rankv[i]]; obj = na_make_object(a2->type, a2->rank, shape, CLASS_OF(self)); na_transpose_bifunc( NA_STRUCT(obj), a2, rankv ); xfree(rankv); return obj; } static void na_accum_set_shape(int *itr_shape, int rank, int *ary_shape, int rankc, int *rankv) { int i; if (rankc==0) { /* Accumulate all elements */ for (i=0; iptr; for (i=ary->total; i>0; --i) *(v++) = zero; } static void na_zero_data(struct NARRAY *ary) { if (ary->type==NA_ROBJ) na_zero_obj(ary); else na_clear_data(ary); } static VALUE na_sum_body(int argc, VALUE *argv, VALUE self, int flag) { int *shape, rankc, *rankv, cl_dim; struct NARRAY *a1, *a2; VALUE obj, klass; GetNArray(self,a1); rankv = ALLOC_N(int,a1->rank*2); rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 ); shape = &rankv[a1->rank]; na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv ); klass = CLASS_OF(self); cl_dim = na_class_dim(klass); if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv)) klass = cNArray; obj = na_make_object(a1->type,a1->rank,shape,klass); GetNArray(obj,a2); na_zero_data(a2); na_exec_unary( a2, a1, AddUFuncs[a1->type] ); if (flag==0) obj = na_shrink_rank(obj,cl_dim,rankv); xfree(rankv); return obj; } /* method: sum( rank, ... ) */ static VALUE na_sum(int argc, VALUE *argv, VALUE self) { return na_sum_body(argc,argv,self,0); } /* method: accum( rank, ... ) */ static VALUE na_accum(int argc, VALUE *argv, VALUE self) { return na_sum_body(argc,argv,self,1); } static VALUE na_prod_body(int argc, VALUE *argv, VALUE self, int flag) { int *shape, rankc, *rankv, cl_dim; struct NARRAY *a1, *a2; VALUE obj, klass; int32_t one = 1; GetNArray(self,a1); rankv = ALLOC_N(int,a1->rank*2); rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 ); shape = &rankv[a1->rank]; na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv ); klass = CLASS_OF(self); cl_dim = na_class_dim(klass); if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv)) klass = cNArray; obj = na_make_object(a1->type,a1->rank,shape,klass); GetNArray(obj,a2); SetFuncs[a2->type][NA_LINT](a2->total, a2->ptr, na_sizeof[a2->type], &one, 0); na_exec_unary( a2, a1, MulUFuncs[a1->type] ); if (flag==0) obj = na_shrink_rank(obj,cl_dim,rankv); xfree(rankv); return obj; } /* method: prod( rank, ... ) */ static VALUE na_prod(int argc, VALUE *argv, VALUE self) { return na_prod_body(argc,argv,self,0); } static VALUE na_mul_add_body(int argc, VALUE *argv, volatile VALUE self, volatile VALUE other, VALUE wrap_klass, int flag) { VALUE ans, op_klass; int rank, cl_dim; int *dst_shape, *max_shape; int rankc, *rankv; int type; struct NARRAY *a1, *a2; GetNArray(self,a1); other = na_upcast_object(other,a1->type); GetNArray(other,a2); self = na_upcast_type(self,type=a2->type); GetNArray(self,a1); rank = NA_MAX(a1->rank,a2->rank); rankv = ALLOC_N(int,rank*3); rankc = na_arg_to_rank( argc, argv, rank, rankv, 0 ); max_shape = &rankv[rank]; na_shape_max_2obj(rank,max_shape,a1,a2); dst_shape = &max_shape[rank]; na_accum_set_shape( dst_shape, rank, max_shape, rankc, rankv ); op_klass = na_bifunc_class(CLASS_OF(self),CLASS_OF(other)); if (op_klass==Qnil) /* coerce_rev --- unsupported */ op_klass = cNArray; cl_dim = na_class_dim(op_klass); if (flag==0 && cl_dim>0 && na_shrink_class(cl_dim,rankv)) op_klass = cNArray; ans = na_make_object( type, rank, dst_shape, (wrap_klass==Qnil) ? op_klass : wrap_klass); na_zero_data( NA_STRUCT(ans) ); na_exec_binary( NA_STRUCT(ans), a1, a2, MulAddFuncs[type] ); if (flag==0) ans = na_shrink_rank(ans,cl_dim,rankv); xfree(rankv); return ans; } /* method: mul_add( other, rank, ... ) */ static VALUE na_mul_add(int argc, VALUE *argv, VALUE self) { if (argc<2) rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc); return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,0); } /* method: mul_accum( other, rank, ... ) */ static VALUE na_mul_accum(int argc, VALUE *argv, VALUE self) { if (argc<2) rb_raise(rb_eArgError, "wrong # of arguments (%d for >=2)", argc); return na_mul_add_body(argc-1,argv+1,self,argv[0],Qnil,1); } /* singleton method: NArray.mul_add( obj1, obj2, rank, ... ) */ static VALUE na_s_mul_add(int argc, VALUE *argv, VALUE klass) { if (argc<3) rb_raise(rb_eArgError, "wrong # of arguments (%d for >=3)", argc); return na_mul_add_body(argc-2,argv+2,argv[0],argv[1],klass,0); } /* cumsum! [1 2 3 4 5] -> [1 3 6 10 15] */ static VALUE na_cumsum_bang(VALUE self) { struct NARRAY *a; int step; GetNArray(self,a); if ( a->rank != 1 ) rb_raise( rb_eTypeError, "only for 1-dimensional array" ); if ( a->total < 2 ) return self; /* do nothing */ step = na_sizeof[a->type]; AddUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step); return self; } /* cumsum */ static VALUE na_cumsum(VALUE self) { return na_cumsum_bang(na_clone(self)); } /* cumprod! [1 2 3 4 5] -> [1 3 6 10 15] */ static VALUE na_cumprod_bang(VALUE self) { struct NARRAY *a; int step; GetNArray(self,a); if ( a->rank != 1 ) rb_raise( rb_eTypeError, "only for 1-dimensional array" ); if ( a->total < 2 ) return self; /* do nothing */ step = na_sizeof[a->type]; MulUFuncs[a->type](a->total-1, a->ptr+step,step, a->ptr,step); return self; } /* cumprod */ static VALUE na_cumprod(VALUE self) { return na_cumprod_bang(na_clone(self)); } /* Copy element of idx=0 from a2 to a1, as start of accumulation */ /* a1->rank <= a2->rank is assumed */ static void na_minmax_copy0(struct NARRAY *a1, struct NARRAY *a2) { int i, ndim=a2->rank; /* a2 has larger rank */ struct slice *s1, *s2; /* Allocate Structure */ s1 = ALLOC_N(struct slice, (ndim+1)*2); s2 = &s1[ndim+1]; na_set_slice_1obj(a1->rank,s1,a1->shape); for (i=0; ishape[i]; /* no-repeat if a1->shape[i]==1 */ s2[i].beg = 0; /* copy idx=0 */ s2[i].step = 1; s2[i].idx = NULL; } /* Initialize */ na_init_slice(s1, ndim, a1->shape, na_sizeof[a1->type] ); na_init_slice(s2, ndim, a2->shape, na_sizeof[a2->type] ); /* Loop */ na_do_loop_unary( ndim, a1->ptr, a2->ptr, s1, s2, SetFuncs[a1->type][a2->type] ); xfree(s1); } static VALUE na_minmax_func(int argc, VALUE *argv, VALUE self, na_ufunc_t funcs) { VALUE obj, klass; int *shape, rankc, *rankv, cl_dim; struct NARRAY *a1, *a2; GetNArray(self,a1); rankv = ALLOC_N(int,a1->rank*2); rankc = na_arg_to_rank( argc, argv, a1->rank, rankv, 0 ); shape = &rankv[a1->rank]; na_accum_set_shape( shape, a1->rank, a1->shape, rankc, rankv ); klass = CLASS_OF(self); cl_dim = na_class_dim(klass); if (na_shrink_class(cl_dim,rankv)) klass = cNArray; obj = na_make_object(a1->type,a1->rank,shape,klass); GetNArray(obj,a2); na_minmax_copy0( a2, a1 ); na_exec_unary( a2, a1, funcs[a1->type] ); obj = na_shrink_rank(obj, cl_dim, rankv); xfree(rankv); return obj; } /* method: min( rank, ... ) */ static VALUE na_min(int argc, VALUE *argv, VALUE self) { return na_minmax_func(argc,argv,self,MinFuncs); } /* method: max( rank, ... ) */ static VALUE na_max(int argc, VALUE *argv, VALUE self) { return na_minmax_func(argc,argv,self,MaxFuncs); } static int na_sort_number(int argc, VALUE *argv, struct NARRAY *a1) { int i, nsort, rank; if (argc==0) { rank = a1->rank-1; } else { rank = NUM2INT(argv[0]); if (rank >= a1->rank || rank < -a1->rank) rb_raise(rb_eArgError,"illeagal rank:%i out of %i",rank,a1->rank); if (rank < 0) rank += a1->rank; } nsort = 1; for (i=0; i<=rank; ++i) nsort *= a1->shape[i]; return nsort; } /* method: sort([rank]) */ static VALUE na_sort(int argc, VALUE *argv, VALUE self) { struct NARRAY *a1, *a2; VALUE obj; int (*func)(const void*, const void*); int i, size, step, nloop, nsort; char *ptr; GetNArray(self,a1); nsort = na_sort_number(argc,argv,a1); nloop = a1->total/nsort; obj = na_make_object(a1->type,a1->rank,a1->shape,CLASS_OF(self)); GetNArray(obj,a2); memcpy(a2->ptr, a1->ptr, a1->total*na_sizeof[a1->type]); func = SortFuncs[a2->type]; size = na_sizeof[a2->type]; ptr = a2->ptr; step = size * nsort; for (i=0; itotal/nsort; func = SortFuncs[a1->type]; size = na_sizeof[a1->type]; ptr = a1->ptr; step = size * nsort; for (i=0; itotal/nsort; size = na_sizeof[a1->type]; ptr_p = ptr_ptr = ALLOC_N(char*, a1->total); ptr_a = ptr_ary = a1->ptr; for (i=a1->total; i>0; --i) { *(ptr_p++) = ptr_a; ptr_a += size; } func = SortIdxFuncs[a1->type]; ptr_p = ptr_ptr; for (i=0; irank,a1->shape,CLASS_OF(self)); GetNArray(obj,a2); ptr_p = ptr_ptr; ptr_i = (int32_t*)(a2->ptr); for (i=a2->total; i>0; --i) { *(ptr_i++) = (int32_t)(*(ptr_p++)-ptr_ary)/size; } xfree(ptr_ptr); return obj; } void Init_na_funcs(void) { rb_define_method(cNArray, "+", na_add, 1); rb_define_method(cNArray, "-", na_sbt, 1); rb_define_method(cNArray, "*", na_mul, 1); rb_define_method(cNArray, "/", na_div, 1); rb_define_method(cNArray, "%", na_mod, 1); rb_define_alias (cNArray, "mod", "%"); rb_define_method(cNArray, "&", na_bit_and, 1); rb_define_method(cNArray, "|", na_bit_or, 1); rb_define_method(cNArray, "^", na_bit_xor, 1); rb_define_method(cNArray, "**", na_power, 1); rb_define_method(cNArray, "add!", na_add_bang, 1); rb_define_method(cNArray, "sbt!", na_sbt_bang, 1); rb_define_method(cNArray, "mul!", na_mul_bang, 1); rb_define_method(cNArray, "div!", na_div_bang, 1); rb_define_method(cNArray, "mod!", na_mod_bang, 1); rb_define_method(cNArray, "imag=",na_imag_set, 1); rb_define_method(cNArray, "swap_byte", na_swap_byte, 0); rb_define_method(cNArray, "hton", na_hton, 0); rb_define_alias (cNArray, "ntoh", "hton"); rb_define_method(cNArray, "htov", na_htov, 0); rb_define_alias (cNArray, "vtoh", "htov"); rb_define_method(cNArray, "-@", na_neg, 0); rb_define_method(cNArray, "recip",na_recip, 0); rb_define_method(cNArray, "abs", na_abs, 0); rb_define_method(cNArray, "real", na_real, 0); rb_define_method(cNArray, "imag", na_imag, 0); rb_define_alias (cNArray, "image", "imag"); rb_define_method(cNArray, "angle", na_angle, 0); rb_define_alias (cNArray, "arg", "angle"); rb_define_method(cNArray, "conj", na_conj, 0); rb_define_alias (cNArray, "conjugate", "conj"); rb_define_method(cNArray, "conj!", na_conj_bang, 0); rb_define_alias (cNArray, "conjugate!", "conj!"); rb_define_method(cNArray, "im", na_imag_mul, 0); rb_define_method(cNArray, "floor",na_floor, 0); rb_define_method(cNArray, "ceil", na_ceil, 0); rb_define_method(cNArray, "round",na_round, 0); rb_define_method(cNArray, "~", na_bit_rev, 0); rb_define_method(cNArray, "not", na_not, 0); rb_define_method(cNArray, "<=>", na_compare, 1); rb_define_method(cNArray, "eq", na_equal, 1); rb_define_method(cNArray, "ne", na_not_equal, 1); rb_define_method(cNArray, "gt", na_greater_than, 1); rb_define_alias (cNArray, ">", "gt"); rb_define_method(cNArray, "ge", na_greater_equal, 1); rb_define_alias (cNArray, ">=", "ge"); rb_define_method(cNArray, "lt", na_less_than, 1); rb_define_alias (cNArray, "<", "lt"); rb_define_method(cNArray, "le", na_less_equal, 1); rb_define_alias (cNArray, "<=", "le"); rb_define_method(cNArray, "and", na_cond_and, 1); rb_define_method(cNArray, "or", na_cond_or, 1); rb_define_method(cNArray, "xor", na_cond_xor, 1); rb_define_method(cNArray, "mul_add", na_mul_add, -1); rb_define_method(cNArray, "mul_accum", na_mul_accum, -1); rb_define_method(cNArray, "sum", na_sum, -1); rb_define_method(cNArray, "accum", na_accum, -1); rb_define_method(cNArray, "prod", na_prod, -1); rb_define_method(cNArray, "min", na_min, -1); rb_define_method(cNArray, "max", na_max, -1); rb_define_method(cNArray, "cumsum!", na_cumsum_bang, 0); rb_define_method(cNArray, "cumsum", na_cumsum, 0); rb_define_method(cNArray, "cumprod!", na_cumprod_bang, 0); rb_define_method(cNArray, "cumprod", na_cumprod, 0); rb_define_method(cNArray, "sort", na_sort, -1); rb_define_method(cNArray, "sort!", na_sort_bang, -1); rb_define_method(cNArray, "sort_index", na_sort_index, -1); rb_define_method(cNArray, "transpose", na_transpose, -1); rb_define_singleton_method(cNArray,"mul",na_s_mul,2); rb_define_singleton_method(cNArray,"div",na_s_div,2); rb_define_singleton_method(cNArray,"mul_add",na_s_mul_add,-1); rb_define_module_function(rb_mNMath,"atan2",na_math_atan2,2); } narray-0.6.1.2/src/mknafunc.rb0000644000175000017500000001062712745364057015747 0ustar uwabamiuwabami$type_codes = %w(n B I L F D X C O) $data_types = %w(none u_int8_t int16_t int32_t float double scomplex dcomplex VALUE) $real_types = %w(none u_int8_t int16_t int32_t float double float double VALUE) $int_types = %w(none u_int8_t int16_t int32_t int32_t int32_t scomplex dcomplex VALUE) $comp_types = %w(none scomplex scomplex scomplex scomplex dcomplex scomplex dcomplex VALUE) $swap_types = %w(none u_int8_t na_size16_t na_size32_t na_size32_t na_size64_t na_size64_t na_size128_t VALUE) $upcast = [ [ 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 1, 2, 3, 4, 5, 6, 7, 8], [ 0, 2, 2, 3, 4, 5, 6, 7, 8], [ 0, 3, 3, 3, 4, 5, 6, 7, 8], [ 0, 4, 4, 4, 4, 5, 6, 7, 8], [ 0, 5, 5, 5, 5, 5, 7, 7, 8], [ 0, 6, 6, 6, 6, 7, 6, 7, 8], [ 0, 7, 7, 7, 7, 7, 7, 7, 8], [ 0, 8, 8, 8, 8, 8, 8, 8, 8] ] $data_obj = [ [/[O]/,/[O]/, " *p1 = rb_funcall(*p1,#id,1,*p2);"], [/[O]/,/[BIL]/," *p1 = rb_funcall(*p1,#id,1,INT2FIX(*p2));"], [/[O]/,/[FD]/, " *p1 = rb_funcall(*p1,#id,1,rb_float_new(*p2));"], [/[O]/,/[XC]/, " *p1 = rb_funcall(*p1,#id,1,rb_complex_new(p2->r,p2->i));"], [/[BIL]/,/[O]/," *p1 = NUM2INT(rb_funcall(INT2FIX(*p1),#id,1,*p2));"], [/[FD]/,/[O]/, " *p1 = NUM2DBL(rb_funcall(rb_float_new(*p1),#id,1,*p2));"], [/[XC]/,/[O]/, "VALUE v=rb_funcall(rb_complex_new(p1->r,p1->i),#id,1,*p2); p1->r = NUM2REAL(v); p1->i = NUM2IMAG(v);"] ] def mksetfuncs(name,op,id,funcs) print " /* ------------------------- #{name} --------------------------- */\n" c = $type_codes n = $type_codes.size td = $data_types tr = $real_types # Function Definition for i in 0...n for j in 0...n funcs.each do |k| if c[i]=~k[0] && c[j]=~k[1] #if i==j # f = "memcpy(p1,p1,sizeof(typed));" #else f = k[2] #end f = f. gsub(/p1->/,"((#{td[i]}*)p1)->"). gsub(/p2->/,"((#{td[j]}*)p2)->"). gsub(/\*p1/,"*(#{td[i]}*)p1"). gsub(/\*p2/,"*(#{td[j]}*)p2"). gsub(/ = /," = (#{tr[i]})"). gsub(/#id/,id). gsub(/#op/,op). gsub(/typed/,td[i]). gsub(/typef/,tr[i]) puts $func_body. gsub(/#name/,name). sub(/OPERATION/,f). gsub(/#CC/,c[i]+c[j]) end end end end # function pointer array print "\nna_setfunc_t "+name+"Funcs = {\n" m = [] for i in 0...n l = [] for j in 0...n f = true for k in funcs if c[i]=~k[0] && c[j]=~k[1] l += [name+c[i]+c[j]] f = false break end end if f l += ['TpErr'] end end m += [' { '+l.join(', ')+' }'] end print m.join(",\n")+"\n};\n" end def mkfuncs(name,t1,t2,func) print " /* ------------------------- #{name} --------------------------- */\n" c = $type_codes td = $data_types tr = $real_types for i in 0...c.size if func[i] != nil && func[i] != "copy" f = func[i]. gsub(/p1->/,"((#{t1[i]}*)p1)->"). gsub(/p2->/,"((#{t2[i]}*)p2)->"). gsub(/p3->/,"((#{t2[i]}*)p3)->"). gsub(/\*p1/,"*(#{t1[i]}*)p1"). gsub(/\*p2/,"*(#{t2[i]}*)p2"). gsub(/\*p3/,"*(#{t2[i]}*)p3"). gsub(/type1/,td[i]). gsub(/typec/,t1[i]). gsub(/typef/,tr[i]) puts $func_body. gsub(/#name/,name). sub(/OPERATION/,f). gsub(/#C/,c[i]) end end # Function Array print "\nna_func_t #{name}Funcs =\n{ " m = [] for i in 0...c.size if func[i] == nil m += ['TpErr'] elsif func[i]=='copy' m += ['Set'+c[$data_types.index(t1[i])]+c[i]] else m += [name+c[i]] end end print m.join(", ")+" };\n" end def mksortfuncs(bsname,t1,t2,func) print " /* ------------------------- #{bsname} --------------------------- */\n" c = $type_codes tf = $real_types name = bsname # Function Definition head = "static int #{name}#code(const void *p1, const void *p2)" for i in 0...c.size if func[i] != nil && func[i]=~/^\{/ f = func[i]. gsub(/p1->/,"((#{t1[i]}*)p1)->"). gsub(/p2->/,"((#{t2[i]}*)p2)->"). gsub(/\*\*p1/,"**(#{t1[i]}**)p1"). gsub(/\*\*p2/,"**(#{t2[i]}**)p2"). gsub(/\*p1/,"*(#{t1[i]}*)p1"). gsub(/\*p2/,"*(#{t2[i]}*)p2"). gsub(/typef/,tf[i]) puts( (head+f).gsub(/#code/,c[i]) ) end end # Function Array print "\nna_sortfunc_t #{name}Funcs =\n{ " m = [] for i in 0...c.size if func[i] == nil m += ['(int (*)(const void *, const void *))TpErrI'] elsif func[i]=='copy' m += ['Set'+c[i]*2] elsif !( func[i] =~ /^\{/ ) m += [func[i]] else m += [name+c[i]] end end print m.join(", ")+" };\n" end narray-0.6.1.2/src/mkmath.rb0000644000175000017500000003221212745364057015420 0ustar uwabamiuwabamirequire "mknafunc" # File name fname = "na_math.c" $> = open(fname,"w") print < #include "narray.h" #include "narray_local.h" #ifndef M_LOG2E #define M_LOG2E 1.4426950408889634074 #endif #ifndef M_LOG10E #define M_LOG10E 0.43429448190325182765 #endif VALUE rb_mNMath; static void TpErr(void) { rb_raise(rb_eTypeError,"illegal operation with this type"); } #if 0 void sincos(double x, double *s, double *c) { *s=sin(x); *c=cos(x); } #ifndef HAVE_ACOSH static double rb_log1p (const double x) { double y; y = 1+x; if (y==1) return x; else return log(y)*(x/(y-1)); } static double zero=0; static double acosh(double x) { /* acosh(x) = log(x+sqrt(x*x-1)) */ if (x>2) { return log(2*x-1/(sqrt(x*x-1)+x)); } else if (x>=1) { x-=1; return rb_log1p(x+sqrt(2*x+x*x)); } return zero/(x-x); /* x<1: NaN */ } static double asinh(double x) { double a, x2; int neg; /* asinh(x) = log(x+sqrt(x*x+1)) */ neg = x<0; if (neg) {x=-x;} x2 = x*x; if (x>2) { a = log(2*x+1/(x+sqrt(x2+1))); } else { a = rb_log1p(x+x2/(1+sqrt(x2+1))); } if (neg) {a=-a;} return a; } static double atanh(double x) { double a, x2; int neg; /* atanh(x) = 0.5*log((1+x)/(1-x)) */ neg = x<0; if (neg) {x=-x;} x2 = x*2; if (x<0.5) { a = 0.5*rb_log1p(x2+x2*x/(1-x)); } else if (x<1) { a = 0.5*rb_log1p(x2/(1-x)); } else if (x==1) { a = 1/zero; /* Infinity */ } else { return zero/(x-x); /* x>1: NaN */ } if (neg) {a=-a;} return a; } #endif #endif static void squareX(scomplex *x) { float r=x->r; x->r = r*r - x->i*x->i; x->i = 2*r*x->i; } static void squareC(dcomplex *x) { double r=x->r; x->r = r*r - x->i*x->i; x->i = 2*r*x->i; } static void mulX(scomplex *x, scomplex *y) { scomplex z=*x; x->r = z.r*y->r - z.i*y->i; x->i = z.r*y->i + z.i*y->r; } static void mulC(dcomplex *x, dcomplex *y) { dcomplex z=*x; x->r = z.r*y->r - z.i*y->i; x->i = z.r*y->i + z.i*y->r; } static void divX(scomplex *p1, scomplex *p2) { scomplex x = *p1; float a = p2->r*p2->r + p2->i*p2->i; p1->r = (x.r*p2->r + x.i*p2->i)/a; p1->i = (x.i*p2->r - x.r*p2->i)/a; } static void divC(dcomplex *p1, dcomplex *p2) { dcomplex x = *p1; double a = p2->r*p2->r + p2->i*p2->i; p1->r = (x.r*p2->r + x.i*p2->i)/a; p1->i = (x.i*p2->r - x.r*p2->i)/a; } static scomplex recipX(scomplex *z) { scomplex r; float n; if ( (z->r<0 ? -z->r:z->r) > (z->i<0 ? -z->i:z->i) ) { r.i = z->i/z->r; n = (1+r.i*r.i)*z->r; r.r = 1/n; r.i /= -n; } else { r.r = z->r/z->i; n = (1+r.r*r.r)*z->i; r.r /= n; r.i = -1/n; } return r; } static dcomplex recipC(dcomplex *z) { dcomplex r; double n; if ( (z->r<0 ? -z->r:z->r) > (z->i<0 ? -z->i:z->i) ) { r.i = z->i/z->r; n = (1+r.i*r.i)*z->r; r.r = 1/n; r.i /= -n; } else { r.r = z->r/z->i; n = (1+r.r*r.r)*z->i; r.r /= n; r.i = -1/n; } return r; } static int powInt(int x, int p) { int r=1; switch(p) { case 2: return x*x; case 3: return x*x*x; case 1: return x; case 0: return 1; } if (p<0) return 0; /* if(p>3) */ while (p) { if ( (p%2) == 1 ) r *= x; x *= x; p /= 2; } return r; } static float powFi(float x, int p) { float r=1; switch(p) { case 2: return x*x; case 3: return x*x*x; case 1: return x; case 0: return 1; } if (p<0) return 1/powFi(x,-p); /* if(p>3) */ while (p) { if ( (p%2) == 1 ) r *= x; x *= x; p /= 2; } return r; } static double powDi(double x, int p) { double r=1; switch(p) { case 2: return x*x; case 3: return x*x*x; case 1: return x; case 0: return 1; } if (p<0) return 1/powDi(x,-p); /* if(p>3) */ while (p) { if ( (p%2) == 1 ) r *= x; x *= x; p /= 2; } return r; } static scomplex powXi(scomplex *x, int p) { scomplex y=*x, r={1,0}; if (p==2) { squareX(&y); return y; } if (p==1) { return y; } if (p==0) { return r; } if (p<0) { y = powXi(x,-p); return recipX(&y); } /* if (p>2) */ while (p) { if ( (p%2) == 1 ) mulX(&r,&y); squareX(&y); p /= 2; } return r; } static dcomplex powCi(dcomplex *x, int p) { dcomplex y=*x, r={1,0}; if (p==2) { squareC(&y); return y; } if (p==1) { return y; } if (p==0) { return r; } if (p<0) { y = powCi(x,-p); return recipC(&y); } /* if (p>2) */ while (p) { if ( (p%2) == 1 ) mulC(&r,&y); squareC(&y); p /= 2; } return r; } EOM data = [ ['sqrt', [nil]*4 + ["{ *p1 = sqrt(*p2); }"]*2 + ["{ typer xr=p2->r/2, xi=p2->i/2, r=hypot(xr,xi); if (xr>0) { p1->r = sqrt(r+xr); p1->i = xi/p1->r; } else if ( (r-=xr) ) { p1->i = (xi>=0) ? sqrt(r):-sqrt(r); p1->r = xi/p1->i; } else { p1->r = p1->i = 0; } }"]*2 + [nil] ], ['sin', [nil]*4 + ["{ *p1 = sin(*p2); }"]*2 + ["{ p1->r = sin(p2->r)*cosh(p2->i); p1->i = cos(p2->r)*sinh(p2->i); }"]*2 + [nil] ], ['cos', [nil]*4 + ["{ *p1 = cos(*p2); }"]*2 + ["{ p1->r = cos(p2->r)*cosh(p2->i); p1->i = -sin(p2->r)*sinh(p2->i); }"]*2 + [nil] ], ['tan', [nil]*4 + ["{ *p1 = tan(*p2); }"]*2 + ["{ typer d, th; p1->i = th = tanh(2*p2->i); p1->r = sqrt(1-th*th); /* sech */ d = 1 + cos(2*p2->r) * p1->r; p1->r *= sin(2*p2->r)/d; p1->i /= d; }"]*2 + [nil] ], ['sinh', [nil]*4 + ["{ *p1 = sinh(*p2); }"]*2 + ["{ p1->r = sinh(p2->r)*cos(p2->i); p1->i = cosh(p2->r)*sin(p2->i); }"]*2 + [nil] ], ['cosh', [nil]*4 + ["{ *p1 = cosh(*p2); }"]*2 + ["{ p1->r = cosh(p2->r)*cos(p2->i); p1->i = sinh(p2->r)*sin(p2->i); }"]*2 + [nil] ], ['tanh', [nil]*4 + ["{ *p1 = tanh(*p2); }"]*2 + ["{ typer d, th; p1->r = th = tanh(2*p2->r); p1->i = sqrt(1-th*th); /* sech */ d = 1 + cos(2*p2->i) * p1->i; p1->r /= d; p1->i *= sin(2*p2->i)/d; }"]*2 + [nil] ], ['exp', [nil]*4 + ["{ *p1 = exp(*p2); }"]*2 + ["{ typer a = exp(p2->r); p1->r = a*cos(p2->i); p1->i = a*sin(p2->i); }"]*2 + [nil] ], ['log', [nil]*4 + ["{ *p1 = log(*p2); }"]*2 + ["{ typed x = *p2; p1->r = log(hypot(x.r, x.i)); p1->i = atan2(x.i, x.r); }"]*2 + [nil] ], ['log10', [nil]*4 + ["{ *p1 = log10(*p2); }"]*2 + ["{ log#code(p1,p2); p1->r *= (typer)M_LOG10E; p1->i *= (typer)M_LOG10E; }"]*2 + [nil] ], ['log2', [nil]*4 + ["{ *p1 = log(*p2)*M_LOG2E; }"]*2 + ["{ log#code(p1,p2); p1->r *= (typer)M_LOG2E; p1->i *= (typer)M_LOG2E; }"]*2 + [nil] ], ['asin', [nil]*4 + ["{ *p1 = asin(*p2); }"]*2 + # -i * log( sqrt(1-x**2) + x*i ) ["{ typed x = *p2; square#code(&x); x.r = 1 - x.r; x.i = - x.i; sqrt#code(&x,&x); x.r -= p2->i; x.i += p2->r; log#code(&x,&x); p1->r = x.i; p1->i = -x.r; }"]*2 + [nil]*1 ], ['asinh', [nil]*4 + ["{ *p1 = asinh(*p2); }"]*2 + # log(sqrt(x**2+1)+x) ["{ typed x = *p2; square#code(&x); x.r += 1; sqrt#code(&x,&x); x.r += p2->r; x.i += p2->i; log#code(p1,&x); }"]*2 + [nil]*1 ], ['acos', [nil]*4 + ["{ *p1 = acos(*p2); }"]*2 + # -i * log( sqrt(1-x**2)*i + x ) ["{ typed x = *p2; typer tmp; square#code(&x); x.r = 1 - x.r; x.i = - x.i; sqrt#code(&x,&x); tmp = x.r + p2->i; x.r = -x.i + p2->r; x.i = tmp; log#code(&x,&x); p1->r = x.i; p1->i = -x.r; }"]*2 + [nil]*1 ], ['acosh', [nil]*4 + ["{ *p1 = acosh(*p2); }"]*2 + # log(x+sqrt(x**2-1)) ["{ typed x = *p2; square#code(&x); x.r -= 1; sqrt#code(&x,&x); x.r += p2->r; x.i += p2->i; log#code(p1,&x); }"]*2 + [nil]*1 ], ['atan', [nil]*4 + ["{ *p1 = atan(*p2); }"]*2 + # i/2 * log((i+x)/(i-x)) ["{ typed x,y; x.r=-p2->r; x.i=1-p2->i; y.r= p2->r; y.i=1+p2->i; div#code((void*)&y,(void*)&x); log#code((void*)&x,(void*)&y); p1->r = -x.i/2; p1->i = x.r/2; }"]*2 + [nil]*1 ], ['atanh', [nil]*4 + ["{ *p1 = atanh(*p2); }"]*2 + # 1/2 * log((1+x)/(1-x)) ["{ typed x,y; x.r=1-p2->r; x.i=-p2->i; y.r=1+p2->r; y.i= p2->i; div#code((void*)&y,(void*)&x); log#code((void*)&x,(void*)&y); p1->r = x.r/2; p1->i = x.i/2; }"]*2 + [nil]*1 ] ] def mkmathfuncs(bsname,func) print " /* ------------------------- #{bsname} --------------------------- */\n" c = $type_codes tr = $real_types td = $data_types name = bsname # Function Definition head = "static void #{name}#code(void *p1, void *p2)" for i in 0...c.size if func[i] != nil && func[i]=~/^\{/ f = func[i]. gsub(/p1->/,"((#{td[i]}*)p1)->"). gsub(/p2->/,"((#{td[i]}*)p2)->"). gsub(/\*p1/,"*(#{td[i]}*)p1"). gsub(/\*p2/,"*(#{td[i]}*)p2"). gsub(/typer/, tr[i]). gsub(/typed/, td[i]) puts( (head+f).gsub(/#code/,c[i]) ) end end # Function Array print "\nna_mathfunc_t #{name}Funcs =\n{ " m = [] for i in 0...c.size if func[i] == nil m += ['TpErr'] elsif func[i]=='copy' m += ['Set'+c[i]*2] elsif !( func[i] =~ /^\{/ ) m += [func[i]] else m += [name+c[i]] end end print m.join(", ")+" };\n" end # Function Definitions for i in data mkmathfuncs( i[0], i[1] ) end # # Recip # $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; } } " mkfuncs('Rcp', $data_types, $data_types, [nil] + ["*p1 = 1/(*p2);"]*5 + ["*p1 = recip#C((type1*)p2);"]*2 + ["*p1 = rb_funcall(INT2FIX(1),na_id_div,1,*p2);"] ) # # Power # def mkpowfuncs(name,funcs) print " /* ------------------------- #{name} --------------------------- */\n" c = $type_codes n = $type_codes.size td = $data_types tr = $real_types # Function Definition for i in 0...n for j in 0...n funcs.each do |k| if c[i]=~k[0] && c[j]=~k[1] tu = $data_types[$upcast[i][j]] f = k[2]. gsub(/p1->/,"((#{tu}*)p1)->"). gsub(/p2->/,"((#{td[i]}*)p2)->"). gsub(/p3->/,"((#{td[j]}*)p3)->"). gsub(/\*p1/,"*(#{tu}*)p1"). gsub(/\*p2/,"*(#{td[i]}*)p2"). gsub(/\*p3/,"*(#{td[j]}*)p3"). gsub(/typed/,td[i]). gsub(/typef/,tr[i]) puts $func_body. gsub(/#name/,name). sub(/OPERATION/,f). gsub(/#CC/,c[i]+c[j]). gsub(/#C/, c[i]) end end end end # function pointer array print "\nna_setfunc_t "+name+"Funcs = {\n" m = [] for i in 0...n l = [] for j in 0...n f = true for k in funcs if c[i]=~k[0] && c[j]=~k[1] l += [name+c[i]+c[j]] f = false break end end if f l += ['TpErr'] end end m += [' { '+l.join(', ')+' }'] end print m.join(",\n")+"\n};\n" end $func_body = "static void #name#CC(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; p3+=i3; } } " mkpowfuncs('Pow', [ [/[O]/,/[O]/, "*p1 = rb_funcall(*p2,na_id_power,1,*p3);"], [/[BIL]/,/[BIL]/, "*p1 = powInt(*p2,*p3);"], [/[FD]/,/[BIL]/, "*p1 = pow#Ci(*p2,*p3);"], [/[BILFD]/,/[FD]/,"*p1 = pow(*p2,*p3);"], [/[XC]/,/[BIL]/, "*p1 = pow#Ci((typed*)p2,*p3);"], [/[XC]/,/[FD]/, "typed r; if (*p3==0) { p1->r=1; p1->i=0; } else if (p2->r==0 && p2->i==0 && *p3>0) { p1->r=0; p1->i=0; } else { log#C(&r, p2); r.r *= *p3; r.i *= *p3; exp#C(p1, &r); }"], [/[XC]/,/[XC]/, "typed l, r; if (p3->r==0 && p3->i==0) { p1->r=1; p1->i=0; } else if (p2->r==0 && p2->i==0 && p3->r>0 && p3->i==0) { p1->r=0; p1->i=0; } else { log#C(&l, p2); r.r = p3->r * l.r - p3->i * l.i; r.i = p3->r * l.i + p3->i * l.r; exp#C(p1, &r); }"] ]) # Execution print <type]; s2 = na_sizeof[a2->type]; p1 = a1->ptr; p2 = a2->ptr; for (i=a1->total; i ; i--) { (*func)( p1, p2 ); p1 += s1; p2 += s2; } } static VALUE na_math_func(volatile VALUE self, na_mathfunc_t funcs) { struct NARRAY *a1, *a2; VALUE ans; if (TYPE(self) == T_ARRAY) { self = na_ary_to_nary(self,cNArray); } else if (!IsNArray(self)) { self = na_make_scalar(self,na_object_type(self)); } GetNArray(self,a2); if (NA_IsINTEGER(a2)) { self = na_upcast_type(self,NA_DFLOAT); GetNArray(self,a2); } ans = na_make_object(a2->type, a2->rank, a2->shape, CLASS_OF(self)); GetNArray(ans,a1); na_exec_math(a1, a2, funcs[a2->type]); if (CLASS_OF(self) == cNArrayScalar) SetFuncs[NA_ROBJ][a1->type](1,&ans,0,a1->ptr,0); return ans; } EOM # Module Methods print < narray */ static VALUE na_math_#{bsname}(VALUE obj, VALUE x) { return na_math_func(x,#{name}Funcs); } EOM end # Initializer print <. The original copyright notice follows. A C-program for MT19937, with initialization improved 2002/2/10. Coded by Takuji Nishimura and Makoto Matsumoto. This is a faster version by taking Shawn Cokus's optimization, Matthe Bellew's simplification, Isaku Wada's real version. Before using, initialize the state by using init_genrand(seed) or init_by_array(init_key, key_length). Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.keio.ac.jp/matumoto/emt.html email: matumoto@math.keio.ac.jp */ #include "ruby.h" #include "narray.h" #include "narray_local.h" /* Period parameters */ #define N 624 #define M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UMASK 0x80000000UL /* most significant w-r bits */ #define LMASK 0x7fffffffUL /* least significant r bits */ #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) static u_int32_t state[N]; /* the array for the state vector */ static int left = 1; static int initf = 0; static u_int32_t *next; /* initializes state[N] with a seed */ static void init_genrand(u_int32_t s) { int j; state[0]= s & 0xffffffffUL; for (j=1; j> 30)) + j); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array state[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ state[j] &= 0xffffffffUL; /* for >32 bit machines */ } left = 1; initf = 1; } static void next_state() { u_int32_t *p=state; int j; /* if init_genrand() has not been called, */ /* a default initial seed is used */ if (initf==0) init_genrand(5489UL); left = N; next = state; for (j=N-M+1; --j; ++p) *p = p[M] ^ TWIST(p[0], p[1]); for (j=M; --j; ++p) *p = p[M-N] ^ TWIST(p[0], p[1]); *p = p[M-N] ^ TWIST(p[0], state[0]); } #undef N #undef M /* These real versions are due to Isaku Wada, 2002/01/09 added */ #ifdef HAVE_UNISTD_H #include #endif #include #ifdef HAVE_SYS_TIME_H #include #endif static int first = 1; static int rand_init(seed) u_int32_t seed; { static u_int32_t saved_seed; u_int32_t old; first = 0; init_genrand(seed); old = saved_seed; saved_seed = seed; return old; } static u_int32_t random_seed() { static int n = 0; struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++; } static VALUE na_s_srand(int argc, VALUE *argv, VALUE obj) { VALUE sd; u_int32_t seed, old; //rb_secure(4); if (rb_scan_args(argc, argv, "01", &sd) == 0) { seed = random_seed(); } else { seed = NUM2ULONG(sd); } old = rand_init(seed); return ULONG2NUM(old); } /* - end of the code from ruby/random.c - */ #define genrand(y) \ { if (--left == 0) next_state();\ (y) = *next++;\ (y) ^= ((y) >> 11);\ (y) ^= ((y) << 7) & 0x9d2c5680UL;\ (y) ^= ((y) << 15) & 0xefc60000UL;\ (y) ^= ((y) >> 18); } #define rand_double(x,y) \ (((double)((x)>>5)+(double)((y)>>6)*(1.0/67108864.0)) * (1.0/134217728.0)) #define rand_single(y) \ ((double)(y) * (1.0/4294967296.0)) static int n_bits(int32_t a) { int i, x, xu, xl, n=4; int32_t m; if (a==0) return 0; if (a<0) a=-a; x = 1<=0; --i) { m = ~((1<<(x-1))-1); if (m & a) { xl = x; x += 1<<(i-1); } else { xu = x; x -= 1<<(i-1); } /* printf("%3i, [%3i, %3i], %x\n", i, xu, xl, m1); */ } /* if (xu-xl!=1) printf("*** erorr %d - %d != 1\n", xu, xl); */ return xl; } // max&limit must be integer static u_int32_t size_check(double rmax, double limit) { u_int32_t max; if ( rmax == 0 ) { return (u_int32_t)(limit-1); } if ( rmax < 0 ) { rmax = -rmax; } max = (u_int32_t)(rmax - 1); if ( max >= limit ) { rb_raise(rb_eArgError, "rand-max(%.0f) must be <= %.0f", rmax, limit); } return max; } static void TpErr(void) { rb_raise(rb_eTypeError,"illegal operation with this type"); } static void RndB(int n, char *p1, int i1, double rmax) { u_int32_t y; u_int8_t max; int shift; if ( rmax < 0 ) { rb_raise(rb_eArgError, "rand-max must be positive"); } max = size_check(rmax,0x100); shift = 32 - n_bits(max); if (max<1) { for (; n; --n) { *(u_int8_t*)p1 = 0; p1+=i1; } } else { for (; n; --n) { do { genrand(y); y >>= shift; } while (y > max); *(u_int8_t*)p1 = (u_int8_t)y; p1+=i1; } } } static void RndI(int n, char *p1, int i1, double rmax) { u_int32_t y; u_int32_t max; int shift, sign=1; if ( rmax < 0 ) { rmax = -rmax; sign = -1; } max = size_check(rmax,0x8000); shift = 32 - n_bits(max); if (max<1) { for (; n; --n) { *(int16_t*)p1 = 0; p1+=i1; } } else { for (; n; --n) { do { genrand(y); y >>= shift; } while (y > max); *(int16_t*)p1 = (int16_t)y*sign; p1+=i1; } } } static void RndL(int n, char *p1, int i1, double rmax) { u_int32_t y; u_int32_t max; int shift, sign=1; if ( rmax < 0 ) { rmax = -rmax; sign = -1; } max = size_check(rmax,0x80000000); shift = 32 - n_bits(max); if (max<1) { for (; n; --n) { *(int32_t*)p1 = 0; p1+=i1; } } else { for (; n; --n) { do { genrand(y); y >>= shift; } while (y > max); *(int32_t*)p1 = (int32_t)y*sign; p1+=i1; } } } static void RndF(int n, char *p1, int i1, double rmax) { u_int32_t y; for (; n; --n) { genrand(y); *(float*)p1 = rand_single(y) * rmax; p1+=i1; } } static void RndD(int n, char *p1, int i1, double rmax) { u_int32_t x,y; for (; n; --n) { genrand(x); genrand(y); *(double*)p1 = rand_double(x,y) * rmax; p1+=i1; } } static void RndX(int n, char *p1, int i1, double rmax) { u_int32_t y; for (; n; --n) { genrand(y); ((scomplex*)p1)->r = rand_single(y) * rmax; ((scomplex*)p1)->i = 0; p1+=i1; } } static void RndC(int n, char *p1, int i1, double rmax) { u_int32_t x,y; for (; n; --n) { genrand(x); genrand(y); ((dcomplex*)p1)->r = rand_double(x,y) * rmax; ((dcomplex*)p1)->i = 0; p1+=i1; } } na_func_t RndFuncs = { TpErr, RndB, RndI, RndL, RndF, RndD, RndX, RndC, TpErr }; static VALUE na_random_bang(int argc, VALUE *argv, VALUE self) { VALUE vmax; struct NARRAY *ary; double rmax; rb_scan_args(argc, argv, "01", &vmax); if (first) { rand_init(random_seed()); } if (NIL_P(vmax)) { rmax = 1; } else { rmax = NUM2DBL(vmax); } if (isinf(rmax) || isnan(rmax)) { rb_raise(rb_eArgError, "rand-max must be regular value"); } GetNArray(self,ary); (*RndFuncs[ary->type])( ary->total, ary->ptr, na_sizeof[ary->type], rmax ); return self; } static VALUE na_random(int argc, VALUE *argv, VALUE self) { return na_random_bang(argc, argv, na_clone(self)); } void Init_na_random() { rb_define_singleton_method(cNArray,"srand",na_s_srand,-1); rb_define_method(cNArray, "random!", na_random_bang,-1); rb_define_method(cNArray, "random", na_random,-1); } narray-0.6.1.2/src/narray_local.h0000644000175000017500000001323212745364057016432 0ustar uwabamiuwabami/* narray_local.h Numerical Array Extention for Ruby (C) Copyright 1999-2008 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ typedef int32_t na_index_t; struct slice { char *p; /* pointer to data --- used in loop */ int n; /* n of indices of this rank */ int pstep; /* = step * stride * elmsz --- set in na_init_slice */ int pbeg; /* = beg * stride * elmsz --- set in na_init_slice */ int stride; /* = shape[0]*shape[1]*...*shape[r-1] --- set in na_init_slice */ int step; int beg; na_index_t *idx; /* NULL if normal step */ }; typedef void (*na_setfunc_t[NA_NTYPES][NA_NTYPES]) (); typedef void (*na_func_t[NA_NTYPES]) (); typedef void (*na_ufunc_t[NA_NTYPES]) (); typedef void (*na_bifunc_t[NA_NTYPES]) (); typedef void (*na_mathfunc_t[NA_NTYPES]) (); typedef int (*na_sortfunc_t[NA_NTYPES]) (const void *, const void *); /* function arrays */ extern na_setfunc_t SetFuncs; extern na_ufunc_t SwpFuncs; extern na_ufunc_t H2NFuncs; extern na_ufunc_t H2VFuncs; extern na_ufunc_t NegFuncs; extern na_ufunc_t RcpFuncs; extern na_ufunc_t AbsFuncs; extern na_ufunc_t RealFuncs; extern na_ufunc_t ImagFuncs; extern na_ufunc_t AnglFuncs; extern na_ufunc_t ImagMulFuncs; extern na_ufunc_t ConjFuncs; extern na_ufunc_t FloorFuncs; extern na_ufunc_t CeilFuncs; extern na_ufunc_t RoundFuncs; extern na_ufunc_t ToStrFuncs; extern na_ufunc_t InspFuncs; extern na_ufunc_t IndGenFuncs; extern na_ufunc_t AddUFuncs; extern na_ufunc_t SbtUFuncs; extern na_ufunc_t MulUFuncs; extern na_ufunc_t DivUFuncs; extern na_ufunc_t ModUFuncs; extern na_bifunc_t AddBFuncs; extern na_bifunc_t SbtBFuncs; extern na_bifunc_t MulBFuncs; extern na_bifunc_t DivBFuncs; extern na_bifunc_t MulAddFuncs; extern na_bifunc_t MulSbtFuncs; extern na_bifunc_t ModBFuncs; extern na_bifunc_t BAnFuncs; extern na_bifunc_t BOrFuncs; extern na_bifunc_t BXoFuncs; extern na_ufunc_t BRvFuncs; extern na_bifunc_t ImgSetFuncs; extern na_setfunc_t PowFuncs; extern na_bifunc_t atan2Funcs; extern na_bifunc_t CmpFuncs; extern na_bifunc_t EqlFuncs; extern na_ufunc_t AndFuncs; extern na_ufunc_t Or_Funcs; extern na_ufunc_t XorFuncs; extern na_ufunc_t NotFuncs; extern na_ufunc_t MinFuncs; extern na_ufunc_t MaxFuncs; extern na_sortfunc_t SortFuncs; extern na_sortfunc_t SortIdxFuncs; extern na_bifunc_t RefMaskFuncs; extern na_bifunc_t SetMaskFuncs; /* variables */ extern VALUE rb_mNMath; extern ID na_id_beg, na_id_end, na_id_exclude_end; extern ID na_id_minus, na_id_abs, na_id_power; extern ID na_id_compare, na_id_and, na_id_or; extern ID na_id_equal; extern ID na_id_class_dim; extern ID na_id_add, na_id_sbt, na_id_mul, na_id_div, na_id_mod; extern ID na_id_real, na_id_imag; extern ID na_id_coerce_rev; extern ID na_id_new; extern ID na_id_Complex; extern const int na_upcast[NA_NTYPES][NA_NTYPES]; extern const int na_no_cast[NA_NTYPES]; extern const int na_cast_real[NA_NTYPES]; extern const int na_cast_comp[NA_NTYPES]; extern const int na_cast_round[NA_NTYPES]; extern const int na_cast_byte[NA_NTYPES]; extern const char *na_typestring[]; extern VALUE cNArrayScalar, cComplex; /* narray.c */ VALUE na_newdim_ref(int argc, VALUE *argv, VALUE self); /* na_func.c */ int na_max3(int a, int b, int c); void na_shape_max3(int ndim, int *max_shp, int *shp1, int *shp2, int *shp3); void na_shape_copy( int ndim, int *shape, struct NARRAY *a ); void na_init_slice(struct slice *s, int rank, int *shape, int elmsz); void na_set_slice_1obj(int ndim, struct slice *slc, int *shape); int na_set_slice_3obj( int ndim, struct slice *s1, struct slice *s2, struct slice *s3, int *shp1, int *shp2, int *shp3, int *shape ); void na_loop_general(struct NARRAY *a1, struct NARRAY *a2, struct slice *s1, struct slice *s2, void (*func)()); void na_loop_index_ref(struct NARRAY *a1, struct NARRAY *a2, struct slice *s1, struct slice *s2, void (*func)()); /* na_index.c */ void na_aset_slice(struct NARRAY *dst, struct NARRAY *src, struct slice *s1); int na_shrink_class(int class_dim, int *shrink); VALUE na_shrink_rank(VALUE obj, int class_dim, int *shrink); #define rb_complex_new(r,i) \ rb_funcall(rb_mKernel, na_id_Complex, 2, rb_float_new(r), rb_float_new(i)) typedef union { u_int8_t b[2]; int16_t s; } na_size16_t; typedef union { u_int8_t b[4]; int32_t i; float f; } na_size32_t; typedef union { u_int8_t b[8]; float f[2]; double d; } na_size64_t; typedef union { u_int8_t b[16]; double d[2]; } na_size128_t; #define swap16(d,s) \ (d).b[0]=(s).b[1];\ (d).b[1]=(s).b[0]; #define swap32(d,s) \ (d).b[0]=(s).b[3];\ (d).b[1]=(s).b[2];\ (d).b[2]=(s).b[1];\ (d).b[3]=(s).b[0]; #define swap64(d,s) \ (d).b[0]=(s).b[7];\ (d).b[1]=(s).b[6];\ (d).b[2]=(s).b[5];\ (d).b[3]=(s).b[4];\ (d).b[4]=(s).b[3];\ (d).b[5]=(s).b[2];\ (d).b[6]=(s).b[1];\ (d).b[7]=(s).b[0]; #define swap64c(d,s) \ (d).b[0]=(s).b[3];\ (d).b[1]=(s).b[2];\ (d).b[2]=(s).b[1];\ (d).b[3]=(s).b[0];\ (d).b[4]=(s).b[7];\ (d).b[5]=(s).b[6];\ (d).b[6]=(s).b[5];\ (d).b[7]=(s).b[4]; #define swap128c(d,s) \ (d).b[0]=(s).b[7];\ (d).b[1]=(s).b[6];\ (d).b[2]=(s).b[5];\ (d).b[3]=(s).b[4];\ (d).b[4]=(s).b[3];\ (d).b[5]=(s).b[2];\ (d).b[6]=(s).b[1];\ (d).b[7]=(s).b[0];\ (d).b[8]=(s).b[15];\ (d).b[9]=(s).b[14];\ (d).b[10]=(s).b[13];\ (d).b[11]=(s).b[12];\ (d).b[12]=(s).b[11];\ (d).b[13]=(s).b[10];\ (d).b[14]=(s).b[9];\ (d).b[15]=(s).b[8]; #if !defined RSTRING_LEN #define RSTRING_LEN(a) RSTRING(a)->len #endif #if !defined RSTRING_PTR #define RSTRING_PTR(a) RSTRING(a)->ptr #endif #if !defined RARRAY_LEN #define RARRAY_LEN(a) RARRAY(a)->len #endif #if !defined RARRAY_PTR #define RARRAY_PTR(a) RARRAY(a)->ptr #endif narray-0.6.1.2/src/na_index.c0000644000175000017500000005531112745364057015550 0ustar uwabamiuwabami/* na_index.c Numerical Array Extention for Ruby (C) Copyright 1999-2008 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ #include #include "narray.h" #include "narray_local.h" #define EXCL(r) (RTEST(rb_funcall((r),na_id_exclude_end,0))) static int na_index_range(VALUE obj, int size, struct slice *sl) { int beg,end,len,step; VALUE vbeg, vend; sl->idx = NULL; /* Beginning */ vbeg = rb_funcall(obj, na_id_beg, 0); if (vbeg==Qnil) /* First is nil */ beg = 0; else beg = NUM2INT(vbeg); if (beg<0) beg += size; /* End */ vend = rb_funcall(obj, na_id_end, 0); if (vend==Qnil) { /* Last is nil */ sl->beg = beg; sl->step = 1; return sl->n = 0; } else end = NUM2INT(vend); if (end<0) end += size; /* length */ len = end-beg; /* direction */ if (len>0) { step = 1; if (EXCL(obj)) --end; else ++len; } else if (len<0) { len = -len; step = -1; if (EXCL(obj)) ++end; else ++len; } else /*if(len==0)*/ { if (EXCL(obj)) rb_raise(rb_eIndexError, "empty range"); else { ++len; step = 1; /* or 0 ? depend on whether removing rank */ } } if ( beg<0 || beg>=size || end<0 || end>=size ) rb_raise(rb_eIndexError, "index out of range"); sl->n = len; sl->beg = beg; sl->step = step; return len; } static int na_index_scalar(int idx, int size, struct slice *sl) { if (idx<0) idx+=size; if (idx<0 || idx>=size) rb_raise(rb_eIndexError, "index out of range"); sl->n = 1; sl->beg = idx; sl->step = 0; sl->idx = NULL; return 1; } static int na_ary_to_index(struct NARRAY *a1, int size, struct slice *s) { int i; na_index_t idx, *p; /* Empty Array */ if (a1->total==0) { s->n = 0; s->beg = 0; s->step = 1; s->idx = NULL; } else /* single element */ if (a1->total==1) { SetFuncs[NA_LINT][a1->type](1, &idx, 0, a1->ptr, 0); if ( idx<0 ) idx += size; if ( idx<0 || idx>=size ) rb_raise(rb_eIndexError, "index %i out of range %i", idx, size); s->n = 1; s->beg = idx; s->step = 1; s->idx = NULL; } else { /* Copy index array */ s->n = a1->total; s->step = 1; s->idx = p = ALLOC_N(na_index_t, a1->total); SetFuncs[NA_LINT][a1->type]( s->n, s->idx, na_sizeof[NA_LINT], a1->ptr, na_sizeof[a1->type] ); for ( i=a1->total; i>0; --i ) { if ( *p<0 ) *p += size; if ( *p<0 || *p>=size ) rb_raise(rb_eIndexError, "index %i out of range %i", *p, size); ++p; } s->beg = s->idx[0]; } return s->n; } static struct NARRAY * na_flatten_temporarily(struct NARRAY *dst, struct NARRAY *src) { /* Not normal construction !! Do not wrap as object ! */ dst->shape = &(dst->total); dst->rank = 1; dst->total = src->total; dst->type = src->type; dst->ptr = src->ptr; dst->ref = src->ref; return dst; } #define na_flatten_temp(ary) \ {ary = na_flatten_temporarily(ALLOCA_N(struct NARRAY,1), ary);} /* free index memory */ static void na_free_slice_index(struct slice *s, int n) { while (n-->0) if (s[n].idx != NULL) xfree(s[n].idx); } static int na_index_test(volatile VALUE idx, int shape, struct slice *sl) { int size; struct NARRAY *na; switch(TYPE(idx)) { case T_FIXNUM: /* scalar slice */ na_index_scalar(FIX2LONG(idx),shape,sl); return 1; case T_FLOAT: /* scalar slice */ na_index_scalar(NUM2LONG(idx),shape,sl); return 1; case T_NIL: case T_TRUE: /* entire slice */ sl->n = shape; sl->beg = 0; sl->step = 1; sl->idx = NULL; return shape; case T_ARRAY: /* Array Index */ idx = na_cast_object(idx,NA_LINT); GetNArray(idx,na); size = na_ary_to_index(na,shape,sl); return size; default: /* Range object */ if (rb_obj_is_kind_of(idx, rb_cRange)) { size = na_index_range(idx,shape,sl); } else /* NArray index */ if (NA_IsNArray(idx)) { GetNArray(idx,na); size = na_ary_to_index(na,shape,sl); } else /* NO ALLOWED */ if (TYPE(idx)==T_BIGNUM) { rb_raise(rb_eIndexError, "BigNum is not allowed"); } else rb_raise(rb_eIndexError, "not allowed type"); } return size; } static int na_index_analysis(int nidx, VALUE *idx, struct NARRAY *ary, struct slice *sl) { int i, j, k, total=1, size; int multi_ellip=0; for (i=j=0; irank-nidx+1; k>0; --k,++j) { size = na_index_test( Qtrue, ary->shape[j], &sl[j] ); if (size != 1) total *= size; } multi_ellip = 1; } else { if (j < ary->rank) { size = na_index_test( idx[i], ary->shape[j], &sl[j] ); if (size != 1) total *= size; } ++j; } } if (j != ary->rank) rb_raise(rb_eIndexError, "# of index=%i != ary.dim=%i", j, ary->rank); return total; } /* -------------------- Class Dimension -------------------- */ int na_shrink_class(int class_dim, int *shrink) { int i; for (i=0; irank < class_dim) return obj; for (j=i=0; ishape[i]!=1 || shrink[i]==0) /* not trim */ ++j; } if (j>0) /* if non-trim dimensions exist, */ j = class_dim; /* then do not trim class_dimension. */ /* if (j==0) then all trim. */ for (i=class_dim; irank; ++i) { if (ary->shape[i]!=1 || shrink[i]==0) { /* not trim */ if (i>j) ary->shape[j] = ary->shape[i]; ++j; } } ary->rank = j; if (j==0 && ary->total==1) { SetFuncs[NA_ROBJ][ary->type](1, &obj, 0, ary->ptr, 0); } return obj; } /* ------------------- bracket methods ------------------ */ /* [] -- Reference method */ static VALUE na_aref_slice(struct NARRAY *a2, struct slice *s2, VALUE klass, int flag) { int i, ndim, class_dim, *shape, *shrink; VALUE extr; struct NARRAY *a1; struct slice *s1; ndim = a2->rank; shape = ALLOCA_N(int,ndim); shrink = ALLOCA_N(int,ndim); for (i=0; i0 && na_shrink_class(class_dim,shrink)) klass = cNArray; extr = na_make_object( a2->type, ndim, shape, klass ); GetNArray(extr,a1); s1 = ALLOC_N(struct slice, ndim+1); na_set_slice_1obj(ndim,s1,a1->shape); na_init_slice( s1, ndim, shape, na_sizeof[a2->type] ); na_init_slice( s2, ndim, a2->shape, na_sizeof[a2->type] ); na_loop_index_ref( a1, a2, s1, s2, SetFuncs[a2->type][a2->type] ); xfree(s1); if (!flag) extr = na_shrink_rank(extr,class_dim,shrink); return extr; } static VALUE na_aref_single_dim_array(VALUE self, volatile VALUE vidx) { int total; struct NARRAY *a1, *a2, *aidx; struct slice *s1, *s2; VALUE v; GetNArray( self, a1 ); vidx = na_cast_object( vidx, NA_LINT ); GetNArray(vidx,aidx); /* make Slice from index */ s1 = ALLOCA_N(struct slice, 2); total = na_ary_to_index( aidx, a1->total, s1 ); if (total==0) { return na_make_empty(a1->type,cNArray); } else { /* create New NArray & 1-dimentionize */ v = na_make_object( a1->type, aidx->rank, aidx->shape, CLASS_OF(vidx) ); GetNArray(v,a2); if (a2->rank>1) na_flatten_temp(a2); if (a1->rank>1) na_flatten_temp(a1); /* Slice for Destination array */ s2 = ALLOCA_N(struct slice, 2); na_set_slice_1obj(1,s2,a2->shape); /* Iteration */ na_init_slice( s2, 1, a2->shape, na_sizeof[a1->type] ); na_init_slice( s1, 1, a1->shape, na_sizeof[a1->type] ); na_loop_index_ref( a2, a1, s2, s1, SetFuncs[a1->type][a1->type] ); } na_free_slice_index(s1,1); return v; } static VALUE na_aref_single_dim(VALUE self, VALUE idx, int flag) { int size; VALUE v; struct NARRAY *ary, *arynew; struct slice *sl; GetNArray(self,ary); sl = ALLOCA_N(struct slice, 2); size = na_index_test(idx, ary->total, sl); if ( size == 1 ) { if (flag || sl->step!=0) { /* single-element NArray */ v = na_make_object(ary->type,1,&size,cNArray); GetNArray(v,arynew); SetFuncs[ary->type][ary->type](1, arynew->ptr,0, NA_PTR(ary,sl->beg),0); } else { SetFuncs[NA_ROBJ][ary->type](1, &v,0, NA_PTR(ary,sl->beg),0); } } else if ( size > 1 ) { if ( ary->rank > 1 ) /* 1-dimensional serial index */ na_flatten_temp(ary); v = na_aref_slice(ary, sl, CLASS_OF(self), flag); } else /* size < 1 */ { v = na_make_empty(ary->type,cNArray); } /* na_free_slice_index(sl,1); free index memory */ return v; } static VALUE na_aref_multi_dim_single_elm(VALUE self, struct slice *sl, int flag) { int i, rank, pos, *shape; struct NARRAY *ary, *arynew; VALUE v; ary = (struct NARRAY *)DATA_PTR(self); /* type is already checked */ /* check rank-shrink; whether return NArray or Element */ if (flag==0) { rank = 0; /* [] */ for ( i=ary->rank; (i--)>0; ) { if (sl[i].step!=0) ++rank; } } else { rank = ary->rank; /* slice() */ } /* get position */ pos = 0; for ( i=ary->rank; i-->0; ) { pos = pos * ary->shape[i] + sl[i].beg; } if (rank==0) { SetFuncs[NA_ROBJ][ary->type](1, &v, 0, NA_PTR(ary,pos), 0); } else { VALUE klass; int class_dim; klass = CLASS_OF(self); class_dim = na_class_dim(klass); if (rank < class_dim) rank = class_dim; shape = ALLOCA_N(int, rank); for (i=0;itype,rank,shape,klass); GetNArray(v,arynew); SetFuncs[ary->type][ary->type](1, arynew->ptr, 0, NA_PTR(ary,pos), 0); } return v; } static VALUE na_aref_multi_dim(VALUE self, int nidx, VALUE *idx, int flag) { VALUE v; int size; struct NARRAY *ary; struct slice *sl; GetNArray(self,ary); if (ary->rank==0) rb_raise(rb_eIndexError, "Cannot extract from Empty NArray"); /* make Slice */ sl = ALLOC_N(struct slice, ary->rank+1); size = na_index_analysis(nidx, idx, ary, sl); if ( size == 1 ) { /* return Single Element */ v = na_aref_multi_dim_single_elm(self, sl, flag); } else if ( size > 1 ) { v = na_aref_slice(ary, sl, CLASS_OF(self), flag); } else /* size < 1 */ { v = na_make_empty(ary->type,cNArray); } na_free_slice_index(sl,ary->rank); /* free index memory */ xfree(sl); return v; } /* vvv mask vvv */ static int na_count_true_body(VALUE self) { struct NARRAY *ary; int n, count=0; u_int8_t *ptr; GetNArray(self,ary); if ( ary->type == NA_BYTE ) { ptr = (u_int8_t *)ary->ptr; n = ary->total; for (; n; --n) { if (*ptr++) ++count; } } else rb_raise(rb_eTypeError,"cannot count_true NArray except BYTE type"); return count; } /* * call-seq: * narray.count_true -> int * * Returns the number of true (non-zero) in narray */ VALUE na_count_true(VALUE self) { return( INT2NUM(na_count_true_body(self)) ); } static int na_count_false_body(VALUE self) { struct NARRAY *ary; int n, count=0; u_int8_t *ptr; GetNArray(self,ary); if ( ary->type == NA_BYTE ) { ptr = (u_int8_t *)ary->ptr; n = ary->total; for (; n; --n) { if (!*ptr++) ++count; } } else rb_raise(rb_eTypeError,"cannot count_false NArray except BYTE type"); return count; } /* * call-seq: * narray.count_false -> int * * Returns the number of false (zero-value) in narray */ VALUE na_count_false(VALUE self) { return( INT2NUM(na_count_false_body(self)) ); } /* :nodoc: */ VALUE na_aref_mask(VALUE self, VALUE mask) { int total, i; struct NARRAY *a1, *am, *a2; VALUE v; GetNArray( self, a1 ); GetNArray( mask, am ); if (a1->total != am->total) rb_raise(rb_eTypeError,"self.size(=%i) != mask.size(=%i)", a1->total, am->total); if (a1->rank != am->rank) rb_raise(rb_eTypeError,"self.rank(=%i) != mask.rank(=%i)", a1->rank, am->rank); for (i=0; irank; ++i) if (a1->shape[i] != am->shape[i]) rb_raise(rb_eTypeError,"self.shape[%i](=%i) != mask.shape[%i](=%i)", i, a1->shape[i], i, am->shape[i]); total = na_count_true_body(mask); v = na_make_object( a1->type, 1, &total, CLASS_OF(self) ); GetNArray(v,a2); RefMaskFuncs[a1->type] ( a1->total, a2->ptr, na_sizeof[a2->type], a1->ptr, na_sizeof[a1->type], am->ptr, 1 ); return(v); } /* ^^^ mask ^^^ */ /* method: [](idx1,idx2,...,idxN) */ static VALUE na_aref_body(int nidx, VALUE *idx, VALUE self, int flag) { if (nidx==0) { return na_clone(self); } if (nidx==1) { if ( NA_IsNArray(idx[0]) ) { if( NA_TYPE(idx[0]) == NA_BYTE ) /* then supposed to be a mask */ return na_aref_mask(self, idx[0]); } if ( na_class_dim(CLASS_OF(self)) != 1 ) { if ( NA_IsArray(idx[0]) ) /* Array Index ? */ return na_aref_single_dim_array( self, idx[0] ); else return na_aref_single_dim( self, idx[0], flag ); } } /* if (nidx>1) */ return na_aref_multi_dim( self, nidx, idx, flag ); } /* method: [](idx1,idx2,...,idxN) */ VALUE na_aref(int argc, VALUE *argv, VALUE self) { return na_aref_body(argc, argv, self, 0); } /* method: slice(idx1,idx2,...,idxN) */ VALUE na_slice(int argc, VALUE *argv, VALUE self) { return na_aref_body(argc, argv, self, 1); } /* []= -- Set elements to specified indices */ /* make slice for array-set: a[0..-1,1..2] = 1 */ static void na_make_slice_aset_fill(int rank, struct NARRAY *src_ary, struct slice *src_slc, int *src_shape, struct slice *dst_slc) { int i; for (i=0; irank; ++i) { if ( s1[i].step !=0 ) { /* Range index */ /* rank check */ if ( j >= src->rank ) rb_raise(rb_eIndexError, "dst.range-dim=%i > src.dim=%i", j+1, src->rank); if ( s1[i].n == 0 ) { /* Size is NOT specified: a[0..nil] = other_array a[0] = other_array */ s1[i].n = src->shape[j]; idx_end = s1[i].beg + (s1[i].n-1) * s1[i].step; if ( idx_end < 0 || idx_end >= dst->shape[i] ) rb_raise(rb_eIndexError, "end-index=%i is out of dst.shape[%i]=%i", idx_end, i, dst->shape[i]); } else /* Size is specified: a[0..10] = other */ if ( src->shape[j] >1 && s1[i].n != src->shape[j] ) { rb_raise(rb_eIndexError, "dst.shape[%i]=%i != src.shape[%i]=%i", i, s1[i].n, j, src->shape[j]); } /* copy source shape */ src_shape[i] = src->shape[j++]; } else /* if ( s1[i].n==1 ) Scalar index: a[0, 0..-1] = other --- first rank is skipped. */ src_shape[i] = 1; /* insert dummy rank */ s2[i].beg = 0; s2[i].idx = NULL; s2[i].n = s1[i].n; /* repeate number is same as a1 index */ if ( s1[i].n >1 && src_shape[i]==1 ) /* Extensible index */ s2[i].step = 0; else s2[i].step = 1; } /* rank check */ if ( j != src->rank ) rb_raise(rb_eIndexError, "dst.range-dim=%i < src.dim=%i", j, src->rank); } /* Iterate with bifinc, src has extensible index */ void na_aset_slice(struct NARRAY *dst, struct NARRAY *src, struct slice *dst_slc) { int rank = dst->rank; int *src_shape; struct slice *src_slc; /* rank check */ if (rank < src->rank) rb_raise(rb_eIndexError, "%i dst.ranks < %i src.ranks", rank, src->rank); if (src->rank == 0) rb_raise(rb_eIndexError, "cannot store empty array"); /* extend rank */ src_shape = ALLOCA_N(int, rank); src_slc = ALLOC_N(struct slice, rank+1); if (src->total==1) na_make_slice_aset_fill( rank, src, src_slc, src_shape, dst_slc ); else na_make_slice_aset( dst, src, dst_slc, src_slc, src_shape ); /* Iteration */ na_init_slice( dst_slc, rank, dst->shape, na_sizeof[dst->type] ); na_init_slice( src_slc, rank, src_shape, na_sizeof[src->type] ); na_loop_general( dst,src, dst_slc,src_slc, SetFuncs[dst->type][src->type] ); xfree(src_slc); } static void na_aset_array_index( VALUE self, volatile VALUE idx, volatile VALUE val ) { int i, total; struct NARRAY *aidx, *src, *dst; struct slice *sl; GetNArray(self,dst); idx = na_cast_object(idx,NA_LINT); GetNArray(idx,aidx); val = na_cast_unless_narray(val,dst->type); GetNArray(val,src); /* empty index -- do nothing */ if (aidx->total==0 && (src->total==0 || src->total==1)) return; /* check rank */ if (aidx->rank != src->rank) rb_raise( rb_eIndexError, "idx.rank=%i != src.rank=%i", aidx->rank, src->rank ); /* check shape */ for (i=0;irank;++i) if (aidx->shape[i] != src->shape[i] && src->shape[i] != 1) rb_raise( rb_eIndexError, "idx.shape[%i]=%i != src.shape[%i]=%i", i, aidx->shape[i], i, src->shape[i] ); /* make Slice from index */ sl = ALLOCA_N(struct slice,2); total = na_ary_to_index( NA_STRUCT(idx), dst->total, sl ); /* 1-dimensionize */ if (dst->rank > 1) { na_flatten_temp(dst); } if (src->rank > 1) { na_flatten_temp(src); } na_aset_slice( dst, src, sl ); na_free_slice_index( sl, 1 ); /* free index memory */ } static void na_aset_single_dim(VALUE self, VALUE idx, volatile VALUE val) { int size; struct NARRAY *src, *dst; struct slice *sl; GetNArray(self,dst); if (dst->total==0) rb_raise(rb_eRuntimeError, "cannot set value to empty array"); sl = ALLOCA_N(struct slice, 2); size = na_index_test(idx, dst->total, sl); if ( size == 1 ) { if (NA_IsNArray(val)) { GetNArray(val,src); if ( src->total == 1 ) { SetFuncs[dst->type][src->type](1, NA_PTR(dst,sl->beg),0, src->ptr,0); return; } } else if (TYPE(val)!=T_ARRAY) { /* Storing single element: a[1] = 1 */ SetFuncs[dst->type][NA_ROBJ](1, NA_PTR(dst,sl->beg),0, &val,0); return; } /* Beginning index: a[1] = [1,2,3] */ sl[0].n = 0; sl[0].step = 1; } else if ( size == 0 ) return; /* Empty index */ if ( dst->rank > 1 ) { /* 1-dimensionize */ na_flatten_temp(dst); } val = na_cast_unless_narray(val,dst->type); GetNArray(val,src); na_aset_slice( dst, src, sl ); na_free_slice_index(sl,1); /* free index memory */ } static void na_aset_multi_dim(VALUE self, int nidx, VALUE *idx, volatile VALUE val) { int i, pos, size; struct NARRAY *dst, *src; struct slice *sl; GetNArray(self,dst); if (dst->total==0) rb_raise(rb_eRuntimeError, "cannot set value to empty array"); /* make Slice from index-argv */ sl = ALLOC_N(struct slice, dst->rank+1); size = na_index_analysis( nidx, idx, dst, sl ); if ( size == 0 ) { xfree(sl); return; } /* Empty index */ if ( size == 1 ) { if (NA_IsArray(val)) { /* Beginning index: a[2,3,4] = other */ val = na_cast_unless_narray(val,dst->type); GetNArray(val,src); if (src->total > 1) for( i=0; irank; ++i ) { sl[i].n = 0; sl[i].step = 1; } } else { /* Single Element: a[2,3,4] = 5 */ for ( pos=0, i=dst->rank; i-->0; ) pos = pos * dst->shape[i] + sl[i].beg; SetFuncs[dst->type][NA_ROBJ](1, NA_PTR(dst,pos), 0, &val, 0 ); xfree(sl); return; } } else val = na_cast_unless_narray(val,dst->type); GetNArray(val,src); /* if ( size>1 ) */ /* Range index: a[0..9,0] = other */ na_aset_slice( dst, src, sl ); na_free_slice_index(sl,nidx); /* free index memory */ xfree(sl); } static void na_aset_fill(VALUE self, volatile VALUE val) { struct NARRAY *dst, *src; struct slice *sl; GetNArray(self,dst); if (dst->total==0) rb_raise(rb_eRuntimeError, "cannot set value to empty array"); if ( NA_IsArray(val) ) { /* store Array? */ sl = ALLOC_N(struct slice, dst->rank+1); na_set_slice_1obj(dst->rank,sl,dst->shape); val = na_cast_unless_narray(val,dst->type); GetNArray(val,src); na_aset_slice( dst, src, sl ); xfree(sl); } else { na_fill( self, val ); /* Simple filling */ } } /* --- mask --- */ void na_aset_mask(VALUE self, VALUE mask, VALUE val) { int size, step, i; struct NARRAY *a1, *am, *a2; GetNArray( self, a1 ); GetNArray( mask, am ); if (a1->total != am->total) rb_raise(rb_eTypeError,"self.size(=%i) != mask.size(=%i)", a1->total, am->total); if (a1->rank != am->rank) rb_raise(rb_eTypeError,"self.rank(=%i) != mask.rank(=%i)", a1->rank, am->rank); for (i=0; irank; ++i) if (a1->shape[i] != am->shape[i]) rb_raise(rb_eTypeError,"self.shape[%i](=%i) != mask.shape[%i](=%i)", i, a1->shape[i], i, am->shape[i]); size = na_count_true_body(mask); val = na_cast_object(val,a1->type); GetNArray( val, a2 ); if (a2->total == 1) { step = 0; } else if (a2->total == size) { step = na_sizeof[a2->type]; } else { rb_raise(rb_eTypeError,"val.length != mask.count_true"); } SetMaskFuncs[a1->type] ( a1->total, a1->ptr, na_sizeof[a1->type], a2->ptr, step, am->ptr, 1 ); } /* method: []=(idx1,idx2,...,idxN,val) */ VALUE na_aset(int nidx, VALUE *idx, VALUE self) { --nidx; if (nidx==0) { na_aset_fill( self, idx[0] ); } else if (nidx==1) { if ( NA_IsNArray(idx[0]) ) { if( NA_TYPE(idx[0]) == NA_BYTE ) { /* then supposed to be a mask */ na_aset_mask(self, idx[0], idx[1]); return(idx[1]); } } if ( NA_IsArray(idx[0]) ) /* Array Index ? */ na_aset_array_index( self, idx[0], idx[1] ); else na_aset_single_dim( self, idx[0], idx[1] ); } else if (nidx>1) { na_aset_multi_dim( self, nidx, idx, idx[nidx] ); } else /* if (nidx<0) */ rb_raise( rb_eArgError, "No value specified" ); return idx[nidx]; } void Init_na_index() { /* slice */ rb_define_method(cNArray, "[]", na_aref,-1); rb_define_method(cNArray, "[]=", na_aset,-1); rb_define_method(cNArray, "slice", na_slice,-1); /* mask */ rb_define_method(cNArray, "count_false", na_count_false, 0); rb_define_method(cNArray, "count_true", na_count_true, 0); rb_define_method(cNArray, "mask", na_aref_mask, 1); } narray-0.6.1.2/src/depend0000644000175000017500000000047512745364057015002 0ustar uwabamiuwabamina_op.c: mknafunc.rb mkop.rb $(RUBY) -I$(srcdir) $(srcdir)/mkop.rb na_op.o: na_op.c narray.h $(hdrdir)/ruby.h na_math.c: mknafunc.rb mkmath.rb $(RUBY) -I$(srcdir) $(srcdir)/mkmath.rb na_math.o: na_math.c narray.h $(hdrdir)/ruby.h cleanall: clean @$(RM) -r Makefile narray_config.h na_op.c na_math.c src pkg narray-0.6.1.2/src/mkop.rb0000644000175000017500000003255312745364057015115 0ustar uwabamiuwabamirequire "mknafunc" fname = "na_op.c" $> = open(fname,"w") upcast_ary = $upcast.collect{|i| ' {'+i.join(", ")+'}'}.join(",\n") print < #include "narray.h" #include "narray_local.h" /* isalpha(3) etc. */ #include const int na_upcast[NA_NTYPES][NA_NTYPES] = { #{upcast_ary} }; const int na_no_cast[NA_NTYPES] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; const int na_cast_real[NA_NTYPES] = { 0, 1, 2, 3, 4, 5, 4, 5, 8 }; const int na_cast_comp[NA_NTYPES] = { 0, 6, 6, 6, 6, 7, 6, 7, 8 }; const int na_cast_round[NA_NTYPES] = { 0, 1, 2, 3, 3, 3, 6, 7, 8 }; const int na_cast_byte[NA_NTYPES] = { 0, 1, 1, 1, 1, 1, 1, 1, 1 }; static void TpErr(void) { rb_raise(rb_eTypeError,"illegal operation with this type"); } static int TpErrI(void) { rb_raise(rb_eTypeError,"illegal operation with this type"); return 0; } static void na_zerodiv() { rb_raise(rb_eZeroDivError, "divided by 0"); } static int notnanF(float *n) { return *n == *n; } static int notnanD(double *n) { return *n == *n; } EOM # # Set Fucs # data = [ [/[O]/,/[O]/, "*p1 = *p2;"], [/[O]/,/[BI]/, "*p1 = INT2FIX(*p2);"], [/[O]/,/[L]/, "*p1 = INT2NUM(*p2);"], [/[O]/,/[FD]/, "*p1 = rb_float_new(*p2);"], [/[O]/,/[XC]/, "*p1 = rb_complex_new(p2->r,p2->i);"], [/[BIL]/,/[O]/, "*p1 = NUM2INT(*p2);"], [/[FD]/,/[O]/, "*p1 = NUM2DBL(*p2);"], [/[XC]/,/[O]/, "p1->r = NUM2REAL(*p2); p1->i = NUM2IMAG(*p2);"], [/[BILFD]/,/[BILFD]/,"*p1 = *p2;"], [/[BILFD]/,/[XC]/, "*p1 = p2->r;"], [/[XC]/,/[BILFD]/, "p1->r = *p2; p1->i = 0;"], [/[XC]/,/[XC]/, "p1->r = p2->r; p1->i = p2->i;"] ] $func_body = "static void #name#CC(int n, char *p1, int i1, char *p2, int i2) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; } } " mksetfuncs('Set','','',data) # # Unary Funcs # $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; } } " mkfuncs('Swp', $swap_types, $swap_types, [nil] + ["*p1 = *p2;"] + ["na_size16_t x; swap16(x,*p2); *p1 = x;"] + ["na_size32_t x; swap32(x,*p2); *p1 = x;"] + ["na_size32_t x; swap32(x,*p2); *p1 = x;"] + ["na_size64_t x; swap64(x,*p2); *p1 = x;"] + ["na_size64_t x; swap64c(x,*p2); *p1 = x;"] + ["na_size128_t x; swap128c(x,*p2); *p1 = x;"] + ["*p1 = *p2;"] ) print <r = -p2->r; p1->i = -p2->i;"]*2 + ["*p1 = rb_funcall(*p2,na_id_minus,0);"] ) mkfuncs('AddU', $data_types, $data_types, [nil] + ["*p1 += *p2;"]*5 + ["p1->r += p2->r; p1->i += p2->i;"]*2 + ["*p1 = rb_funcall(*p1,'+',1,*p2);"] ) mkfuncs('SbtU', $data_types, $data_types, [nil] + ["*p1 -= *p2;"]*5 + ["p1->r -= p2->r; p1->i -= p2->i;"]*2 + ["*p1 = rb_funcall(*p1,'-',1,*p2);"] ) mkfuncs('MulU', $data_types, $data_types, [nil] + ["*p1 *= *p2;"]*5 + ["type1 x = *p1; p1->r = x.r*p2->r - x.i*p2->i; p1->i = x.r*p2->i + x.i*p2->r;"]*2 + ["*p1 = rb_funcall(*p1,'*',1,*p2);"] ) mkfuncs('DivU', $data_types, $data_types, [nil] + ["if (*p2==0) {na_zerodiv();} *p1 /= *p2;"]*3 + ["*p1 /= *p2;"]*2 + ["type1 x = *p1; typef a = p2->r*p2->r + p2->i*p2->i; p1->r = (x.r*p2->r + x.i*p2->i)/a; p1->i = (x.i*p2->r - x.r*p2->i)/a;"]*2 + ["*p1 = rb_funcall(*p1,'/',1,*p2);"] ) mkfuncs('ModU', $data_types, $data_types, [nil] + ["if (*p2==0) {na_zerodiv();} *p1 %= *p2;"]*3 + ["*p1 = fmod(*p1, *p2);"]*2 + [nil]*2 + ["*p1 = rb_funcall(*p1,'%',1,*p2);"] ) # method: imag= mkfuncs('ImgSet',$data_types,$real_types, [nil]*6 + ["p1->i = *p2;"]*2 + [nil] ) mkfuncs('Floor',$int_types,$data_types,[nil] + ['copy']*3 + ["*p1 = (typec)floor(*p2);"]*2 + [nil]*3 ) mkfuncs('Ceil',$int_types,$data_types,[nil] + ['copy']*3 + ["*p1 = (typec)ceil(*p2);"]*2 + [nil]*3 ) mkfuncs('Round',$int_types,$data_types,[nil] + ['copy']*3 + # ["*p1 = floor(*p2+0.5);"]*2 + ["if (*p2 >= 0) *p1 = (typec)floor(*p2+0.5); else *p1 = (typec)ceil(*p2-0.5);"]*2 + [nil]*3 ) mkfuncs('Abs',$real_types,$data_types,[nil] + ["*p1 = *p2;"] + ["*p1 = (*p2<0) ? -*p2 : *p2;"]*4 + ["*p1 = (typec)hypot(p2->r, p2->i);"]*2 + ["*p1 = rb_funcall(*p2,na_id_abs,0);"] ) mkfuncs('Real',$real_types,$data_types,[nil] + ['copy']*7 + [nil] ) mkfuncs('Imag',$real_types,$data_types,[nil] + ["*p1 = 0;"]*5 + ["*p1 = p2->i;"]*2 + [nil] ) mkfuncs('Angl',$real_types,$data_types,[nil] + [nil]*5 + ["*p1 = atan2(p2->i,p2->r);"]*2 + [nil] ) mkfuncs('ImagMul',$comp_types,$data_types,[nil] + [nil]*3 + ["p1->r = 0; p1->i = *p2;"]*2 + ["p1->r = -p2->i; p1->i = p2->r;"]*2 + [nil] ) mkfuncs('Conj',$data_types,$data_types,[nil] + ['copy']*5 + ["p1->r = p2->r; p1->i = -p2->i;"]*2 + [nil] ) mkfuncs('Not', [$data_types[1]]*9, $data_types, [nil] + ["*p1 = (*p2==0) ? 1:0;"]*5 + ["*p1 = (p2->r==0 && p2->i==0) ? 1:0;"]*2 + ["*p1 = RTEST(*p2) ? 0:1;"] ) mkfuncs('BRv', $data_types, $data_types, [nil] + ["*p1 = ~(*p2);"]*3 + [nil]*4 + ["*p1 = rb_funcall(*p2,'~',0);"] ) mkfuncs('Min', $data_types, $data_types, [nil] + ["if (*p1>*p2) *p1=*p2;"]*3 + ["if (notnan#C((type1*)p2) && *p1>*p2) *p1=*p2;"]*2 + [nil]*2 + ["if (FIX2INT(rb_funcall(*p1,na_id_compare,1,*p2))>0) *p1=*p2;"] ) mkfuncs('Max', $data_types, $data_types, [nil] + ["if (*p1<*p2) *p1=*p2;"]*3 + ["if (notnan#C((type1*)p2) && *p1<*p2) *p1=*p2;"]*2 + [nil]*2 + ["if (FIX2INT(rb_funcall(*p1,na_id_compare,1,*p2))<0) *p1=*p2;"] ) mksortfuncs('Sort', $data_types, $data_types, [nil] + [" { if (*p1 > *p2) return 1; if (*p1 < *p2) return -1; return 0; }"]*5 + [nil]*2 + [" { VALUE r = rb_funcall(*p1, na_id_compare, 1, *p2); return NUM2INT(r); }"] ) mksortfuncs('SortIdx', $data_types, $data_types, [nil] + [" { if (**p1 > **p2) return 1; if (**p1 < **p2) return -1; return 0; }"]*5 + [nil]*2 + [" { VALUE r = rb_funcall(**p1, na_id_compare, 1, **p2); return NUM2INT(r); }"] ) # indgen $func_body = "static void #name#C(int n, char *p1, int i1, int p2, int i2) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; } } " mkfuncs('IndGen',$data_types,[$data_types[3]]*8, [nil] + ["*p1 = (typef)p2;"]*5 + ["p1->r = (typef)p2; p1->i = 0;"]*2 + ["*p1 = INT2FIX(p2);"] ) $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2) { OPERATION } " mkfuncs('ToStr',['']+[$data_types[8]]*8,$data_types, [nil] + ["char buf[22]; for (; n; --n) { sprintf(buf,\"%i\",(int)*p2); *p1 = rb_str_new2(buf); p1+=i1; p2+=i2; }"]*3 + ["char buf[24]; for (; n; --n) { sprintf(buf,\"%.5g\",(double)*p2); *p1 = rb_str_new2(buf); p1+=i1; p2+=i2; }"] + ["char buf[24]; for (; n; --n) { sprintf(buf,\"%.8g\",(double)*p2); *p1 = rb_str_new2(buf); p1+=i1; p2+=i2; }"] + ["char buf[50]; for (; n; --n) { sprintf(buf,\"%.5g%+.5gi\",(double)p2->r,(double)p2->i); *p1 = rb_str_new2(buf); p1+=i1; p2+=i2; }"] + ["char buf[50]; for (; n; --n) { sprintf(buf,\"%.8g%+.8gi\",(double)p2->r,(double)p2->i); *p1 = rb_str_new2(buf); p1+=i1; p2+=i2; }"] + ["for (; n; --n) { *p1 = rb_obj_as_string(*p2); p1+=i1; p2+=i2; }"] ) print <r); na_str_append_fp(buf); b = buf+strlen(buf); sprintf(b,\"%+g\",(double)p2->i); na_str_append_fp(b); strcat(buf,\"i\"); *p1 = rb_str_new2(buf);"] + ["char buf[50], *b; sprintf(buf,\"%g\",(double)p2->r); na_str_append_fp(buf); b = buf+strlen(buf); sprintf(b,\"%+g\",(double)p2->i); na_str_append_fp(b); strcat(buf,\"i\"); *p1 = rb_str_new2(buf);"] + ["*p1 = rb_inspect(*p2);"] ) # # Binary Funcs # =begin # Optimize experiment $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3) { int i; if (i1==sizeof(type1) && i2==sizeof(type1) && i3==sizeof(type1)) { type1 *a1=p1, *a2=p2, *a3=p3; for (i=0; n; --n,++i) { *a1 = *a2 * *a3; +++a1;++a2;++a3; } } else for (; n; --n) { OPERATION p1+=i1; p2+=i2; p3+=i3; } } " mkfuncs('MulB', $data_types, $data_types, [nil] + ["*p1 = *p2 * *p3;"]*5 + [nil]*3 ) =end $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3) { for (; n; --n) { OPERATION p1+=i1; p2+=i2; p3+=i3; } } " mkfuncs('AddB', $data_types, $data_types, [nil] + ["*p1 = *p2 + *p3;"]*5 + ["p1->r = p2->r + p3->r; p1->i = p2->i + p3->i;"]*2 + ["*p1 = rb_funcall(*p2,'+',1,*p3);"] ) mkfuncs('SbtB', $data_types, $data_types, [nil] + ["*p1 = *p2 - *p3;"]*5 + ["p1->r = p2->r - p3->r; p1->i = p2->i - p3->i;"]*2 + ["*p1 = rb_funcall(*p2,'-',1,*p3);"] ) mkfuncs('MulB', $data_types, $data_types, [nil] + ["*p1 = *p2 * *p3;"]*5 + ["type1 x = *p2; p1->r = x.r*p3->r - x.i*p3->i; p1->i = x.r*p3->i + x.i*p3->r;"]*2 + ["*p1 = rb_funcall(*p2,'*',1,*p3);"] ) mkfuncs('DivB', $data_types, $data_types, [nil] + ["if (*p3==0) {na_zerodiv();}; *p1 = *p2 / *p3;"]*3 + ["*p1 = *p2 / *p3;"]*2 + ["type1 x = *p2; typef a = p3->r*p3->r + p3->i*p3->i; p1->r = (x.r*p3->r + x.i*p3->i)/a; p1->i = (x.i*p3->r - x.r*p3->i)/a;"]*2 + ["*p1 = rb_funcall(*p2,'/',1,*p3);"] ) mkfuncs('ModB', $data_types, $data_types, [nil] + ["if (*p3==0) {na_zerodiv();}; *p1 = *p2 % *p3;"]*3 + ["*p1 = fmod(*p2, *p3);"]*2 + [nil]*2 + ["*p1 = rb_funcall(*p2,'%',1,*p3);"] ) mkfuncs('MulAdd', $data_types, $data_types, [nil] + ["*p1 += *p2 * *p3;"]*5 + ["type1 x = *p2; p1->r += x.r*p3->r - x.i*p3->i; p1->i += x.r*p3->i + x.i*p3->r;"]*2 + ["*p1 = rb_funcall(*p1,'+',1, rb_funcall(*p2,'*',1,*p3));"] ) mkfuncs('MulSbt', $data_types, $data_types, [nil] + ["*p1 -= *p2 * *p3;"]*5 + ["type1 x = *p2; p1->r -= x.r*p3->r - x.i*p3->i; p1->i -= x.r*p3->i + x.i*p3->r;"]*2 + ["*p1 = rb_funcall(*p1,'-',1, rb_funcall(*p2,'*',1,*p3));"] ) # # Bit operator # mkfuncs('BAn', $data_types, $data_types, [nil] + ["*p1 = *p2 & *p3;"]*3 + [nil]*4 + ["*p1 = rb_funcall(*p2,'&',1,*p3);"] ) mkfuncs('BOr', $data_types, $data_types, [nil] + ["*p1 = *p2 | *p3;"]*3 + [nil]*4 + ["*p1 = rb_funcall(*p2,'|',1,*p3);"] ) mkfuncs('BXo', $data_types, $data_types, [nil] + ["*p1 = *p2 ^ *p3;"]*3 + [nil]*4 + ["*p1 = rb_funcall(*p2,'^',1,*p3);"] ) # # Comparison # mkfuncs('Eql', [$data_types[1]]*9, $data_types, [nil] + ["*p1 = (*p2==*p3) ? 1:0;"]*5 + ["*p1 = (p2->r==p3->r) && (p2->i==p3->i) ? 1:0;"]*2 + ["*p1 = RTEST(rb_equal(*p2, *p3)) ? 1:0;"] ) mkfuncs('Cmp', [$data_types[1]]*9, $data_types, [nil] + ["if (*p2>*p3) *p1=1; else if (*p2<*p3) *p1=2; else *p1=0;"]*5 + [nil]*2 + ["int v = NUM2INT(rb_funcall(*p2,na_id_compare,1,*p3)); if (v>0) *p1=1; else if (v<0) *p1=2; else *p1=0;"] ) mkfuncs('And', [$data_types[1]]*9, $data_types, [nil] + ["*p1 = (*p2!=0 && *p3!=0) ? 1:0;"]*5 + ["*p1 = ((p2->r!=0||p2->i!=0) && (p3->r!=0||p3->i!=0)) ? 1:0;"]*2 + ["*p1 = (RTEST(*p2) && RTEST(*p3)) ? 1:0;"] ) mkfuncs('Or_', [$data_types[1]]*9, $data_types, [nil] + ["*p1 = (*p2!=0 || *p3!=0) ? 1:0;"]*5 + ["*p1 = ((p2->r!=0||p2->i!=0) || (p3->r!=0||p3->i!=0)) ? 1:0;"]*2 + ["*p1 = (RTEST(*p2) || RTEST(*p3)) ? 1:0;"] ) mkfuncs('Xor', [$data_types[1]]*9, $data_types, [nil] + ["*p1 = ((*p2!=0) == (*p3!=0)) ? 0:1;"]*5 + ["*p1 = ((p2->r!=0||p2->i!=0) == (p3->r!=0||p3->i!=0)) ? 0:1;"]*2 + ["*p1 = (RTEST(*p2) == RTEST(*p3)) ? 0:1;"] ) # # Atan2 # mkfuncs('atan2', $data_types, $data_types, [nil]*4 + ["*p1 = atan2(*p2, *p3);"]*2 + [nil]*3 ) # # Mask # $func_body = "static void #name#C(int n, char *p1, int i1, char *p2, int i2, char *p3, int i3) { for (; n; --n) { OPERATION } } " mkfuncs('RefMask',$data_types,$data_types, [nil] + ["if (*(u_int8_t*)p3) { *p1=*p2; p1+=i1; } p3+=i3; p2+=i2;"]*8 ) mkfuncs('SetMask',$data_types,$data_types, [nil] + ["if (*(u_int8_t*)p3) { *p1=*p2; p2+=i2; } p3+=i3; p1+=i1;"]*8 ) narray-0.6.1.2/src/na_array.c0000644000175000017500000003052512745364057015557 0ustar uwabamiuwabami/* na_array.c Numerical Array Extention for Ruby (C) Copyright 1999-2008 by Masahiro TANAKA This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. */ #include #include "narray.h" #include "narray_local.h" /* Multi-Dimensional Array Investigation */ typedef struct { int shape; VALUE val; } na_mdai_item_t; typedef struct { int n; na_mdai_item_t *item; int *type; } na_mdai_t; int na_object_type(VALUE v) { switch(TYPE(v)) { case T_TRUE: case T_FALSE: return NA_BYTE; case T_FIXNUM: case T_BIGNUM: return NA_LINT; case T_FLOAT: return NA_DFLOAT; case T_NIL: return NA_NONE; default: if (IsNArray(v)) return ((struct NARRAY *)(RDATA(v)->data))->type ; if (CLASS_OF(v) == cComplex) return NA_DCOMPLEX; } return NA_ROBJ; } static na_mdai_t * na_alloc_mdai(VALUE ary) { int i, n=2; na_mdai_t *mdai; mdai = ALLOC(na_mdai_t); mdai->n = n; mdai->item = ALLOC_N( na_mdai_item_t, n ); for (i=0; iitem[i].shape = 0; mdai->item[i].val = Qnil; } mdai->item[0].val = ary; mdai->type = ALLOC_N( int, NA_NTYPES ); for (i=0; itype[i]=0; return mdai; } static void na_realloc_mdai(na_mdai_t *mdai, int n_extra) { int i, n; i = mdai->n; mdai->n += n_extra; n = mdai->n; REALLOC_N( mdai->item, na_mdai_item_t, n ); for (; iitem[i].shape = 0; mdai->item[i].val = Qnil; } } static int * na_free_mdai(na_mdai_t *mdai, int *rank, int *type) { int i, t, r; int *shape; for (t=i=NA_BYTE; itype[i] > 0 ) t = na_upcast[t][i]; } *type = t; for (i=0; i < mdai->n && mdai->item[i].shape > 0; ++i) ; *rank = r = i; shape = ALLOC_N(int,r); for (i=0; r-->0; ++i) { shape[i] = mdai->item[r].shape; } xfree(mdai->type); xfree(mdai->item); xfree(mdai); return shape; } #define EXCL(r) (RTEST(rb_funcall((r),na_id_exclude_end,0))) /* Range as a Sequence of numbers */ static void na_range_to_sequence(VALUE obj, int *n, int *beg, int *step) { int end,len; *beg = NUM2INT(rb_funcall(obj, na_id_beg, 0)); end = NUM2INT(rb_funcall(obj, na_id_end, 0)); len = end - *beg; /* direction */ if (len>0) { *step = 1; if (EXCL(obj)) --end; else ++len; } else if (len<0) { len = -len; *step = -1; if (EXCL(obj)) ++end; else ++len; } else /*if(len==0)*/ { *step = 0; if (!EXCL(obj)) { ++len; } } *n = len; } /* investigate rank, shape, type of Array */ static int na_do_mdai(na_mdai_t *mdai, int rank) { int i, j, len, length, start, dir; VALUE v; VALUE ary; ary = mdai->item[rank-1].val; len = RARRAY_LEN(ary); for (i=0; i < RARRAY_LEN(ary); ++i) { v = RARRAY_PTR(ary)[i]; if (TYPE(v) == T_ARRAY) { /* check recursive array */ for (j=0; jitem[j].val == v) rb_raise(rb_eStandardError,"converting recursive Array to NArray"); } if ( rank >= mdai->n ) { na_realloc_mdai(mdai,2); } mdai->item[rank].val = v; if ( na_do_mdai(mdai,rank+1) ) { --len; /* Array is empty */ } } else if ( rb_obj_is_kind_of(v, rb_cRange) ) { na_range_to_sequence(v,&length,&start,&dir); len += length-1; mdai->type[ na_object_type(rb_funcall(v, na_id_beg, 0)) ] = 1; mdai->type[ na_object_type(rb_funcall(v, na_id_end, 0)) ] = 1; } else { mdai->type[ na_object_type(v) ] = 1; if (IsNArray(v)) { int r; struct NARRAY *na; GetNArray(v,na); if ( na->rank == 0 ) { --len; /* NArray is empty */ } else { if ( rank+na->rank > mdai->n ) { na_realloc_mdai(mdai,((na->rank-1)/4+1)*4); } for ( j=na->rank, r=rank; j-- > 0 ; ++r ) { if ( mdai->item[r].shape < na->shape[j] ) mdai->item[r].shape = na->shape[j]; } } } } } if (len==0) return 1; /* this array is empty */ if (mdai->item[rank-1].shape < len) { mdai->item[rank-1].shape = len; } return 0; } /* get index from multiple-index */ static int na_index_pos(struct NARRAY *ary, int *idxs) { int i, idx, pos = 0; for ( i = ary->rank; (i--)>0; ) { idx = idxs[i]; if (idx < 0 || ary->shape[i] <= idx) { abort(); rb_raise(rb_eRuntimeError, "Subsctipt out of range: accessing shape[%i]=%i with %i", i, ary->shape[i], idx ); } pos = pos * ary->shape[i] + idx; } return pos; } static void na_copy_nary_to_nary(VALUE obj, struct NARRAY *dst, int thisrank, int *idx) { struct NARRAY *src; struct slice *s; int i, n; GetNArray(obj,src); n = thisrank - src->rank + 1; s = ALLOCA_N(struct slice, dst->rank+1); for (i=0; i < n; ++i) { s[i].n = 1; s[i].beg = 0; s[i].step = 0; s[i].idx = NULL; } for ( ; i <= thisrank; ++i) { s[i].n = src->shape[i-n]; s[i].beg = 0; s[i].step = 1; s[i].idx = NULL; } for ( ; i < dst->rank; ++i) { s[i].n = 1; s[i].beg = idx[i]; s[i].step = 0; s[i].idx = NULL; } na_aset_slice(dst,src,s); } /* copy Array to NArray */ static void na_copy_ary_to_nary( VALUE ary, struct NARRAY *na, int thisrank, int *idx, int type ) { int i, j, pos, len, start, step, dir; VALUE v; if (thisrank==0) { for (i = idx[0] = 0; i < RARRAY_LEN(ary); ++i) { v = RARRAY_PTR(ary)[i]; if (rb_obj_is_kind_of(v, rb_cRange)) { na_range_to_sequence(v,&len,&start,&dir); if (len>0) { pos = na_index_pos(na,idx); IndGenFuncs[type](len, NA_PTR(na,pos),na_sizeof[type], start,dir); idx[0] += len; } } else if (TYPE(v) != T_ARRAY) { /* NIL if empty */ if (v != Qnil) { pos = na_index_pos(na,idx); SetFuncs[type][NA_ROBJ]( 1, NA_PTR(na,pos), 0, &v, 0 ); /* copy here */ } idx[0] ++; } } } else /* thisrank > 0 */ { for (i = idx[thisrank] = 0; i < RARRAY_LEN(ary); ++i) { v = RARRAY_PTR(ary)[i]; if (TYPE(v) == T_ARRAY) { na_copy_ary_to_nary(v,na,thisrank-1,idx,type); if (idx[thisrank-1]>0) ++idx[thisrank]; } else if (IsNArray(v)) { na_copy_nary_to_nary(v,na,thisrank-1,idx); ++idx[thisrank]; } else { for (j=thisrank; j; ) idx[--j] = 0; if (rb_obj_is_kind_of(v, rb_cRange)) { na_range_to_sequence(v,&len,&start,&dir); if (len>0) { pos = na_index_pos(na,idx); ++idx[thisrank]; step = na_index_pos(na,idx)-pos; IndGenFuncs[type]( len, NA_PTR(na,pos), na_sizeof[type]*step, start, dir ); idx[thisrank] += len-1; } } else { pos = na_index_pos(na,idx); SetFuncs[type][NA_ROBJ]( 1, NA_PTR(na,pos), 0, &(RARRAY_PTR(ary)[i]), 0 ); ++idx[thisrank]; } /* copy here */ } } } } static VALUE na_ary_to_nary_w_type(VALUE ary, int type_spec, VALUE klass) { int i, rank; int type = NA_BYTE; int *shape, *idx; na_mdai_t *mdai; struct NARRAY *na; VALUE v; /* empty array */ if (RARRAY_LEN(ary) < 1) { return na_make_empty( type, klass ); } mdai = na_alloc_mdai(ary); na_do_mdai(mdai,1); shape = na_free_mdai(mdai,&rank,&type); /* printf("rank=%i\n", rank); printf("type=%i\n", type); for (i=0; irank, a2->shape, CLASS_OF(v2)); GetNArray(v1,a1); na_copy_nary(a1,a2); return v1; } VALUE na_change_type(VALUE obj, int type) { struct NARRAY *a2; GetNArray(obj,a2); if (a2->type == type) return obj; return na_dup_w_type(obj, type); } VALUE na_upcast_type(VALUE obj, int type) /* na_upcast_narray */ { int newtype; struct NARRAY *a2; GetNArray(obj,a2); newtype = na_upcast[a2->type][type]; if (newtype == a2->type) return obj; return na_dup_w_type(obj, newtype); } /* obj.kind_of?(Object) == true */ VALUE na_cast_object(VALUE obj, int type) /* na_cast_certain */ { if (IsNArray(obj)) { return na_change_type(obj,type); } if (TYPE(obj) == T_ARRAY) { return na_ary_to_nary_w_type(obj,type,cNArray); } return na_make_scalar(obj,type); } VALUE na_cast_unless_narray(VALUE obj, int type) { if (IsNArray(obj)) { return obj; } if (TYPE(obj) == T_ARRAY) { return na_ary_to_nary_w_type(obj,type,cNArray); } return na_make_scalar(obj,type); } VALUE na_cast_unless_array(VALUE obj, int type) { if (IsNArray(obj)) { return obj; } if (TYPE(obj) == T_ARRAY) { return na_ary_to_nary(obj,cNArray); } return na_make_scalar(obj,type); } VALUE na_upcast_object(VALUE obj, int type) { if (IsNArray(obj)) { return na_upcast_type(obj,type); } if (TYPE(obj) == T_ARRAY) { return na_ary_to_nary_w_type(obj,type,cNArray); } return na_make_scalar(obj,type); } /* :nodoc: */ VALUE na_to_narray(VALUE obj) { if (IsNArray(obj)) { return obj; } if (TYPE(obj) == T_ARRAY) { return na_ary_to_nary(obj,cNArray); } return na_make_scalar(obj,na_object_type(obj)); } /* convert NArray to Array */ static VALUE na_to_array0(struct NARRAY* na, int *idx, int thisrank, void (*func)()) { int i, elmsz; char *ptr; VALUE ary, val; /* Create New Array */ ary = rb_ary_new2(na->shape[thisrank]); if (thisrank == 0) { ptr = NA_PTR( na, na_index_pos(na,idx) ); elmsz = na_sizeof[na->type]; for (i = na->shape[0]; i; --i) { (*func)( 1, &val, 0, ptr, 0 ); ptr += elmsz; rb_ary_push( ary, val ); } } else { for (i = 0; i < na->shape[thisrank]; ++i) { idx[thisrank] = i; rb_ary_push( ary, na_to_array0(na,idx,thisrank-1,func) ); } } return ary; } /* method: to_a -- convert itself to Array */ VALUE na_to_array(VALUE obj) { struct NARRAY *na; int *idx, i; GetNArray(obj,na); if (na->rank<1) return rb_ary_new(); idx = ALLOCA_N(int,na->rank); for (i = 0; irank; ++i) idx[i] = 0; return na_to_array0(na,idx,na->rank-1,SetFuncs[NA_ROBJ][na->type]); } static VALUE na_inspect_col( int n, char *p2, int p2step, void (*tostr)(), VALUE sep, int rank ) { VALUE str=Qnil, tmp; int max_col = 77; int sep_len = RSTRING_LEN(sep); if (n>0) (*tostr)(&str,p2); for (n--; n>0; --n) { p2 += p2step; (*tostr)(&tmp,p2); if (!NIL_P(sep)) rb_str_concat(str, sep); if (RSTRING_LEN(str) + RSTRING_LEN(tmp) + rank*4 + sep_len < max_col) { rb_str_concat(str, tmp); } else { rb_str_cat(str,"...",3); return str; } } return str; } /* * Create inspect string ... under construction */ VALUE na_make_inspect(VALUE val) { int i, ii, rank, count_line=0, max_line=10; int *si; struct NARRAY *ary; struct slice *s1; VALUE fs = rb_str_new(", ",2); GetNArray(val,ary); if (ary->total < 1) return rb_str_new(0, 0); /* Allocate Structure */ rank = ary->rank; s1 = ALLOCA_N(struct slice, rank+1); si = ALLOCA_N(int,rank); na_set_slice_1obj(rank,s1,ary->shape); /* Iteration */ na_init_slice(s1, rank, ary->shape, na_sizeof[ary->type]); i = rank; s1[i].p = ary->ptr; val = rb_str_new(0,0); for(;;) { /* set pointers */ while (i > 0) { --i; rb_str_cat(val, "[ ", 2); s1[i].p = s1[i].pbeg + s1[i+1].p; si[i] = s1[i].n; } rb_str_concat(val, na_inspect_col( s1[0].n, s1[0].p, s1[0].pstep, InspFuncs[ary->type], fs, rank )); /* rank up */ do { rb_str_cat(val, " ]", 2); if ( ++i == rank ) return val; } while ( --si[i] == 0 ); s1[i].p += s1[i].pstep; rb_str_concat(val, fs); rb_str_cat(val, "\n", 1); /* count check */ if (++count_line>=max_line) { rb_str_cat(val, " ...", 4); return val; } /* indent */ for (ii=i; ii= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Masahiro Tanaka"] s.date = "2016-02-11" s.description = "Numerical N-dimensional Array class" s.email = "masa16.tanaka@gmail.com" s.extensions = ["src/extconf.rb"] s.files = ["ChangeLog", "MANIFEST", "README.ja.md", "README.md", "SPEC.en.txt", "SPEC.ja.txt", "src/depend", "src/extconf.rb", "src/lib/narray/narray_ext.rb", "src/lib/narray/nmatrix.rb", "src/mkmath.rb", "src/mknafunc.rb", "src/mkop.rb", "src/na_array.c", "src/na_func.c", "src/na_index.c", "src/na_linalg.c", "src/na_random.c", "src/narray.c", "src/narray.def", "src/narray.h", "src/narray_local.h"] s.homepage = "http://masa16.github.io/narray/" s.licenses = ["Ruby"] s.rdoc_options = ["--title", "NArray", "--main", "NArray", "--exclude", "mk.*", "--exclude", "extconf\\.rb", "--exclude", "src/.*\\.h", "--exclude", "src/lib/", "--exclude", ".*\\.o", "--exclude", "narray\\.so", "--exclude", "libnarray\\.*"] s.require_paths = ["."] s.rubygems_version = "1.8.23" s.summary = "N-dimensional Numerical Array class for Ruby" if s.respond_to? :specification_version then s.specification_version = 2 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then else end else end end narray-0.6.1.2/MANIFEST0000644000175000017500000000144012745364057014153 0ustar uwabamiuwabamiChangeLog MANIFEST README.md README.ja.md SPEC.en.txt SPEC.ja.txt depend extconf.rb mkmath.rb mknafunc.rb mkop.rb na_array.c na_func.c na_index.c na_linalg.c na_random.c narray.c narray.def narray.h narray_local.h lib/narray/narray_ext.rb lib/narray/nmatrix.rb test/statistics.rb test/testarray.rb test/testbit.rb test/testcast.rb test/testcomplex.rb test/testfftw.rb test/testindex.rb test/testindexary.rb test/testindexset.rb test/testmask.rb test/testmath.rb test/testmath2.rb test/testmatrix.rb test/testmatrix2.rb test/testmatrix3.rb test/testminmax.rb test/testobject.rb test/testpow.rb test/testrandom.rb test/testround.rb test/testsort.rb test/teststr.rb test/testtrans.rb test/testwhere.rb bench/all.rb bench/bench.m bench/bench.py bench/bench.rb bench/dummy.m bench/dummy.py bench/dummy.rb narray-0.6.1.2/SPEC.en.txt0000644000175000017500000002412712745364057014725 0ustar uwabamiuwabami Ruby/NArray ver 0.6.0.7 (2013-02-01) by Masahiro TANAKA Class method: NArray.new(typecode, size, ...) create new NArray. initialize with 0. NArray.byte(size,...) 1 byte unsigned integer NArray.sint(size,...) 2 byte signed integer NArray.int(size,...) 4 byte signed integer NArray.sfloat(size,...) single precision float NArray.float(size,...) double precision float NArray.scomplex(size,...) single precision complex NArray.complex(size,...) double precision complex NArray.object(size,...) Ruby object all above method initialize with 0 or nil. NArray.to_na(array) convert to NArray NArray.to_na(string,type[,size,...]) NArray[...] NArray[1,5,10.0] #=> NArray.float(3):[1.0, 5.0, 10.0] NArray[1..10] #=> NArray.int(10):[1,2,3,4,5,6,7,8,9,10] Class constant: CLASS_DIMENSION # of dimension treated as data. 0 for NArray, 1 for NVector, 2 for NMatrix. NArray information self.dim Return the dimension = the number of indices self.rank same as dim self.shape Return the array of sizes of each index self.total Return the number of total elements Slicing Array - Index components: Integer, Range, Array, true. - Index order: FORTRAN type. a[ 1, 2, -1 ] element slicing. If negative, counts backward from the end. Element-dimensions are contracted. a[ 0..3, 4..1 ] extract in the range. If the former of the range is bigger, return elements in reversed order. a[ [1,3,2,4] ] an array with the elements of the indices. If `a' has multi-dimension but, in [], single index is specified, `a' is treated as a single dimension array. a[ 1, 2..3, [1,3,2,4], true ] compound index. This returns 3-dim array. a[] same as a.dup. a[ 0, true ] sams as a[0,0..-1]. `true' means all. a[ false, 0 ] same as a[true,true,0], if a is a 3-d array, `false' means ellipsis dimension. a[ mask ] masking. "mask" is a byte NArray with its length equal to that of "a". According to the value of each element of mask, the corresponding element in "a" is eliminated (when 0) or retained (when not 0). Example: a=NArray.float(2,2).indgen! p a[ a.lt 3 ] --> [ 0.0, 1.0, 2.0 ] (Here, a.lt 3 gives a byte NArray) (This is also done by a[ (a.lt 3).where ]) - A 2-or-more-dim array object with only one argument in `[ ]', is treated as a flat 1-d array. e.g.: a[3] is same as a[0,1] if a is 3x3 array. - self.slice(...) Same as self[...] but keeps the rank of original array by not elimiting dimensions whose length became equal to 1 (which self[] does). This is not the case with the 1-dimensional indexing and masking (same as []). Replacing Elements -- Same rule as slicing a[ 1, 2, 3 ] = 1 a[ 0..3, 1..4, 2..5 ] = 2 a[ [1,3,2,4], true ] = 3 a[] = 4 Same as a.fill!(4) a[0..2] = b[1..5] --> Error! due to different num of elements. a[1,2] = b[0..2,1..3] Storing elements from index [1,2] ( a[1,2]=b[0,1],a[2,2]=b[1,1],... ) a[0..2,0..3] = b[0..2,1] Storing repetitively ( a[0,0]=b[0,1],..,a[0,3]=b[0,1] ) Delete row/columns -- Complement of slice self.delete_at(...) Arguments are the same as the [] and slice methods see https://github.com/masa16/narray/issues/5 Filling values self.indgen!([start[,step]]) Generate index; Set values from 'start' with 'step' increment self.fill!(value) Fill elements with 'value' self.random!(max) Set random values between 0<=x NArray.float(3,3) a = NArray.float(3,1).indgen b = NArray.float(1,3).fill(10) c = a*b # --> NArray.float(3,3) -- size=1 dimension is extensible. Arithmetic operator -self self + other self - other self * other self / other self % other self ** other self.abs self.add! other self.sbt! other self.mul! other self.div! other self.mod! other Bitwise operator (only for integers) ~self self & other self | other self ^ other Comparison -- element-wise comparison, results in BYTE-type NArray; Note that not true nor false is returned. self.eq other (distinguish from == operator; see below ) self.ne other self.gt other self > other self.ge other self >= other self.lt other self < other self.le other self <= other self.and other element-wise condition. self.or other self.xor other self.not other self.all? true if all the elements are true. self.any? true if any element is true. self.none? true if none of the element is true. self.where Return NArray of indices where elements are true. self.where2 Return Array including two NArrays of indices, where elements are true and false, respectively. e.g.: idx_t,idx_f = (a>12).where2 Equivalence NArray[1] == NArray[1] #=> true NArray[1] == NArray[1.0] #=> true NArray[1].eql? NArray[1] #=> true NArray[1].eql? NArray[1.0] #=> false NArray[1].equal? NArray[1] #=> false a=b=NArray[1]; a.equal? b #=> true Statistics self.sum(dim,..) Summation self.cumsum Cumulative Summation (for 1-d array) self.prod(dim,..) Product (Multiply elements) self.cumprod Cumulative Produce (for 1-d array) self.mean(dim,..) Mean self.stddev(dim,..) Standard deviation self.rms(dim,..) Root mean square self.rmsdev(dim,..) Root mean square deviation self.min(dim,..) Minimum self.max(dim,..) Maximum note: * If dimensions are specified, statistics are performed on those dimensions and the rest dimensions are kept. * Range can be used. * If dimension is not specified, statistics are performed for all the elements. self.median(dim) Median in 0..dim (All dimensions if omitted) Sort self.sort(dim) Sort in 0..dim (All dimensions if omitted) self.sort_index(dim) Return index of Sort result. self[self.sort_index] equals to self.sort. Transpose self.transpose( dim0, dim1, .. ) Transpose array. The dim0-th dimension goes to the 0-th dimension of new array. Negative number counts backward. transpose(-1,1..-2,0) is replacement between the first and the last. Changing Shapes of indices self.reshape!(size,...) self.shape=(size,...) self.newdim=(dim) Insert new dimension with size=1 Reference to another NArray self.refer create NArray obj referring to another NArray self.reshape(size,...) same as self.refer.reshape! self.newdim(dim,...) same as self.refer.newdim! Reverse and Rotate self.reverse([dim,...]) Reverse array at axes self.rot90([k]) Rotate array by 90 degrees k times Type conversion self.floor Return integer NArray whose elements processed 'floor' self.ceil self.round self.to_f Convert NArray type to float self.to_i Convert NArray type to integer self.to_a Convert NArray type to Ruby-object self.to_s Convert NArray data to String as a binary data. self.to_string Convert NArray type to Ruby-object containing Strings as printed elements Iteration self.each {|i| ...} self.collect {|i| ...} self.collect! {|i| ...} Byte swap self.swap_byte swap byte order self.hton convert to network byte order self.ntoh self.htov convert to VAX byte order self.vtoh Boolean / mask related self.count_false count # of elements whose value == 0 (only for byte type) self.count_true count # of elements whose value != 0 (only for byte type) self.mask( mask ) same as self[ mask ], but exclusively for masking. Unlike [], a int or sint mask is accepted. Complex compound number self.real self.imag self.conj self.conj! self.angle atan2(self.imag, self.real) self.imag= other set imaginary part self.im multiply by imaginary unit NMath module sqrt(x) exp(x) log(x) log10(x) log2(x) atan2(x,y) sin,cos,tan sinh,cosh,tanh asin,acos,atan asinh,acosh,atanh csc,sec,cot csch,sech,coth acsc,asec,acot acsch,asech,acoth covariance (no idea why NMath::covariance doesn't work) FFTW module (separate module) fftw(x,[1|-1]) convol(a,b) convolution with FFTW NMatrix Subclass of NArray. First 2 dimensions are used as Matrix. Residual dimensions are treated as Multi-dimensional array. The order of Matrix dimensions is opposite from the notation of mathematics: a_ij => a[j,i] Methods: +,- enable if other is NMatrix. * Matrix product if other is NMatrix or NVector. Scalar product if other is Numeric or NArray. ex: NMatrix[[1,2],[3,4]] * [1,10] == NMatrix[ [[1,2],[3,4]], [[10,20],[30,40]] ] / Scalar division if other is Numeric or NArray. Solve Linear Equation with LU factorization if other is square NMatrix. a/b == b.lu.solve(a) transpose transpose Matrix dimensions if argument omitted. diagonal(val) diagonal!(val) set val to diagonal elements. (set 1 if omitted) unit set 1 to diagonal elements. inverse Inverse matrix. lu compute LU factorization. return NMatrixLU class object. NVector Subclass of NArray. First 1 dimension is used as Vector. Residual dimensions are treated as Multi-dimensional array. Methods: +,- enable if other is NVector. * Matrix product if other is NMatrix. Inner product if other is NVector. Scalar product if other is Numeric or NArray. / Scalar division if other is Numeric or NArray. Solve Linear Equation with LU factorization if other is square NMatrix. v/m == m.lu.solve(v) NMatrixLU Created by NMatrix#lu method. Including LU (NMatrix) and pivot (NVector). Methods: solve(other) Solve with the result of LU factorization. other should be NMatrix or NVector instance. narray-0.6.1.2/ChangeLog0000644000175000017500000005417212745364057014606 0ustar uwabamiuwabami2016-02-11 Masahiro TANAKA * nmatrix.rb, narray_ext.rb: moved from lib/ to lib/narray/ * ver 0.6.1.2 2013-03-16 Masahiro TANAKA * narray.c (Init_narray): add map, map! Thanks to Michael Macias. 2013-02-27 Masahiro TANAKA * Rakefile: use rubygems/package_task. * narray.gemspec: add --exclude in rdoc_options. * ver 0.6.0.8 2013-02-26 Masahiro TANAKA * test/ld.rb: add require "rubygems". * narray.gemspec: change gem directory from src to ext. * narray.c: avoid warnings in require "complex" and rdoc parsing. 2013-02-13 Masahiro TANAKA * lib/narray_ext.rb: new method: NArray.cast 2013-02-01 Masahiro TANAKA * lib/narray_ext.rb: eql? hash methods implemented. * ver 0.6.0.7 2013-01-31 Masahiro TANAKA * na_raondom.c: unuse u_int16_t * mknafunc.rb, mkmath.rb, mkop.rb, na_linalg.c: bug: duplicated definition of asinh/acosh/atanh, typecast warning (mingw/mswin) * ver 0.6.0.6 2013-01-30 Masahiro TANAKA * narray.c (na_check_class_narray): use Module#<= instead of rb_mod_ancestors * na_random.c, na_linalg.c: avoid warnings of signed <=> unsigned comparison * ver 0.6.0.5 2012-12-07 geoffyoungs * narray.c (na_check_class_narray): Use ruby methods to check class ancestors, instead of m_tbl directly * ver 0.6.0.2 2012-09-20 Masahiro TANAKA * lib/narray_ext.rb (reverse,rot90): new method 2012-09-01 ohai * lib/narray_ext.rb: Change NMath#recip into a module function. 2011-08-29 Masahiro TANAKA * narray.c (na_alloc_struct): check array size (zero/negative). * ver 0.6.0.1 2011-08-27 Masahiro TANAKA * narray.c (na_alloc_struct): check array size (overflow). * extconf.rb (#install_rb): --export-all option for mingw. * ver 0.6.0.0 2011-02-04 Masahiro TANAKA * na_func.c (na_prod, na_prod_body, na_cumprod, na_cumprod_bang): New method. 2010-01-04 David MacMahon * mkop.rb, na_func.c, na_linalg.c, narray_local.h: Add NArray#mod! method Also adds NArray#mod as an alias for NArray#%. 2010-01-04 David MacMahon * mkop.rb: Fix divide-by-zero bug in % operator Prior to this fix, the following would crash Ruby with a floating point exception (at least on Mac OS X 10.6)... 1 % NArray[0] Now that code raises ZeroDivisionError which can be rescued. 2010-01-04 David MacMahon * Rakefile: Add Rakefile for easy gem creation Just run "rake gem" to create the gem file in the pkg/ subdirectory. Added .gitignore file to ignore pkg/ subdirectory. 2011-01-04 sgwong * extconf.rb: failure due to the change of $DLDFLAGS in ruby1.9 2010-12-14 Masahiro TANAKA * lib/nmatrix.rb (NMatrix#diagonal!): - failed due to spec change of NArray.to_na. Thanks to M. Kikkawa. * ver 0.5.9p9 2010-09-13 David MacMahon * narray.c (na_where2): - Convert to NA_BYTE by calling "obj.ne(0)" * ver 0.5.9p8 2010-07-12 Masahiro TANAKA * narray.c (na_s_to_na): - improve argument check in NArray.to_na 2010-04-30 Masahiro TANAKA * narray.c (na_s_to_na): - the number of arguments was not checked. Thanks to S D for report. 2010-01-16 Masahiro TANAKA * na_index.c (na_index_analysis): - access out-of-bounds "struct slice" array. * SPEC.en, SPEC.ja: - fix wrong explanation in count_false/true. * na_random.c (na_random): - modify random method not to change itself. * lib/narray_ext.rb: - modify randomn! method to replace itself. Thank Yusuke ENDOH for report and comments. 2009-06-14 Masahiro TANAKA * narray.h: include sys/stdint.h rather than sys/types.h for C99 confomance * ver 0.5.9p7 2009-05-20 Masahiro TANAKA * lib/narray_ext.rb (mean, stddev,rms,rsmdev,covariance): - swith to DFLOAT type if integer array. - thanks to Philip Silva for report. 2009-03-11 Masahiro TANAKA * na_index.c (na_aset_single_dim): - add check of storing empty array. - thanks to NISHI Takao for report. 2008-11-05 Masahiro TANAKA * work with ruby 1.9.1 preview1 - use RARRAY_*** macros instead of struct RArray. - follow changes in Complex feature. - change oprator arg of coerce_rev func : id -> symbol - modify test scripts. * na_array.c (na_do_mdai): - bug fix in counting narray's rank. * ver 0.5.9p6 2008-06-10 Masahiro TANAKA * bench/: new sophisticated benchmark script. * ver 0.5.9p5 2008-05-27 Jose M * na_array.c, na_index.c, na_random.c, na_func.c: * na_linalg.c, narray.c, mkmath.rb, mkop.rb: change var++ to ++var: make NArray perform faster. 2008-05-24 Hiroki Motoyoshi * mkmath.rb: fix bug in powOO. 2008-04-02 David MacMahon * na_func.c: new methods: conj!, conjugate! 2008-01-11 David MacMahon * lib/narray_ext.rb (stddev): fix for complex NArrays. * lib/narray_ext.rb (rms, rmsdev): new methods. 2008-01-28 Masahiro TANAKA * na_array.c (na_range_to_sequence, na_do_mdai): * na_index.c (na_index_range): change in internal structure of Ruby 1.9 Range object. Thanks to Hargobind Khalsa. * ver 0.5.9p4 2007-12-27 Masahiro TANAKA * narray_local.h, narray.c, na_array.c: use RSTRING_PTR, RSTRING_LEN for Ruby 1.9.0. * ver 0.5.9p3 2007-12-11 Masahiro TANAKA * mkop.rb: omit precision in format "%g" for InspS/D/X/C. Thanks to Shigenori OTSUKA at kyoto-u. * ver 0.5.9p2 2007-10-09 David MacMahon * narray.h, mkop.rb: bug in NArray::NARRAY_VERSION and InspX. 2006-08-09 Masahiro TANAKA * na_fftw.c, extconf.rb, narray.c (Init_narray): Remove FFTW2 support; it is a separete module. * ver 0.5.9 2006-08-08 Masahiro TANAKA * na_index.c (na_index_test, na_aset_single_dim): `nv[1] = nu' should work if nv and nu are NVector. `NA_IsNArray(nu)' is used for checking NArray. Thanks to sun@titech. 2006-08-08 Masahiro TANAKA * narray_local.h, mknafunc.rb (mksortfuncs): Argument type of comparison function passed to qsort should be `const void *'. Thank Daniel Berger for report. 2006-07-30 Masahiro TANAKA * narray.h, narray.c: Do not declare external variables of cNArray, na_sizeof in narray.c. Thank Daniel Berger for report. 2006-03-22 Masahiro TANAKA * lib/narray_ext.rb (mean, stddev): Fix to work with NVector/NMatrix classes. Thank Stephen Hill for report. 2005-09-13 Charlie Mills * mkop.rb, na_func.c, narray_local.h: Make NArray#eq more robust. 2005-08-05 Masahiro TANAKA * mkmath.rb (na_math_func): Bug: In NMath functions, Float class arguments have been converted to SFLOAT type. Thank Yuhei Kuratomi for his report. Spec Change: Calculate and return as DFLOAT type if an integer argument is given to NMath functions. * na_func.c (na_math_atan2): NMath.atan2() accepts other objects than NArray class. Treat as DFLOAT for integer arguments. * ver 0.5.8 2005-01-25 Masahiro TANAKA * na_array.c (na_ary_to_nary_w_type): Bug: "type" is not initialized when an array is empty. 2005-01-07 Masahiro TANAKA * narray.h: #define NARRAY_VERSION NARRAY_VERSION_CODE * narray.c: new constant: NArray::NARRAY_VERSION 2004-11-10 Masahiro TANAKA * na_random.c: Fix infinite loop due to gcc bug?; "int32_t x; x>>=32;" unvaried although 0 expected. Thanks to David G. Andersen. * lib/narray_ext.rb (randomn): Raise error if NArray type is other than float. * ver 0.5.7p4 2004-09-22 Masahiro TANAKA * nimage/nimage.c: Argument type of rb_str2cstr is changed. Use RSTRING()->ptr & RSTRING()->len. Thanks to Ara Howard. 2004-06-28 KOSHIRO Tsuyoshi * extconf.rb: generate libnarray.a for Cygwin + Ruby 1.8.1. * ver 0.5.7p3 2004-02-19 Masahiro TANAKA * na_array.c (na_free_mdai): memory free bug: xfree(mdai->type); added. * ver 0.5.7p2 2004-01-04 Masahiro TANAKA * extconf.rb: narray.h, narray_conf.h was not installed on ruby-1.8.x * narray.c: NArray-GC is disabled. * nimage/nimage.c, test/testwhere.rb, speed/[mybench.rb,mul_rep.rb]: fix ruby-1.8.x incompatibility * ver 0.5.7p1 2003-03-04 Masahiro TANAKA * narray.c (na_alloc_struct): NArray-specific GC is enabled for ruby-1.8.0. * ver 0.5.7 2003-03-03 Masahiro TANAKA * na_random.c: created. * lib/narray_ext.rb (rank_total): Array#indices is obsolete. use Array#select. Default `to_a' will be obsolete. * lib/nmatrix.rb: Object#type is obsolete. use Object#class. 2003-03-01 Masahiro TANAKA * narray_ext.rb (swap_byte,hton,htov): removed. * mkop.rb, mknafunc.rb, na_func.c, narray_local.h: add C-version of swap_byte, hton, htov. 2003-02-28 Masahiro TANAKA * extconf.rb: do not add "--output-lib libnarray.a" to link options if Cygwin with Ruby 1.8.0. Thank MoonWolf for the note. 2002-11-25 Masahiro TANAKA * na_func.c (na_cumsum_bang,na_cumsum_): created. Thank Jon Davidson for the proposal. 2002-09-15 Masahiro TANAKA * na_array.c (na_do_mdai): Index is not `i' but `j' in recursive array check. Thank Ara Howard for the bug report. 2002-05-30 WATANABE Hirofumi * extconf.rb: to build in another directory than source tree. * depend: ditto. 2002-05-18 Masahiro TANAKA * lib/narray_ext.rb (NArray#==): return false unless other is NArray. * narray.h, narray_local.h, narray.c: move na_sizeof variable from narray_local.h to narray.h. const keyword added. Thanks to Horinouchi-san. * narray.c (na_get_typecode): change to public method. * narray.c (na_sizeof,na_typestring): const keyword added. * mkop.rb : ditto. * na_func.c (na_unary_func): ditto. * mkmath.rb : dismiss sincos() 2002-04-11 Masahiro TANAKA * mkmath.rb (asinh,acosh,atanh): better precision. 2002-04-10 Masahiro TANAKA * mkop.rb (SetFucs): should use INT2NUM to extract 32-bit int. Thanks to Kozuka-san. 2002-03-26 Masahiro TANAKA * narray.def: remove unused entry. Thanks to Watanabe-san. 2002-03-24 Masahiro TANAKA * na_array.c: New multi-dimentional array investigation is introduced. Scan array only once and check recursive array. * narray.h, narray_local.h: Local definisions in narray.h are moved into narray_local.h. * ver 0.5.6 2002-03-17 Masahiro TANAKA * nmatrix.rb (NMatrix#*): accept Array as an argument. 2002-02-26 Masahiro TANAKA * na_array.c (na_copy_ary_to_nary): accept Range as a sequence. 2002-02-06 Masahiro TANAKA * narray.c, na_func.c, na_index.c, na_linalg.c, na_fftw.c, mkmath.rb: add volatile keyword instead of na_touch_object() function. 2002-01-25 Masahiro TANAKA * na_array.c (na_to_array0): Bug: GC fails if ary->len is set in advance. Thanks to Bil Kleb. 2001-12-30 Masahiro Tanaka * extconf.rb: Modify install_rb to install narray.h, narray_config.h. * na_index.c (na_aref,na_aset): Mask support. Thanks to T.Horinoichi. * mkop.rb: Mask functions added. * narray.h: Macros added. * narray.def: created. * ver 0.5.5 2001-11-20 Takeshi Horinouchi * narray.c (na_get_typecode): Bug: "!" needed at strncmp. * Mask support in [], []=. na_aref/aset_mask(), na_count_true/false() added. Methods mask, count_true, count_false added. * test/testmask.rb: created. 2001-07-01 Masahiro Tanaka * narray.h: introduce na_index_t. * na_func.c (na_init_slice,na_loop_index_ref,na_loop_general): change to na_index_t. * na_index.c: modify EXCL(range) to use excule_end?. * na_index.c (na_aref_single_dim): remain array if sl->step!=0. i.e., a[0..0] results in 1-element array. * na_func.c (Init_na_funcs): alias image, arg, conjugate. * ver 0.5.4 2001-06-30 Masahiro Tanaka * extconf.rb: check sys/typedef.h, u_int8_t, int16_t, int32_t. generating narray_config.h. * narray.h: conditional typedef. define NARRAY_H. * na_func.c (Init_na_funcs): change == to eq. add gt,ge,lt,le. * lib/narray_ext.rb: new entry: ==, all?, any?, none?. * mkop.rb: new entry: conditional XOR. * na_func.c (na_cond_xor): ditto. * narray.h: ditto. 2001-06-05 Masahiro Tanaka * na_index.c (na_aref_body): NVector#[] should return NVector class even when single argument of range/array. Thanks to Daishi Harada. * narray.h (na_class_dim): delete redundant ";" * extconf.rb: delete config_dir("narray"), add dir_config("fftw"). 2001-06-04 Masahiro Tanaka * na_index.c (na_aref_multi_dim_single_elm): do not change class even if a[0..0,0..0] for NMatrix. Thanks to Daishi Harada. * narray.c (na_inspect): rb_str_cat(str,": \n",4); not 4, but 3. Thanks to Matju. 2001-05-11 Masahiro Tanaka * nimage/extconf.rb: add dir_config("x11"). rm have_header. 2001-04-10 Masahiro Tanaka * narray.h: exclude typedef int32_t,int16_t,u_int8_t for Mac OS X. Thanks to T.Yamamoto. * mkmath.rb (atan,atanh): avoid non-constant initializer for complex. 2001-04-03 Masahiro Tanaka * na_array.c (na_search_rank): ignore empty array. * na_array.c (na_copy_ary_to_nary): ignore empty array and nil. * ver 0.5.3 2001-04-02 Masahiro Tanaka * narray.c (na_to_s): bug: na_sizeof[] is necessary. Thank matju for report. 2001-01-29 Masahiro Tanaka * mkop.rb (Angl): added. * na_func.c (na_angle): added. Thank M.Tagusai for proposal. * ver 0.5.2 2001-01-21 Masahiro Tanaka * mkop.rb, mkmath.rb: loop-end condition changed from n>0 to n. 5% speed up for multiplication of double. 2001-01-20 Masahiro Tanaka * mkop.rb (DivU,DivB): raise error if divided by 0. 2001-01-19 Masahiro Tanaka * mkop.rb (round): bug: has omitted the case of 0. 2001-01-18 Masahiro Tanaka * narray.c (na_is_empty): added. * na_func.c (na_exec_unary,na_exec_binary,na_make_object_extend): enable operation of empty array. 2001-01-17 Masahiro Tanaka * na_index.c (na_aset_array_index): allow a[[]]=1. 2001-01-14 Masahiro Tanaka * na_index.c (na_ary_to_index): bug: should raise error if < -n. 2001-01-13 Masahiro Tanaka * na_func.c (na_unary_func): should call func of self-type. Thanks to Matju. 2001-01-06 Masahiro Tanaka * narray.c (na_s_new_int): check argc==0. Thanks to Matju. 2000-12-10 Masahiro Tanaka * ver 0.5.1 2000-12-11 Masahiro Tanaka * narray.c (na_alloc_struct): cope with empty array. * na_func.c (na_exec_unary,na_shape_max_2obj): empty check. 2000-12-10 Masahiro Tanaka * narray.c (na_random): disable initalizing seed. * na_touch_object created. * free -> xfree. Thanks to Naoki Matsumoto. 2000-12-07 Masahiro Tanaka * ver 0.5.0.p2 * fix problems for VC++. Thanks to Naoki Matsumoto. * mkmath.rb: create asinh, acosh, atanh missing in VC++. * mkop.rb (TpErrI): return int after rb_raise(). * narray.h: max() -> NA_MAX(), swap() -> NA_SWAP(). * narray.c (na_get_typecode): return int after rb_raise(). * na_func.c (na_sort,na_sort_index): fix function decl. for qsort. 2000-12-01 Masahiro Tanaka * ver 0.5.0.p1 * lib/nmatrix.rb (NVector#+,-): should change Class to NArray before calling super. Thanks to Kenya OGATA. * na_index.c (EXCL): follow the change of EXCL() in 1.6.2. Thanks to Robert Feldt. 2000-11-25 Masahiro Tanaka * ver 0.5.0 * No Log between 0.5.0 and 0.3.5.p1. Sorry. 2000-10-14 Masahiro Tanaka * narray.c (na_wrap_struct_class): na_mark_ref, na_mark_obj. 2000-10-05 Masahiro Tanaka * nmatrix.rb: created. * too many changes are applied to source codes. ^^; 2000-10-03 Masahiro Tanaka * na_index.c (na_shrink_rank): created for general purposes. * narray.c (na_reshape): use new na_shrink rank. recognize "true" argument. * lib/narray_ext.rb: use new feature of reshape 2000-10-02 Masahiro Tanaka * na_index.c (na_make_slice_aset_fill): created. * lib/narray_ext.rb (flatten): no more use dup. * na_func.c (na_s_mul_sum): created. * narray.c (na_wrap_struct): wrap with referring class. (na_ref_alloc_struct): created. (na_reshape_ref,na_newrank_ref): created. (na_inspect): print class name. * narray.h: add "VALUE obj" elmt to "struct NARRAY". 2000-09-29 Masahiro Tanaka * mkopfunc.rb (mulacmfunc): created. * mkfuncs.rb: rewrite with %w(). (mktrifunc): renamed from mkcmpfunc. accept block. * na_loop.c (na_slice_set_extend): change arguments. * na_func.c (na_mul_acm,na_shape_max_3obj): created. (na_exec_trifunc_extend): a1 can be shrinkable. 2000-09-28 Masahiro Tanaka * lib/narray_ext.rb (is_ineger?,is_complex?): -> ineger?, complex?. 2000-09-27 Masahiro Tanaka * na_index.c (na_index_analysis): add false dimension. * narray.c (na_clone): renamed from ns_dup. 2000-09-04 Masahiro Tanaka * ver 0.3.5.p1 * narray.c, na_array.c, na_func.c, narray.h, mknmath.rb remove unused variables and functions. (-Wall check) (Thanks to Robert Feldt) * lib/narray_ext.rb (convol): put in module FFTW. (Thanks to Robert Feldt) 2000-09-01 Masahiro Tanaka * ver 0.3.5 * narray.c (na_random): remove `seed' argument. add rand(). 2000-08-25 Masahiro Tanaka * lib/narray_ext.rb: create randomn (Box-Muller). 2000-08-23 Masahiro Tanaka * na_index.c (aref, aset): categolize procedures with arguments. 2000-08-02 Masahiro Tanaka * lib/narray_ext.rb: create FFTW.convol. 2000-08-01 Masahiro Tanaka * na_index.c (na_aref_array_index): bug fix: free index memory. 2000-07-28 Masahiro Tanaka * ver 0.3.4 * mkcmpfunc.rb : remove <=> with complex. add ~. * mkopfunc.rb, na_func.c: add &, |, ^. 2000-07-27 Masahiro Tanaka * mknmath.rb, lib/narray_ext.rb: add covariance. * mkopfunc.rb (data_mod): add imag=. * mksetfunc.rb: add im (ImagMul). * mknmath.rb, lib/narray_ext.rb: add trigonometric functions. 2000-07-26 Masahiro Tanaka * na_func.c (na_exec_math_func): extract object if argument is non-array. * lib/narray_ext.rb: add mean, stddev. 2000-07-21 Masahiro Tanaka * na_index.c (na_aset): bug fix for empty index, etc. * na_func.c (na_shape_check): raise error if empty array. (na_sum_body,na_min,na_min,na_transpose): better arg-parse. (na_arg_to_rank,na_accum_set_shape,na_accum_shrink_rank): created. 2000-07-20 Masahiro Tanaka * narray.c (na_str_to_na): more size check. * na_index.c (na_aset): allow if src-ary has smaller dims. * narray.c (na_to_narray): moved from na_array.c * lib/narray_ext.rb: created. swap_byte, hton etc. * narray.c (Init_narray): change type=>typecode. add NArray.dfloat, NArray::DFLOAT etc. add element_size, to_binary, to_type_as_binary. 2000-07-18 Masahiro Tanaka * na_loop.c (na_loop_general): created. na_loop_index is obsolete. 2000-07-17 Masahiro Tanaka * na_func.c (na_sum_body,na_accum): created. * na_index.c (na_slice): created. * na_index.c (na_aref,na_aset): if the argument is an array, methods [],[]= return same shape as the array. e.g, a[[[0,1],[2,3]]] creates 2-D array. * na_index.c (na_serialize_struct,na_aref_aryindex,na_aref_single): Created. 2000-07-16 Masahiro Tanaka * na_func.c (na_transpose_bifunc,na_transpose), test/testtrans.rb: Created. 2000-07-15 Masahiro Tanaka * ver 0.3.3 * na_func.c (na_sort,na_sort_index,na_sort_number): Created. * mkfuncs.rb (mksortfunc): Created. * test/testsort.rb: Created. 2000-07-14 Masahiro Tanaka * narray.c (Init_narray), narrah.h: introduce NArrayScalar class. * narray.c (na_coerce), na_func.c (na_bifunc): better casting. 2000-07-11 Masahiro Tanaka * mk*.rb, depend: include code-generating scripts in distribution. * na_func.c, mkopfunc.rb: rename sub! => sbt!. * mkfuncs.rb: fix to work for Ruby ver 1.5.4. 2000-07-10 Masahiro Tanaka * na_array.c: rename na_to_narray1 to na_ary_to_narray * na_array.c: reduce GC problem; delay registration of objects. change return value of na_to_narray0 from VALUE to struct NARRAY * reflect in na_ary_to_na, na_ary_to_na, na_ary_to_narray. * narray.h: add GetOrMakeNArray(obj,ary), FreeMadeNArray(obj,ary) * narray.c, na_index.c, na_func.c, na_fftw.c: change na_to_narray0 to GetOrMakeNArray/FreeMadeNArray. * narray.c (na_free): free memory of itself structure. * narray.c (na_mark): pass pointer to rb_gc_mark. * na_array.c (na_make_inspect): return if total<0. * na_index.c (na_ary_to_index, na_aref, na_aset): judge whether empty array. * naimage/demo/mandel.rb: Now no need for checking size. * test/testindex*.rb: print more description. 2000-07-05 Masahiro Tanaka * ver 0.3.2 * Create NImage library narray-0.6.1.2/README.md0000644000175000017500000000252012745364057014301 0ustar uwabamiuwabami# Ruby/NArray * ver 0.6.1.0 (2014-06-02) * [Home page](http://masa16.github.io/narray/) * [GitHub Repository](https://github.com/masa16/narray) * [RubyGems](https://rubygems.org/gems/narray) * [NArray method list](https://github.com/masa16/narray/blob/master/SPEC.en.txt) ## NArray Features: * Fast and easy calculation for large numerical array. * Accepting Elements: 8,16,32 bit integer, single/double float/complex, Ruby Object. * Easy extraction/substitution of array subset, using assignment with number, range, array index. * Operator: +, -, *, /, %, **, etc. * NMath: Mathematics functions. * FFTW version 2 or 3 is separately supported. * Ruby/PGPLOT: Graphics library interface (separately distributed) X-Y Graph, Histogram, Contour map, Image map, etc. * NArray is similar to: * Python/NumPy, Perl/PDL, Yorick, IDL * NArray is far from completed! * Experimental! Specification may be changed. * Far from completed. * Bugs may be included. * No document. ## Installation ruby extconf.rb make make install ## Tested Platform * ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux] * gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ## License This program is free software. You can distribute/modify this program under the same terms as Ruby itself. NO WARRANTY. ## Author Masahiro TANAKA