Numo::NArray の使い方
デバッグ系
inspect
人間向け表記
NArray[5, 6].inspect # => "Numo::Int32#shape=[2]\n[5, 6]"
.inspect_cols=, .inspect_cols
inspect 時の幅を設定する
v = NArray.inspect_cols # => 80
NArray.inspect_cols = 16 # => 16
Int8.new(8).seq.inspect # => "Numo::Int8#shape=[8]\n[0, 1, 2, ...]"
NArray.inspect_cols = v
.inspect_rows=, .inspect_rows
inspect 時の高さを設定する
v = NArray.inspect_rows # => 20
NArray.inspect_rows = 2 # => 2
Int8.new(3, 2).seq.inspect # => "Numo::Int8#shape=[3,2]\n[[0, 1], \n [2, 3], \n ..."
NArray.inspect_rows = v
.debug=
デバッグ表示の切り替え
NArray.debug = true
# Int8.new.seq
NArray.debug = false
NArray.debug rescue $! # => #<NoMethodError: undefined method `debug' for Numo::NArray:Class>
debug_info
デバッグ情報を表示する
# Int8[5, 6].debug_info # => nil
NArray.debug = true
にしなくても表示する
.profile, .profile=
?
NArray.profile # => 0.0
NArray.profile = 1 # => 1
NArray.profile # => 1.0
生成
.new
次元を指定して作る
a = Int8.new(2, 3) # => Numo::Int8#shape=[2,3](empty)
空の状態では参照できない
a[0] rescue $! # => #<RuntimeError: cannot read unallocated NArray>
.[]
値を渡して作る
Int8[5, 6].inspect # => "Numo::Int8#shape=[2]\n[5, 6]"
Int16[5, 6].inspect # => "Numo::Int16#shape=[2]\n[5, 6]"
Int32[5, 6].inspect # => "Numo::Int32#shape=[2]\n[5, 6]"
Int64[5, 6].inspect # => "Numo::Int64#shape=[2]\n[5, 6]"
SFloat[5, 6].inspect # => "Numo::SFloat#shape=[2]\n[5, 6]"
DFloat[5, 6].inspect # => "Numo::DFloat#shape=[2]\n[5, 6]"
NArray[] を使うと適切な型が自動的に決まる
NArray[5].class # => Numo::Int32
NArray[10000000000].class # => Numo::Int64
NArray[5.0].class # => Numo::DFloat
NArray[1.to_c].class # => Numo::DComplex
NArray[true].class # => Numo::Bit
NArray["a"].class # => Numo::RObject
.cast
値を渡して作る
Int8.cast([5, 6]).to_a # => [5, 6]
Int8.cast(Int64[5, 6]).to_a # => [5, 6]
引数は1つだけなところが .[] と異なる
Int8.cast(5, 6) rescue $! # => #<ArgumentError: wrong number of arguments (given 2, expected 1)>
Int8[5, 6].to_a # => [5, 6]
cast_to
他の NArray から作る
Int8[5, 6].cast_to(Int64) # => Numo::Int64#shape=[2]
元を破壊しない
この2つは同じ意味
Int64.cast(Int8[5, 6]) # => Numo::Int64#shape=[2]
Int8[5, 6].cast_to(Int64) # => Numo::Int64#shape=[2]
.zeros
全部 0 で作る
Int8.zeros(5).to_a # => [0, 0, 0, 0, 0]
.ones
全部 1 で作る
Int8.ones(5).to_a # => [1, 1, 1, 1, 1]
.linspace
線型で作る
Int8.linspace(0, 100, 3).to_a # => [0, 50, 100]
.logspace
累乗で作る
DFloat.logspace(2, 4, 3).to_a # => [100.0, 1000.0, 10000.0]
[10.0**2, 10.0**3, 10.0**4] # => [100.0, 1000.0, 10000.0]
Int64.logspace(2, 4, 3) rescue $! # => #<NoMethodError: undefined method `logseq' for Numo::Int64#shape=[3](empty):Numo::Int64>
.parse
文字列から作る
NArray.parse(<<~EOT).to_a # => [[1, 2, 3], [4, 5, 6]]
1 2 3
4 5 6
EOT
カンマ区切りの場合
NArray.parse("1, 2, 3", split1d: ",").to_a # => [[1, 2, 3]]
.asarray
いろんな型の差異を吸収して NArray 化する
NArray.asarray(NArray[5, 6]) # => Numo::Int32#shape=[2]
NArray.asarray([5, 6]) # => Numo::Int32#shape=[2]
NArray.asarray(5..6) # => Numo::Int32#shape=[2]
NArray.asarray(5) # => Numo::Int32#shape=[1]
NArray.asarray(5, 6) rescue $! # => #<ArgumentError: wrong number of arguments (given 2, expected 1)>
NArray.asarray("A") rescue $! # => #<TypeError: invalid type for NArray>
.eye
単位行列を作る
a = Int8.eye(3).to_a
a[0] # => [1, 0, 0]
a[1] # => [0, 1, 0]
a[2] # => [0, 0, 1]
.new_like
値から「未割り当て」の NArray を作る
NArray.new_like([1, 2]) # => Numo::Int32#shape=[2](empty)
NArray.new_like([1.0, 2.0]) # => Numo::DFloat#shape=[2](empty)
Int64.new_like([1, 2]) # => Numo::Int64#shape=[2](empty)
.[] や .cast と似ているが値は入っていない
埋める系
全部レシーバを破壊してしまうので注意する
seq, indgen
連番で埋める
a = Int8.new(4)
a.seq # => Numo::Int8#shape=[4]
a.to_a # => [0, 1, 2, 3]
元を破壊する
1 + i
Int8.new(4).seq(1).to_a # => [1, 2, 3, 4]
10 + i * 2
Int8.new(4).seq(10, 2).to_a # => [10, 12, 14, 16]
fill
塗り潰す
a = Int8.new(3)
a.fill(5)
a.to_a # => [5, 5, 5]
元を破壊する
store
指定の値の羅列で埋める
a = Int8.new(3)
a.store(5)
a.to_a # => [5, 5, 5]
要素が一つだと fill と変わらない。元を破壊する。
配列の場合は要素数が合っていなくても 0 で埋めたり切り捨てたりする
Int8.new(2).store([5]).to_a # => [5, 0]
Int8.new(2).store([5, 6]).to_a # => [5, 6]
Int8.new(2).store([5, 6, 7]).to_a # => [5, 6]
だいたいビューに対して行う
a = Int8.ones(5)
a[1..3] # => Numo::Int8(view)#shape=[3]
a[1..3].store(8) # => Numo::Int8(view)#shape=[3]
a.to_a # => [1, 8, 8, 8, 1]
logseq
べき乗で埋める
a = DFloat.new(3)
a.logseq(0, 2)
a.to_a # => [1.0, 100.0, 10000.0]
10**(0 + 0 * 2) # => 1
10**(0 + 1 * 2) # => 100
10**(0 + 2 * 2) # => 10000
元を破壊する
Int8.new(3).logseq(0, 2) rescue $! # => #<NoMethodError: undefined method `logseq' for Numo::Int8#shape=[3](empty):Numo::Int8>
eye
単位行列にする
a = Int8.new(3, 3).seq
a.eye
a.to_a[0] # => [1, 0, 0]
a.to_a[1] # => [0, 1, 0]
a.to_a[2] # => [0, 0, 1]
元を破壊する
乱数
rand
乱数で埋める
a = DFloat.new(2)
a.rand
a.to_a # => [0.061754467473337606, 0.3730667918557394]
a.rand(5)
a.to_a # => [3.974076127383806, 1.0052107667404373]
元を破壊する
rand_norm
正規乱数で埋める
a = DFloat.new(2)
a.rand_norm
a.to_a # => [-0.8028018065626139, -0.32610562028036544]
a.rand_norm(5)
a.to_a # => [5.282921532942489, 6.684267658020805]
元を破壊する
Int64.new(2).rand_norm rescue $! # => #<NoMethodError: undefined method `rand_norm' for Numo::Int64#shape=[2](empty):Numo::Int64>
.srand
種を設定する
NArray.srand # => nil
NArray.srand(0) # => nil
次元を維持して作る
new_fill
新しく指定値で塗り潰したのを返す
a = Int8.new(3)
a.new_fill(1).to_a # => [1, 1, 1]
a.to_a rescue $! # => #<RuntimeError: cannot read unallocated NArray>
元を破壊しない
new_narray
shape を維持して新しい NArray を返す
a = Int8.new(3).seq
a.new_narray # => Numo::Int8#shape=[3](empty)
以下と同じ
a.class.new(a.shape) # => Numo::Int8#shape=[3](empty)
new_ones
新しく1で塗り潰したのを返す
a = Int8.new(3).seq
a.new_ones.to_a # => [1, 1, 1]
new_zeros
新しく0で塗り潰したのを返す
a = Int8.new(3).seq
a.new_zeros.to_a # => [0, 0, 0]
演算
数値に対する構文とほぼ同じ
a = NArray[1, 2]
b = NArray[3, 4]
(a + b).to_a # => [4, 6]
(a - b).to_a # => [-2, -2]
(a * b).to_a # => [3, 8]
(a / b).to_a # => [0, 0]
(a % b).to_a # => [1, 2]
a.divmod(b).map(&:to_a) # => [[0, 0], [1, 2]]
(a**b).to_a # => [1, 16]
(-a).to_a # => [-1, -2]
(-a).abs.to_a # => [1, 2]
右辺があるメソッドは右辺が整数でもよいし入れ替えても動く
(a * 10).to_a # => [10, 20]
(10 * a).to_a # => [10, 20]
inplace
inplace 経由で演算するとなぜか元を更新できる
inplace
元を更新する (重要)
a = Int64[5, 6]
a.to_a # => [5, 6]
a.object_id # => 500
a.inplace * 10 # => Numo::Int64(view)#shape=[2]
a.to_a # => [50, 60]
a.object_id # => 500
結果的には次と同じだけど inplace を使った方が速い
a = Int64[5, 6]
a.object_id # => 520
a *= 10
a.to_a # => [50, 60]
a.object_id # => 540
inplace!
inplace の破壊版
a = Int64[5, 6]
a.inplace!
a *= 10
a.to_a # => [50, 60]
out_of_place! のし忘れに注意する
out_of_place!, not_inplace!
inplace を解除する
a = Int8[5, 6]
a.inplace!
a * 10
a.to_a # => [50, 60]
a.out_of_place!
a * 10
a.to_a # => [50, 60]
小数
ceil
上に近い整数 (を表す浮動小数点値を返す)
DFloat[5.1, 5.9].ceil.to_a # => [6.0, 6.0]
floor
下に近い整数
DFloat[-1.1, -1.9].floor.to_a # => [-2.0, -2.0]
round
四捨五入
DFloat[2.4, 2.5, 2.51].round.to_a # => [2.0, 3.0, 3.0]
DFloat[0.1234].round(2) rescue $! # => #<ArgumentError: wrong number of arguments (given 1, expected 0)>
rint
最も近い整数
DFloat[2.4, 2.5, 2.51].rint.to_a # => [2.0, 2.0, 3.0]
trunc
小数部を捨てる
DFloat[-5.1, -5.9].trunc.to_a # => [-5.0, -5.0]
nearly_eq
小数の誤差を考慮した同値比較
a = DFloat[1.000000000000001]
b = DFloat[1.000000000000002]
a.to_a # => [1.000000000000001]
b.to_a # => [1.000000000000002]
値同士の比較では一致しない
a.to_a == b.to_a # => false
eq でも一致しない
a.eq(b).to_a # => [0]
nearly_eq では一致する
a.nearly_eq(b).to_a # => [1]
DFloat::Math
frexp を除いてすべて DFloat 型を返す
DFloat::Math.module_eval do
acos(0.5).to_a # => [1.0471975511965976]
acosh(1.5).to_a # => [0.9624236501192069]
asin(0.5).to_a # => [0.5235987755982988]
asinh(0.5).to_a # => [0.48121182505960347]
atan(0.5).to_a # => [0.46364760900080615]
atan2(2, 4).to_a # => [0.4636476090008061]
atanh(0.5).to_a # => [0.5493061443340549]
cbrt(0.5).to_a # => [0.7937005259840998]
cos(0.5).to_a # => [0.8775825618903728]
cosh(0.5).to_a # => [1.1276259652063807]
erf(0.5).to_a # => [0.5204998778130465]
erfc(0.5).to_a # => [0.4795001221869535]
exp(0.5).to_a # => [1.6487212707001282]
exp10(2).to_a # => [100.0]
exp2(8).to_a # => [256.0]
expm1(0.5).to_a # => [0.6487212707001282]
frexp(2.34).flat_map(&:to_a) # => [0.585, 2]
hypot(2, 3).to_a # => [3.605551275463989]
ldexp(1, 8).to_a # => [256.0]
log(3).to_a # => [1.0986122886681098]
log10(8).to_a # => [0.9030899869919435]
log1p(0.5).to_a # => [0.4054651081081644]
log2(256).to_a # => [8.0]
sin(0.5).to_a # => [0.479425538604203]
sinc(0.5).to_a # => [0.958851077208406]
sinh(0.5).to_a # => [0.5210953054937474]
sqrt(4).to_a # => [2.0]
tan(0.5).to_a # => [0.5463024898437905]
tanh(0.5).to_a # => [0.46211715726000974]
end
NMath は DFloat::Math に委譲する
NMath.log2(256) # => Numo::DFloat#shape=[]
DFloat::Math.log2(256) # => Numo::DFloat#shape=[]
統計
mean
平均
DFloat[1, 5, 7, 1000].mean # => 253.25
median
中央値
DFloat[1, 5, 7, 1000].median # => 6.0
square
2乗
a = DFloat[3, 4]
a.square.to_a # => [9.0, 16.0]
a.to_a # => [3.0, 4.0]
[3.0**2, 4.0**2] # => [9.0, 16.0]
元を破壊しない
var
不偏分散
DFloat[3, 6, 9].var # => 9.0
次と同じ
a = [3, 6, 9]
n = a.size
平均 = a.sum.fdiv(n)
a.sum { |e| (e - 平均)**2 } / (n - 1) # => 9.0
stddev
標準偏差
DFloat[3, 6, 9].stddev # => 3.0
Math.sqrt(DFloat[3, 6, 9].var) # => 3.0
不偏分散のルート
sum
総和
DFloat[2, 3, 4].sum # => 9.0
精度が低いけど速い
kahan_sum
カハンの加算アルゴリズムを使った総和
a = DFloat.ones(10000000) - 0.8
a.sum # => 1999999.9996779507
a.kahan_sum # => 1999999.9999999995
精度が高いけど遅い
x = Benchmark.ms { a.sum } # => 9.209000039845705
y = Benchmark.ms { a.kahan_sum } # => 140.67599992267787
y / x # => 15.275925650341822
trace
斜めの合計
a = Int16.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
a.trace # => 12
[0, 4, 8].sum # => 12
デバッグ用のメソッドかと思ったけど numpy にも同じのがあった
cumsum
累積和
Int8[2, 3, 4].cumsum.to_a # => [2, 5, 9]
[2, 3, 4].inject([]) { |a, e| [*a, (a.last || 0) + e] } # => [2, 5, 9]
prod
総積
DFloat[2, 3, 4].prod # => 24.0
[2, 3, 4].inject(&:*) # => 24
cumprod
累積積
Int8[2, 3, 4].cumprod.to_a # => [2, 6, 24]
[2, 3, 4].inject([]) { |a, e| [*a, (a.last || 1) * e] } # => [2, 6, 24]
mulsum
積
a = DFloat[2, 3]
b = DFloat[4, 5]
a.mulsum(b) # => 23.0
2 * 4 + 3 * 5 # => 23
rms
二乗平均平方根
DFloat[5, 6, 7].rms # => 6.0553007081949835
以下と同じ
v = [5, 6, 7] # => [5, 6, 7]
v = v.map { |e| e**2 } # => [25, 36, 49]
v = v.sum.fdiv(v.size) # => 36.666666666666664
v = Math.sqrt(v) # => 6.0553007081949835
reciprocal
逆数
DFloat[2, 3].reciprocal.to_a # => [0.5, 0.3333333333333333]
[1.0 / 2, 1.0 / 3] # => [0.5, 0.3333333333333333]
abs
絶対値
DFloat[-5, 6].abs.to_a # => [5.0, 6.0]
max, max_index
最大値とインデックス
Int8[5, 6, 7].max # => 7
Int8[5, 6, 7].max_index # => 2
min, min_index
最小値とインデックス
Int8[5, 6, 7].min # => 5
Int8[5, 6, 7].min_index # => 0
minmax
最小・最大
Int8[5, 6, 7].minmax # => [5, 7]
ptp
範囲の大きさを返す
a = DFloat[5, 6, 7]
a.ptp # => 2.0
a.max - a.min # => 2.0
sort
a = Int8[7, 6, 5]
a.sort.to_a # => [5, 6, 7]
a.to_a # => [7, 6, 5]
元を破壊しない
sort_index
並び換えることができるインデックス順を返す
a = Int8[8, 6, 9, 7]
a.to_a # => [8, 6, 9, 7]
a.sort_index.to_a # => [1, 3, 0, 2]
a[a.sort_index].to_a # => [6, 7, 8, 9]
a.sort_index.map { |i| a[i] }.to_a # => [6, 7, 8, 9]
format
文字列化して RObject を返す
DFloat[5, 6].format("%d %%") # => Numo::RObject#shape=[2]
DFloat[5, 6].format("%d %%").to_a # => ["5 %", "6 %"]
format_to_a
文字列化して Array を返す
DFloat[5, 6].format_to_a("%d %%") # => ["5 %", "6 %"]
なんとか積
dot
内積
Int8[2, 3].dot(4) # => 20
2 * 4 + 3 * 4 # => 20
Int8[2, 3].dot([4, 5]) # => 23
2 * 4 + 3 * 5 # => 23
Int8[2, 3].inner(Int8[4, 5]) # => 23
いろんな引数を解釈する。inner と似ているけど inner は NArray 型しか受け付けない。
inner
内積
Int8[2, 3].inner(Int8[4, 5]) # => 23
2 * 4 + 3 * 5 # => 23
相手は NArray 型でないとだめ
Int8[2, 3].inner([4, 5]) rescue $! # => #<TypeError: wrong argument type Array (expected Numo::NArray)>
outer
直積
Int64[2, 3].outer(Int64[4, 5]).to_a # => [[8, 10], [12, 15]]
[[2 * 4, 2 * 5], [3 * 4, 3 * 5]] # => [[8, 10], [12, 15]]
Int64[2, 3].kron(Int64[4, 5]).to_a # => [8, 10, 12, 15]
kron のフラットにしない版
kron
クロネッカー積
Int64[2, 3].kron(Int64[4, 5]).to_a # => [8, 10, 12, 15]
[2 * 4, 2 * 5, 3 * 4, 3 * 5] # => [8, 10, 12, 15]
角度
deg2rad
度数 → ラジアン
Int64[180].deg2rad.to_a # => [3.141592653589793]
rad2deg
ラジアン → 度数
NArray[Math::PI].rad2deg.to_a # => [180.0]
繰り返し
Int8[5, 6].each rescue $! # => #<LocalJumpError: no block given>
Int8[5, 6].map rescue $! # => #<LocalJumpError: no block given>
Int8[5, 6].each_with_index(1) rescue $! # => #<ArgumentError: wrong number of arguments (given 1, expected 0)>
Int8[5, 6].map_with_index(1) rescue $! # => #<ArgumentError: wrong number of arguments (given 1, expected 0)>
each
a = []
Int8.new(2, 2).seq.each { |*e| a << e }
a # => [[0], [1], [2], [3]]
each_with_index
a = []
Int8.new(2, 2).seq.each_with_index { |e, y, x| a << [e, y, x] }
a # => [[0, 0, 0], [1, 0, 1], [2, 1, 0], [3, 1, 1]]
map
DFloat[5, 6].map(&:itself).to_a # => [5.0, 6.0]
DFloat[5, 6].map(&:to_s) rescue $! # => #<TypeError: no implicit conversion to float from string>
map_with_index
DFloat[5, 6].map_with_index { |e, i| e * i }.to_a # => [0.0, 6.0]
each_over_axis
行毎または列毎に each する
a = Int8.new(3, 3).seq
行毎
v = []
a.each_over_axis(0) { |e| v << e }
v[0].inspect # => "Numo::Int8(view)#shape=[3]\n[0, 1, 2]"
v[1].inspect # => "Numo::Int8(view)#shape=[3]\n[3, 4, 5]"
v[2].inspect # => "Numo::Int8(view)#shape=[3]\n[6, 7, 8]"
列毎
v = []
a.each_over_axis(1) { |e| v << e }
v[0].inspect # => "Numo::Int8(view)#shape=[3]\n[0, 3, 6]"
v[1].inspect # => "Numo::Int8(view)#shape=[3]\n[1, 4, 7]"
v[2].inspect # => "Numo::Int8(view)#shape=[3]\n[2, 5, 8]"
反転
reverse
反転したビューを返す
a = Int8.new(3, 3).seq
a.to_a # => [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
上下左右
a.reverse.to_a # => [[8, 7, 6], [5, 4, 3], [2, 1, 0]]
上下
a.reverse(0).to_a # => [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
左右
a.reverse(1).to_a # => [[2, 1, 0], [5, 4, 3], [8, 7, 6]]
flipud
上下反転
a = Int8.new(3, 3).seq
a.flipud.to_a # => [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
a.reverse(0).to_a # => [[6, 7, 8], [3, 4, 5], [0, 1, 2]]
reverse(0)
と同じ
fliplr
左右反転
a = Int8.new(3, 3).seq
a.fliplr.to_a # => [[2, 1, 0], [5, 4, 3], [8, 7, 6]]
a.reverse(1).to_a # => [[2, 1, 0], [5, 4, 3], [8, 7, 6]]
reverse(1)
と同じ
三角系
.tril_indices
斜めに切ったときの左下△のインデックスを返す
a = Int8.new(3, 3).seq.to_a
a[0] # => [0, 1, 2]
a[1] # => [3, 4, 5]
a[2] # => [6, 7, 8]
NArray.tril_indices(3, 3, -2).to_a # => [6]
NArray.tril_indices(3, 3, -1).to_a # => [3, 6, 7]
NArray.tril_indices(3, 3, 0).to_a # => [0, 3, 4, 6, 7, 8]
NArray.tril_indices(3, 3, 1).to_a # => [0, 1, 3, 4, 5, 6, 7, 8]
NArray.tril_indices(3, 3, 2).to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
.triu_indices
斜めに切ったときの右上△のインデックスを返す
a = Int8.new(3, 3).seq.to_a
a[0] # => [0, 1, 2]
a[1] # => [3, 4, 5]
a[2] # => [6, 7, 8]
NArray.triu_indices(3, 3, -2).to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
NArray.triu_indices(3, 3, -1).to_a # => [0, 1, 2, 3, 4, 5, 7, 8]
NArray.triu_indices(3, 3, 0).to_a # => [0, 1, 2, 4, 5, 8]
NArray.triu_indices(3, 3, 1).to_a # => [1, 2, 5]
NArray.triu_indices(3, 3, 2).to_a # => [2]
tril
左下三角形を除いて 0 にしたのを返す
a = Int8.new(3, 3).seq(1)
a.tril.to_a[0] # => [1, 0, 0]
a.tril.to_a[1] # => [4, 5, 0]
a.tril.to_a[2] # => [7, 8, 9]
tril!
trilの破壊版
a = Int8.new(3, 3).seq(1)
a.tril!
a.to_a[0] # => [1, 0, 0]
a.to_a[1] # => [4, 5, 0]
a.to_a[2] # => [7, 8, 9]
tril_indices
左下三角形の領域のインデックスたちを返す
a = Int8.new(3, 3)
a.tril_indices.to_a # => [0, 3, 4, 6, 7, 8]
triu
右上三角形を除いて 0 にしたのを返す
a = Int8.new(3, 3).seq(1)
a.triu.to_a[0] # => [1, 2, 3]
a.triu.to_a[1] # => [0, 5, 6]
a.triu.to_a[2] # => [0, 0, 9]
triu!
triuの破壊版
a = Int8.new(3, 3).seq(1)
a.triu!
a.to_a[0] # => [1, 2, 3]
a.to_a[1] # => [0, 5, 6]
a.to_a[2] # => [0, 0, 9]
triu_indices
右上三角形の領域のインデックスたちを返す
a = Int8.new(3, 3)
a.triu_indices.to_a # => [0, 1, 2, 4, 5, 8]
入れ替え
transpose
横と縦を入れ替える
a = Int8.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
a = a.transpose # => Numo::Int8(view)#shape=[3,3]
a.to_a[0] # => [0, 3, 6]
a.to_a[1] # => [1, 4, 7]
a.to_a[2] # => [2, 5, 8]
rot90 とは異なる。元は破壊しない。
swapaxes
並びを入れ替える
a = Int8.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
b = a.swapaxes(0, 1)
b.to_a[0] # => [0, 3, 6]
b.to_a[1] # => [1, 4, 7]
b.to_a[2] # => [2, 5, 8]
c = a.transpose
c.to_a[0] # => [0, 3, 6]
c.to_a[1] # => [1, 4, 7]
c.to_a[2] # => [2, 5, 8]
swapaxes(0, 1) だと transpose と同じ結果になる
rot90
90度左回転する
a = Int8.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
b = a.rot90 # => Numo::Int8(view)#shape=[3,3]
b.to_a[0] # => [2, 5, 8]
b.to_a[1] # => [1, 4, 7]
b.to_a[2] # => [0, 3, 6]
180度回転する場合は rot90(2)
とする
transpose とは走査の順が異なる
c = a.transpose # => Numo::Int8(view)#shape=[3,3]
c.to_a[0] # => [0, 3, 6]
c.to_a[1] # => [1, 4, 7]
c.to_a[2] # => [2, 5, 8]
結合
.concatenate
合体したのを返す
a = Int8.new(2, 2).seq(0)
b = Int8.new(2, 2).seq(4)
Int8.concatenate([a, b]).to_a # => [[0, 1], [2, 3], [4, 5], [6, 7]]
.hstack, .vstack, .dstack
結合
a = Int8[1, 2]
b = Int8[3, 4]
c = Int8[5, 6]
Int8.hstack([a, b, c]).to_a # => [1, 2, 3, 4, 5, 6]
Int8.vstack([a, b, c]).to_a # => [[1, 2], [3, 4], [5, 6]]
Int8.dstack([a, b, c]).to_a # => [[[1, 3, 5], [2, 4, 6]]]
内部で .concatenate を呼んでいる
concatenate
合体する
a = Int8.new(2, 2).seq(0)
b = Int8.new(2, 2).seq(4)
a.concatenate(b) # => Numo::Int8#shape=[4,2]
a.concatenate(b).to_a # => [[0, 1], [2, 3], [4, 5], [6, 7]]
a.to_a # => [[0, 1], [2, 3]]
元を破壊しない
(a + b).to_a # => [[4, 6], [8, 10]]
クラスメソッドにも似たのがある
Int8.concatenate([a, b]).to_a # => [[0, 1], [2, 3], [4, 5], [6, 7]]
append
合体する
a = Int8.new(2, 2).seq(0)
b = Int8.new(2, 2).seq(4)
a.append(b) # => Numo::Int8#shape=[8]
a.append(b).to_a # => [0, 1, 2, 3, 4, 5, 6, 7]
a.to_a # => [[0, 1], [2, 3]]
元を破壊しない。フラットになる点が concatenate と違う
バイトオーダー
名前 | 何 endian ? | 備考 |
---|---|---|
vacs | little | 固定 |
network | big | 固定 |
host | little | ビルド方法によって変わる |
swap_byte | すると big | ビルド方法によって変わる |
byte_swapped?
big endian か?
Int16[1].byte_swapped? # => false
Int16[1].network_order? # => false
host_order?
little endian か?
Int16[1].host_order? # => true
Int16[1].little_endian? # => true
Int16[1].vacs_order? # => true
swap_byte, hton
big endian 化する
Int16[1].to_a # => [1]
Int16[1].swap_byte.to_a # => [256]
Int16[1].hton.to_a # => [256]
to_vacs
必ず little endian 化する
Int16[1].to_vacs.to_a # => [1]
もともと little endian だから変化していない
to_network
必ず big endian 化する
Int16[1].to_network.to_a # => [256]
to_swapped
big endian 化する
Int16[1].to_swapped.to_a # => [256]
to_host
little endian 化する
Int16[1].to_host.to_a # => [1]
シリアライズ
to_binary, to_string
バイナリ表現を返す
a = Int8.new(2, 3).seq
a.to_binary # => "\x00\x01\x02\x03\x04\x05"
a.to_string # => "\x00\x01\x02\x03\x04\x05"
store_binary
to_binary から復元する
bin = Int8.new(2, 3).seq.to_binary # => "\x00\x01\x02\x03\x04\x05"
a = Int8.new(3, 2)
a.store_binary(bin) # => 6
a.to_a # => [[0, 1], [2, 3], [4, 5]]
from_binary と読み替えると挙動をイメージしやすい。shape は違っていてもいいけど size が足りないとエラーになる。元を破壊する。
.from_binary
バイナリから1次元な NArray を返す
bin = Int8.new(2, 3).seq.to_binary # => "\x00\x01\x02\x03\x04\x05"
Int8.from_binary(bin).to_a # => [0, 1, 2, 3, 4, 5]
shape を作ってから取り込む場合は store_binary の方を使う
marshal_dump
Marshal.dump 用
a = Int8[5, 6]
a.marshal_dump # => [1, [2], 0, "\x05\x06"]
marshal_load
Marshal.load 用
d = Int8[5, 6].marshal_dump # => [1, [2], 0, "\x05\x06"]
Int8.new.marshal_load(d).to_a # => [5, 6]
シリアライズと復元の例
a = Int8[5, 6]
bin = Marshal.dump(a) # => "\x04\bU:\x0FNumo::Int8[\ti\x06[\x06i\ai\x00I\"\a\x05\x06\x06:\x06EF"
Marshal.load(bin).inspect # => "Numo::Int8#shape=[2]\n[5, 6]"
メタ情報
shape
次元の形を返す
Int8.new(2, 3, 4).shape # => [2, 3, 4]
new で生成したときの引数に相当する
ndim, rank
次元数
Int8.new(2, 3, 4).ndim # => 3
Int8.new(2, 3, 4).rank # => 3
new で生成したときの引数の数に相当する
size, length, total
要素数を返す
Int8.new(2, 3, 4).size # => 24
Int8.new(2, 3, 4).length # => 24
Int8.new(2, 3, 4).total # => 24
new で生成したときの引数の積に相当する
byte_size
総バイト数を返す
a = Int16.new(3)
a.byte_size # => 6
a.class::ELEMENT_BYTE_SIZE # => 2
a.size # => 3
a.class::ELEMENT_BYTE_SIZE * a.size # => 6
内部データの並び
[[0, 1], [2, 3]] のとき
内部 | 名称 |
---|---|
[0, 1, 2, 3] | row_major |
[0, 2, 1, 3] | column_major |
row_major?
内部データは行毎か? (フラグで判定)
Int8.new.row_major? # => true
column_major?
内部データは列毎か? (フラグで判定)
Int8.new.column_major? # => false
contiguous?
内部データは行毎か? (動的判定)
Int8.new.contiguous? # => true
fortran_contiguous?
内部データは列毎か? (動的判定)
Int8.new.fortran_contiguous? # => false
NArrayのその他のクラスメソッド
それぞれの型に継承している
.column_stack
transpose のクラスメソッド版
a = Int8[1, 2]
b = Int8[3, 4]
Int8.column_stack([a, b]).to_a # => [[1, 3], [2, 4]]
Int8[a, b].transpose.to_a # => [[1, 3], [2, 4]]
.array_type
要素に合った型のクラスを返す
NArray.array_type(0.0) # => Numo::DFloat
NArray.array_type(0) # => Numo::Int32
NArray.array_type(10000000000) # => Numo::Int64
RObject 型にはならなかった
NArray.array_type("a") rescue $! # => #<TypeError: invalid type for NArray: String>
.byte_size
要素のバイト数を返す
Int8.byte_size # => 1
Int8::ELEMENT_BYTE_SIZE # => 1
Int16.byte_size # => 2
Int16::ELEMENT_BYTE_SIZE # => 2
ELEMENT_BYTE_SIZE 定数と同じ値になっている
.diag_indices
対角インデックスを返す
NArray.diag_indices(3, 3).to_a # => [0, 4, 8]
実体がなくても shape からインデックスは取れる。diagonal で使われていると思われる。
.upcast
両方が収まる型を返す
Int8.upcast(Int16) # => Numo::Int16
Int16.upcast(Int8) # => Numo::Int16
NArray から継承するその他のインスタンスメソッド
to_i, to_f, to_c
想定通りの値を返す
DFloat[5.6].to_i # => 5
Int8[5].to_f # => 5.0
Int8[5].to_c # => (5+0i)
Int8[5, 6].to_i rescue $! # => #<TypeError: can't convert Numo::Int8 into Complex>
[]
参照
a = Int8.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
2次元の場合は (行, 列) つまり (y, x) の順になる
a[1, 2] # => 5
1次元としてもアクセスできる
a[6] # => 6
a[9] rescue $! # => #<IndexError: index=9 out of shape[0]=9>
Range
a[1..2].to_a # => [1, 2]
Array
a[[1, 2]].to_a # => [1, 2]
フラットになる
a[0..-1].to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
a[true].to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
列でアクセスする。true は 0..-1 と同じ。
a[true, 0].to_a # => [0, 3, 6]
a[true, 1].to_a # => [1, 4, 7]
a[true, 2].to_a # => [2, 5, 8]
3次元目を取り除く場合
a[0..1, 0].to_a # => [0, 3]
a[0..1, 1].to_a # => [1, 4]
a[0..1, 2].to_a # => [2, 5]
at
指定位置のビューを取得する
Int8[5, 6, 7, 8].at([1, 2]) # => Numo::Int8(view)#shape=[2]
Int8[5, 6, 7, 8].at(1..2) # => Numo::Int8(view)#shape=[2]
指定できるのは配列と Range だけだった
Int8[5, 6, 7, 8].at(1) rescue $! # => #<IndexError: not allowed type>
Int8[5, 6, 7, 8].at(1, 2) rescue $! # => #<ArgumentError: the number of argument must be same as dimension>
[]=
ビューに対して更新する
a = Int8[5, 6, 7, 8]
a[1..2] # => Numo::Int8(view)#shape=[2]
a[1..2] = [0, 1]
a.to_a # => [5, 0, 1, 8]
ビューを更新すると元を更新する
slice
次元数が変わらない以外は [] と同じ
a = Int8.new(3, 3).seq
a.to_a # => [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
a.slice(0..1, 0).to_a # => [[0], [3]]
[] で書いたときは次元が減っている
a[0..1, 0].to_a # => [0, 3]
==
比較する
DFloat[5.0, 6.0] == Int64[5, 6] # => true
eq とは違う
DFloat[5.0, 6.0].eq Int64[5, 6] # => Numo::Bit#shape=[2]
cov
共分散
DFloat[[5, 6, 7], [5, 6, 7]].cov.to_a # => [[1.0, 1.0], [1.0, 1.0]]
delete
インデックスで値や列や行を削除する
a = Int64[5, 6, 7]
a.delete(1).to_a # => [5, 7]
a.to_a # => [5, 6, 7]
列や行を削除する場合
a = Int64.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
0行目の削除
a.delete(0, 0).to_a # => [[3, 4, 5], [6, 7, 8]]
0列目の削除
a.delete(0, 1).to_a # => [[1, 2], [4, 5], [7, 8]]
diag
?
a = Int8.new(3, 3).seq
a.to_a[0] # => [0, 1, 2]
a.to_a[1] # => [3, 4, 5]
a.to_a[2] # => [6, 7, 8]
a = a.diag.to_a
a[0] # => [[0, 0, 0], [0, 1, 0], [0, 0, 2]]
a[1] # => [[3, 0, 0], [0, 4, 0], [0, 0, 5]]
a[2] # => [[6, 0, 0], [0, 7, 0], [0, 0, 8]]
列毎に分解されてでっかくなった。よくわかってない。
diag_indices
斜めのインデックスを返す
a = Int8.new(3, 3).seq(10)
a.to_a[0] # => [10, 11, 12]
a.to_a[1] # => [13, 14, 15]
a.to_a[2] # => [16, 17, 18]
a.diag_indices(-2).to_a # => [6]
a.diag_indices(-1).to_a # => [3, 7]
a.diag_indices(0).to_a # => [0, 4, 8]
a.diag_indices(1).to_a # => [1, 5]
a.diag_indices(2).to_a # => [2]
diagonal
斜めのビューを返す
a = Int8.new(3, 3).seq(10)
a.to_a[0] # => [10, 11, 12]
a.to_a[1] # => [13, 14, 15]
a.to_a[2] # => [16, 17, 18]
a.diagonal(-2).to_a # => [16]
a.diagonal(-1).to_a # => [13, 17]
a.diagonal(0).to_a # => [10, 14, 18]
a.diagonal(1).to_a # => [11, 15]
a.diagonal(2).to_a # => [12]
diff
隣りとの差を返す
a = Int8[10, 7, 9]
a.diff.to_a # => [-3, 2]
a.to_a.each_cons(2).map { |a, b| b - a } # => [-3, 2]
empty?
空か?
Int8[].empty? # => true
値の有無は見てない
Int8.new(3).empty? # => false
expand_dims
次元を増やす
a = Int8.new(5)
a.shape # => [5]
a.expand_dims(0).shape # => [1, 5]
a.expand_dims(1).shape # => [5, 1]
a.shape # => [5]
元を破壊しない
flatten
平らにする
Int8.new(3, 3).seq.flatten.to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
代替は [true]
でいいはず
Int8.new(3, 3).seq[true].to_a # => [0, 1, 2, 3, 4, 5, 6, 7, 8]
free
空の状態にする
a = Int8[1] # => Numo::Int8#shape=[1]
a.free # => Numo::Int8#shape=[1](empty)
a # => Numo::Int8#shape=[1](empty)
破壊的。new したときの状態になる。
insert
指定のインデックスに入れる
a = Int64[5, 6]
a.insert(1, 10).to_a # => [5, 10, 6]
a.to_a # => [5, 6]
repeat
指定回数繰り返したのを生成する
a = Int8.new(2, 2).seq
a.to_a # => [[0, 1], [2, 3]]
a.repeat(2).to_a # => [0, 0, 1, 1, 2, 2, 3, 3]
a.repeat(2, axis: 0).to_a # => [[0, 1], [0, 1], [2, 3], [2, 3]]
a.repeat(2, axis: 1).to_a # => [[0, 0, 1, 1], [2, 2, 3, 3]]
tile
タイルを敷き詰めるように広げる
a = Int8.new(2, 2).seq
a.to_a[0] # => [0, 1]
a.to_a[1] # => [2, 3]
縦横2倍する
v = a.tile(2, 2).to_a
v[0] # => [0, 1, 0, 1]
v[1] # => [2, 3, 2, 3]
v[2] # => [0, 1, 0, 1]
v[3] # => [2, 3, 2, 3]
元は破壊していない
a.size # => 4
reshape
shape を変形したコピーを返す
a = Int8.new(2, 3).seq
a.to_a # => [[0, 1, 2], [3, 4, 5]]
a.reshape(3, 2).to_a # => [[0, 1], [2, 3], [4, 5]]
size が同じのときだけ使える
reshape!
reshape の破壊版
a = Int8.new(2, 3).seq
a.to_a # => [[0, 1, 2], [3, 4, 5]]
a.reshape!(3, 2)
a.to_a # => [[0, 1], [2, 3], [4, 5]]
split, vsplit, hsplit, dsplit
分割する
a = Int8.new(7).seq
インデックスで分割する
a.split([2])[0].to_a # => [0, 1]
a.split([2])[1].to_a # => [2, 3, 4, 5, 6]
N分割する (半分にできない場合、前の方が多くなる)
a.split(2)[0].to_a # => [0, 1, 2, 3]
a.split(2)[1].to_a # => [4, 5, 6]
axis 0 から 2 を初期値にした別メソッドがある
Int8.new(4, 4, 4).seq.vsplit(2) # => [Numo::Int8(view)#shape=[2,4,4]
Int8.new(4, 4, 4).seq.hsplit(2) # => [Numo::Int8(view)#shape=[4,2,4]
Int8.new(4, 4, 4).seq.dsplit(2) # => [Numo::Int8(view)#shape=[4,4,2]
coerce
両者を適切な型にして [other, self]
を返す
v = Int8[5].coerce([6])
v[0] # => Numo::Int8#shape=[1]
v[1] # => Numo::Int8#shape=[1]
v = Int16[5].coerce(Int8[6])
v[0] # => Numo::Int16#shape=[1]
v[1] # => Numo::Int16#shape=[1]
view
単にビューを返す
Int8.new.view # => Numo::Int8(view)#shape=[](empty)
サブクラスのその他のインスタンスメソッド
NArray を継承している
allocate
?
DFloat.new.allocate # => Numo::DFloat#shape=[]
DFloat.new.allocate.to_a # => [0.0]
0 が入ってた。
argmin, argmax
最小値・最大値のインデックスを返す
a = DFloat.new(3, 3).seq(0)
a.to_a[0] # => [0.0, 1.0, 2.0]
a.to_a[1] # => [3.0, 4.0, 5.0]
a.to_a[2] # => [6.0, 7.0, 8.0]
a.argmin # => 0
a.argmax # => 8
引数がないときは min_index, max_index と変わらない
a.min_index # => 0
a.max_index # => 8
axis があると結果が変わる
a.argmin(axis: 0).to_a # => [0, 0, 0]
a.min_index(axis: 0).to_a # => [0, 1, 2]
a.argmax(axis: 0).to_a # => [2, 2, 2]
a.max_index(axis: 0).to_a # => [6, 7, 8]
clip
clip というより clamp
a = DFloat.new(5).seq
a.clip(1, 4).to_a # => [1.0, 1.0, 2.0, 3.0, 4.0]
a.to_a # => [0.0, 1.0, 2.0, 3.0, 4.0]
coerce_cast
?
DFloat[5].coerce_cast(Int64) # => nil
ただ nil を返すだけ
copysign
dup して引数の符号を適用する
a = DFloat[-5, 6]
a.copysign([1, -2]).to_a # => [5.0, -6.0]
a.to_a # => [-5.0, 6.0]
元を破壊しない
divmod
割って商と剰余を返す
q, r = DFloat[5, 6].divmod(2)
q.to_a # => [2.5, 3.0]
r.to_a # => [1.0, 0.0]
extract
0次元のときだけ抽出する (?)
Int8[].ndim # => 1
Int8.new(0).ndim # => 1
Int8.allocate.ndim # => 0
# Int8.allocate.extract # => [BUG] Segmentation fault at 0x0000000000000000
Int8[5].inspect # => "Numo::Int8#shape=[1]\n[5]"
Int8[5].extract.inspect # => "Numo::Int8#shape=[1]\n[5]"
modf
小数と整数に分離する
a, b = DFloat[5.1, 6.2].modf
a.to_a # => [0.09999999999999964, 0.20000000000000018]
b.to_a # => [5.0, 6.0]
poly
多項式の係数を求める
# DFloat[2].poly(3) # =>
sign
符号だけにする
DFloat[5, -6, 7].sign.to_a # => [1.0, -1.0, 1.0]
signbit
マイナスを true とした Bit 型にする
DFloat[5, -6, 7].signbit # => Numo::Bit#shape=[3]
DFloat[5, -6, 7].signbit.to_a # => [0, 1, 0]
to_a
Array 化
DFloat[5, 6, 7].to_a # => [5.0, 6.0, 7.0]
isnan, isinf, isfinite
DFloat[0.0 / 0].isnan.to_a # => [1]
DFloat[5.0 / 0].isinf.to_a # => [1]
DFloat[-5.0 / 0].isneginf.to_a # => [1]
DFloat[+5.0 / 0].isposinf.to_a # => [1]
DFloat[5].isfinite.to_a # => [1]
nan? infinite? finite? に相当する
eq, ne, ge, gt, le, lt
DFloat[5, 6].eq DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6].ne DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6] >= DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6] > DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6] <= DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6] < DFloat[5, 7] # => Numo::Bit#shape=[2]
DFloat[5, 6].ge(DFloat[5, 7]) # => Numo::Bit#shape=[2]
DFloat[5, 6].gt(DFloat[5, 7]) # => Numo::Bit#shape=[2]
DFloat[5, 6].le(DFloat[5, 7]) # => Numo::Bit#shape=[2]
DFloat[5, 6].lt(DFloat[5, 7]) # => Numo::Bit#shape=[2]
eq
ne
と ==
!=
は異なる
DFloat[5, 6] == DFloat[5, 7] # => false
DFloat[5, 6] != DFloat[5, 7] # => true
Bit 型
演算すると勝手にできる
a = Int8.new(5).seq(5)
a.to_a # => [5, 6, 7, 8, 9]
(a >= 8) # => Numo::Bit#shape=[5]
(a >= 8).to_a # => [0, 0, 0, 1, 1]
a[a >= 8].to_a # => [8, 9]
&
や |
でマージできる
c = (a >= 8) | (a.eq 5) # => Numo::Bit#shape=[5]
c # => Numo::Bit#shape=[5]
c.to_a # => [1, 0, 0, 1, 1]
a[c].to_a # => [5, 8, 9]
true false は 1 0 で書いても同じ内部表現になるっぽい
Bit[true, false].to_a # => [1, 0]
Bit[1, 0].to_a # => [1, 0]
all? any? none?
Bit[true, false, true].all? # => false
Bit[true, false, true].any? # => true
Bit[true, false, true].none? # => false
copy
おそらく deep copy と思われる
a = Bit.new(3, 3).fill(true)
b = a.copy
別のオブジェクトになっている
a.object_id # => 500
b.object_id # => 520
コピー元を更新する
a[1, 1] = 0
a.to_a[0] # => [1, 1, 1]
a.to_a[1] # => [1, 0, 1]
a.to_a[2] # => [1, 1, 1]
コピー先は変化しない
b.to_a[0] # => [1, 1, 1]
b.to_a[1] # => [1, 1, 1]
b.to_a[2] # => [1, 1, 1]
copy を dup に変更しても結果は変わらなかった
count_true, count_1
true の個数を返す
Bit[true, false, true].count_true # => 2
Bit[true, false, true].count_1 # => 2
count_false, count_0
false の個数を返す
Bit[true, false, true].count_false # => 1
Bit[true, false, true].count_0 # => 1
| &
論理和と論理積
a = Bit[1, 0, 1, 0]
b = Bit[1, 1, 0, 0]
(a & b).to_a # => [1, 0, 0, 0]
(a | b).to_a # => [1, 1, 1, 0]
mask
相手の該当要素を抽出する
a = Bit[1, 0, 1, 0]
a.mask([5, 6, 7, 8]).to_a # => [5, 7]
これと同じ
NArray[5, 6, 7, 8][a].to_a # => [5, 7]
where
真になる位置のインデックスを返す
a = Int8[5, 6, 7, 8]
a.to_a # => [5, 6, 7, 8]
(a > 6).where.to_a # => [2, 3]
where が返すのは該当した値ではない。該当した値がある位置のインデックスになっている。where をかまさないときは有効な位置が true になる行列がとれる。
(a > 6).to_a # => [0, 0, 1, 1]
対象の値たちがほしい場合、再度 a を参照しないといけない
a[a > 6].to_a # => [7, 8]
次のように書いても結果は同じなので、おそらく a[x] は x.where を呼んでいると思われる
a[(a > 6).where].to_a # => [7, 8]
where2
真偽両方のインデックスを返す
a = Int8[5, 6, 7, 8]
a.to_a # => [5, 6, 7, 8]
前側は条件にマッチした方のインデックスでこれがほしいだけなら where でいい
(a > 6).where2[0].to_a # => [2, 3]
後側は条件にマッチしなかった方のインデックスになっている
(a > 6).where2[1].to_a # => [0, 1]
整数専用
<<, >>
(Int8[1, 2, 3] << 1).to_a # => [2, 4, 6]
(Int8[2, 4, 6] >> 1).to_a # => [1, 2, 3]
DFloat[1] << 1 rescue $! # => #<NoMethodError:"undefined method `<<' for Numo::DFloat#shape=[1]\n[1]:Numo::DFloat">
定数
NArray::VERSION # => "0.9.2.1"
Bit
Bit::UPCAST # => {Array=>Numo::Bit, Integer=>Numo::Bit, Float=>Numo::DFloat, Complex=>Numo::DComplex, false=>false, Numo::DComplex=>Numo::DComplex, Numo::SComplex=>Numo::SComplex, Numo::DFloat=>Numo::DFloat, Numo::SFloat=>Numo::SFloat, Numo::Int64=>Numo::Int64, Numo::Int32=>Numo::Int32, Numo::Int16=>Numo::Int16, Numo::Int8=>Numo::Int8, Numo::UInt64=>Numo::UInt64, Numo::UInt32=>Numo::UInt32, Numo::UInt16=>Numo::UInt16, Numo::UInt8=>Numo::UInt8}
Bit::ELEMENT_BIT_SIZE # => 1
Bit::ELEMENT_BYTE_SIZE # => 0.125
Bit::CONTIGUOUS_STRIDE # => 1
Int8
Int8::UPCAST # => {Array=>Numo::Int8, Integer=>Numo::Int8, Float=>Numo::DFloat, Complex=>Numo::DComplex, false=>Numo::Int16, Numo::DComplex=>Numo::DComplex, Numo::SComplex=>Numo::SComplex, Numo::DFloat=>Numo::DFloat, Numo::SFloat=>Numo::SFloat, Numo::Int64=>Numo::Int64, Numo::Int32=>Numo::Int32, Numo::Int16=>Numo::Int16, Numo::Int8=>Numo::Int8, Numo::UInt64=>Numo::Int64, Numo::UInt32=>Numo::Int64, Numo::UInt16=>Numo::Int32}
Int8::ELEMENT_BIT_SIZE # => 8
Int8::ELEMENT_BYTE_SIZE # => 1
Int8::CONTIGUOUS_STRIDE # => 1
Int8::MAX # => 127
Int8::MIN # => -128
DFloat
DFloat::UPCAST # => {Array=>Numo::DFloat, Integer=>Numo::DFloat, Float=>Numo::DFloat, Complex=>Numo::DComplex, false=>Numo::DFloat, Numo::DComplex=>Numo::DComplex, Numo::DFloat=>Numo::DFloat}
DFloat::ELEMENT_BIT_SIZE # => 64
DFloat::ELEMENT_BYTE_SIZE # => 8
DFloat::CONTIGUOUS_STRIDE # => 8
DFloat::EPSILON # => 2.220446049250313e-16
DFloat::MAX # => 1.7976931348623157e+308
DFloat::MIN # => 2.2250738585072014e-308
RObject 型
.[]
どんな型でも入る
a = RObject["a", 1, {}] # => Numo::RObject#shape=[3]
a.to_a # => ["a", 1, {}]
a = a.map(&:size).map(&:to_s) # => Numo::RObject#shape=[3]
a.to_a # => ["1", "8", "0"]
a[a.ne("0")].to_a # => ["1", "8"]
空配列を入れると空配列が消えてしまう
RObject[[]].to_a # => []
どこから nil が来た?
RObject[[], 1].to_a # => [nil]
Struct 型
Struct # => Struct
Numo::Struct # => Numo::Struct
定義
color = Numo::Struct.new do
uint8 "foo"
end
color # => #<Class:0x0000000105907120>
color.new rescue $! # => #<TypeError: allocator undefined for #<Class:0x0000000105907120>>
color[] rescue $! # => #<TypeError: allocator undefined for #<Class:0x0000000105907120>>
つまづいた点
継承したクラスから .[] で生成すると親クラスで生成される
class Vec2 < Int64
def x; self[0]; end
def y; self[1]; end
end
Vec2[1, 2].x rescue $! # => #<NoMethodError:"undefined method `x' for Numo::Int64#shape=[2]\n[1, 2]:Numo::Int64">
Vec2[].class # => Numo::Int64
Discussion