[IDL8] は IDL 8.0 で導入された機能、[IDL84] は IDL 8.4 で導入された機能であることを示す。
A[1]
と 丸括弧による A(1)
の2通りの書き方があるが、角括弧を用いたほうが無難。A[1,5,4]
)。多次元配列のメモリ内での順番は列主導、つまりFortranと同じ。通常は0以上の数字で指定する。64bit整数型の範囲まで利用可能。小数を指定した場合、小数点以下は切り捨てられる。
負の添え字は配列の末尾からの位置を示す。n
を正整数とするとき、a[-n]
は a[n_elements(a)-n]
と等価。負の添字をサポートした結果、コードによっては以前のバージョンのIDLで実行したときと異なる結果になる場合がある。以前ならエラーで止まってしまうケースが、エラーとならず想定外の計算結果を返してしまう。具体例はwhere
の項目を参照。
IDLで配列の添え字を指定するには、角括弧による A[1]
と 丸括弧による A(1)
の2通りの書き方がある。配列で丸括弧を利用すると関数呼び出しと一見区別がつかない。特に、同名の関数と配列が存在するとき、関数が既にコンパイル済みであるかどうかでプログラムの動作が変わってしまう。このため、角括弧を用いるほうがよい。compile_opt strictarr
(compile_opt idl2
にも含まれる)で丸括弧による添え字の指定を禁止できる。
配列の一部分だけを引用することができる (部分配列)。部分配列を指定するには、添え字として添え字三つ組やベクトル添え字を用いる。
A[l:m:n]
A[l] から A[m] まで添え字が n 間隔の要素から構成される部分配列。mに*を指定すると配列の添え字の上限を指定したことになる。nは1以上の整数。A[l:m]
のようにnを省略した時のデフォルトのnの値は1。m-l が n の倍数でないとき、部分配列にA[m]は含まれない。
A[l1:m1:n1,l2:m2:n2]
多次元配列に対しても同様。
A[l1:m1:n1,*]
ある次元については要素を全て選択するときには*を用いる。
1次元配列を添え字として使用することで、一つの配列の複数の要素を引用することができる(ベクトル添え字)。
A[[1,2,3,5]]
A[1], A[2], A[3], A[5] から構成される部分配列。A[[1,3,1,5]]
のように同じ要素を複数回指定してもよい。
ただし、ベクトル添え字を利用する場合、配列の範囲外を指し示す添え字が存在する場合でも、デフォルトでは範囲外を指さないようにクリップされてエラーにならない。
A = [3, 5, 1, 2, 9]
B = [1, 4, 100]
PRINT, A[B] ; 結果は 5 9 9
COMPILE_OPT STRICTARRSUBS
A = [3, 5, 1, 2, 9]
B = [1, 4, 100]
PRINT, A[B] ; エラー
部分配列は左辺値としても使用できる。代入の項を参照。
make_array
intarr(n)
make_array(n,/integer)
と等価。初期化が不要な時は /nozero
オプションを利用する。巨大な配列を作成する際に初期化の時間を節約できる。dblarr(n,m,n)
または dblarr([n,m,n])
make_array(n,m,n,/double)
またはmake_array([n,m,n],/double)
と等価。型ごとに次のような個別の関数が用意されている。bytarr (byte型), intarr (integer型), lonarr (long型), lon64arr (64bit integer型), uintarr (符号無しinteger型), ulonarr (符号無しlong型), ulon64arr (符号無し64bit integer型), fltarr (float型), dblarr (double型), complexarr (complex型), dcomplexarr (倍精度complex型), strarr (string型)
A = indgen(n)
make_array(n,/integer,/index)
と等価。A = indgen(n,start=s)
[IDL 8.2]A = indgen(n,increment=i)
[IDL 8.3]A = [s:f]
または A = [s:f:i]
[IDL8.3]indgen((f-s)/i+1, start=n, increment=i)
と同じ結果になるが、新しい方法のほうがわかりやすい。s,f,iには小数も使えるが、浮動小数点の計算誤差のため要素数が期待されるよりも少なくなることがある。例: [0:1:0.001]
の要素数は本来1001になることが期待されるが、実際には1000になる。A = indgen(n,m)
または A = indgen(n,m)
型ごとに次のような個別の関数も用意されている。bindgen (byte型), indgen (integer型 または任意の型), lindgen (long型), l64indgen (64bit integer型), uindgen (符号無しinteger型), ulindgen (符号無しlong型), ul64indgen (符号無し64bit integer型), findgen (float型), dindgen (double型), cindgen (complex型), dcindgen (倍精度complex型), sindgen (string型)
添え字を指定するための角括弧との混同に注意。
A = [43, 8, 75, 57, 19, 83]
A = [41, 5.3d-1, 7, 313L, 4.3]
A = ['Jan', 'Feb', 'Mar']
A = [1, '2.2d0', 3.3]
A = [[0,4,1],[2,1,3]]
B=[0,4,1] & C=[2,1,3] & A=[B,C]
とすると、B
とC
が単純に連結され、要素数6の1次元配列となることに注意。同じ結果を得るには、最後にA=[[B],[C]]
とする必要がある。array=replicate(r, 次元1, 次元2, ...)
make_array(次元1, 次元2, ... , value=r)
と等価。
array=[]
または array=!NULL
[]
は !NULL
と等価である。[]
や !NULL
を代入すると、変数が使用していたメモリが解放される。!NULLの項目も参照。IDLでは最高で8次元までの多次元配列が利用可能。添え字はカンマで区切る(A[1,5,4]
)。
多次元配列のメモリ内での順番は列主導(Column Major)。一番左の添え字がもっとも急速に変化する。つまりFortran、MATLABなどと同じ。例えば2次元配列の場合は、a[0, 0], a[1, 0], a[2, 0], ... , a[0, 1], a[1, 1], a[2, 1], ... の順になる。行主導(Row Major)の配列を採用している他の言語(Cなど)とデータをやりとりするときには、場合によってはtranspose関数を用いて次元の順序を入れ替える必要がある。
多次元配列の各要素は、その配列を「1次元配列とみなして」アクセスすることができる。つまり、A = intarr(3,2)のとき、a[i,j] は 2 * j + i 番目の要素であるから、a[2 * j + 1]としても参照できる。このことは、多次元配列の各要素に対して配列中での位置に依存しない処理を行うとき、ループのネストが必要ないことを意味する。
逆に、WHERE、MAX、MIN関数など、1次元配列とみなしたときの添字を返すような関数の結果を、実際の多次元配列での添字に変換するには、ARRAY_INDICES 関数を使う。(割り算して自分で求めることもできるが、こちらのほうが楽)
配列の要素数を変えず、メモリー内に格納されている順序も変更しないで、次元のみを変えるときは reform 関数を用いる。/overwrite キーワードをつけると、データのコピーは行わず、次元の変更のみが行われる。reform関数は、次元を指定しない場合には、サイズが1の次元のみを除去する。
a=b
a[*]=1
a=1
a=temporary(b)
a=a+2
a=temporary(a)+2
a+=2
部分配列は左辺値としても使用できる。
A[[1,7,2]] = [10,9,8]
A[1:*:2] = A[0:*:2]
A[2:4] = [4,5,6]
A[2] = [4,5,6]
配列の全部または一部にスカラーを代入するには、REPLICATE_INPLACEプロシージャも使える。うまく使えば高速化に有効。
b=[a,1,2,3]
c=[a,b]
c=[[a],[b]]
c=[[[a]],[[b]]]
[ ] のネスト数の最大は、IDL 8.8.x までは3個、IDL 8.9以降は8個。
配列aの要素数を調べる。変数が未定義の場合は0を返す。変数がスカラーの場合1を返すため、この方法では「要素数1の配列」とスカラーの区別はできない。
PRINT, N_ELEMENTS(a)
PRINT, SIZE(a ,/N_ELEMENTS)
PRINT, a.length ; [IDL84]
size(変数,/n_dimensions)
は配列の次元を返す。これが0ならスカラー(または未定義)、1以上なら配列。ただし、構造体・ハッシュ・リストは、たとえ要素が1個であったとしても、常に配列であるとみなされる。変数.ndim ; [IDL84]
も次元を返す。size(変数,/dimensions)
変数.dim ; [IDL84]
size(変数,/type)
で type code (0-15の整数)、size(変数,/tname)
で型の名前を文字列で返す。変数.typecode
で type code (0-15の整数)、変数.typename
で型の名前を文字列で返す。where関数を使う。例えば、a
が数値の配列のとき、where(a lt 0)
で 0 よりも小さな要素の位置を配列で返す。条件を満たす要素が存在しないときには -1 を返す。
IDL 8以降では配列の負の添字がサポートされたため、a[where(a lt 0)] = 0
などとすると、a
に負の値が含まれていないとき、where(a lt 0)
の結果は -1
となり、a
の最後の要素が0になってしまう。これを回避するには、a[where(a lt 0, /null)] = 0
とする。
最小値や最大値でクリップするには >や< 演算子も使える。例えば、a >= 0
と a[where(a lt 0, /null)] = 0
はどちらも0より小さい値を0に置き換える。
[IDL84] IDL_Variable::Filter を用いると、自作の関数やlambda関数をフィルタとして用いて、これらの関数が真を返す要素のみを抽出することができる。
部分配列をサブルーチンの引数として渡すときは、値渡しとなることに注意。
reform
rebin, expand, congrid
transpose, rot, rotate
shift, shift_diff
reverse, sort, uniq
array_equal, IDL_Variable::Compare, IDL_Variable::Diff, IDL_Variable::Equals
total
多数の要素を加算するときや、要素の値の大小差が非常に大きいときには誤差に注意。IDLのtotal関数は配列の要素を最初から順に足しあわせるだけである。並列化の有無(デフォルトでは並列化を行うが、/TPOOL_NO
をつけると並列化を行わない)でも計算順序が変わるため結果が変わる。例えば、a = FINDGEN(100000) & PRINT, TOTAL(a, /TPOOL_NO) - TOTAL(REVERSE(a), /TPOOL_NO)
の結果は -96768.0 となる。入力をDOUBLE型にするか、totalに /DOUBLE
キーワードをつけて倍精度で計算するようにする。
状況によってはカハンの加算アルゴリズムの使用を検討する。
function kahansum, input
sum = 0d
c = 0d
for i = 0, n_elements(input) -1 do begin
y = input[i] - c
t = sum + y
c = (t - sum) - y
sum = t
endfor
return, sum
end
total(replicate(0.1d, 1000000),/TPOOL_NO)
の結果は 100000.00000133288 になるが、kahansum(replicate(0.1d, 1000000))
の結果は 100000.00000000000 になる。
product
/INTEGER
キーワードをつけると、64-bit 整数型で計算を行う。
min, max関数
mean, stddev, variance, skewness, kurtosis
identity
#, ##, matrix_multiply, matrix_power
invert, la_invert
西田圭佑 (NISHIDA Keisuke)