IDLメモ 演算子

IDLでは大半の演算子(operator)はオペランド(operand; 被演算子)が配列であっても使用できる。たとえば、[1,2,3] * [4,5,6]の結果は[4,10,18]となり、[1,2,3] + 2の結果は[3,4,5]となる。

優先順位と結合性

https://www.nv5geospatialsoftware.com/docs/operator_precedence.html を参照。

優先順位が同じ演算子同士の場合、左から右に評価される(左結合)。

算術演算子

+ - * / (二項演算子)
加減乗除 (+ は文字列の連結にも用いられる。 - は負の符号を示す単項演算子としても用いられる)
^ (二項演算子)
冪乗 例: 3^2.5
MOD (二項演算子)
剰余 例: 7 mod 2
++ -- (単項演算子)
インクリメント・デクリメントを行う単項演算子。++でオペランドの値を1増やし、--でオペランドの値を1減らす。式の評価値を用いるときは、前置のほうが後置よりも高速でメモリ消費量も少ない(後置の場合、データのコピーが行われて、元のデータの値を変更してから、コピーしたデータが評価値として用いられる)。副作用と評価順序にも注意(例えば A = B++ + Bなどとしてはいけない)。

最大・最小演算子

> (二項演算子)
最大演算子。大きい方の値を返す 例: a が配列の時、b = a > 0 とするとaの要素のうち正のものはそのまま、負のものは0になってbに格納される。
< (二項演算子)
最小演算子。小さい方の値を返す

右オペランドの表記に負の符号が含まれる場合には括弧で囲む必要がある 例: 5 < (-6)。最大・最小演算子と-は優先順位が同じであるため。

複素数の場合は絶対値で比較される。2つのオペランドの絶対値が等しいときは、最初のオペランドが返される。

オペランドがNaNである場合の結果は未定義(最大演算子のときは右オペランドの値、最小演算子の時は左オペランドの値を返す?)。この場合は、( FINITE(A) && FINITE(B) ) ? ( A > B ) : !VALUES.F_NAN などとする。

IDL では、比較演算子としては LT, GT などを用いる。もし、IF a > b THEN ... としても文法的には正しいが、おそらくそれは意図した結果ではない (aとbのうち大きい方の値が真偽値として評価される)。

行列演算子

# (二項演算子)
A # B は行列の積 BA を計算する。1つめの配列の列と2つめの配列の行との間でそれぞれ内積が計算される。1つめの配列の行数と2つめの配列の列数は等しくなければならない。ただし、2つめの配列が1次元配列で、転置することでつじつまが合う場合は、かけあわせる前に転置してくれる。結果の配列のサイズは、列数は1つめの配列と、行数は2つめの配列と等しくなる。A # Bmatrix_multiply(A,B)と等価。
## (二項演算子)
A ## B は行列の積 AB を計算する。1つめの配列の行と2つめの配列の列との間でそれぞれ内積が計算される。1つめの配列の列数と2つめの配列の行数は等しくなければならない。ただし、1つめの配列が1次元配列で、転置することでつじつまが合う場合は、かけあわせる前に転置してくれる。結果の配列のサイズは、行数は1つめの配列と、列数は2つめの配列と等しくなる。A ## BB # Aと等価。

論理演算子

IDL 6.0で導入された。論理演算子はオペランドとして配列をとることはできない。配列のときはLOGICAL_OR, LOGICAL_AND関数を用いるか、引数が0, 1 のみをとる場合はビット演算子で代用する(これらの場合、両方の引数が評価されることに注意する)。&&|| の優先順位は等しいことにも注意。論理演算子とビット演算子の表現がPerlとは逆であることに注意。

&& (二項演算子)
論理積。左オペランドが偽のとき右オペランドは評価されない。
|| (二項演算子)
論理和。左オペランドが真の時右オペランドは評価されない。
~ (単項演算子)
否定

ビット演算子

論理演算子とビット演算子の表現がPerlとは逆であることに注意。AND, OR, XOR の優先順位は等しいことにも注意。ビットシフトにはISHFT関数を用いる。

AND (二項演算子)
ビット単位AND
NOT (単項演算子)
ビット単位NOT
OR (二項演算子)
ビット単位OR
XOR (二項演算子)
ビット単位XOR

関係演算子

オペランドがNaNとなっている可能性があるときは、あらかじめFINITE関数でNaNでないことを確認しておく。

EQ NE GE GT LE LT (二項演算子)
それぞれ、EQual to, Not Equal to, Greater than or Equal to, Greater Than, Less than or Equal to, Less Than。文字列の比較もできる。文字列同士の比較の場合は辞書順で評価される。文字列と数値を比較した場合は、文字列は数値に変換されてから評価される。つまり、'2' gt '10' は真となるが 2 gt '10' は偽となる。

条件演算子

? : (三項演算子)
条件演算子。expr1 ? expr2 : expr3 としたとき、expr1 が真なら expr2が評価され、偽なら expr3が評価される。左辺値としても使える。(expr1 ? var1 : var2) = expr2

括弧

( )
1. 関数呼び出しで引数を囲む 例: sin(0.5)
2. 演算子の評価順序を変更する 例: (a+3)*5
3. 配列の添え字を囲む 例: a(1)
[ ]
1. 配列を生成する 例: a=[1.3,1.5,1.9,2.7]
2. 配列の添え字を囲む 例: a[1]

配列の添え字を指定するには、角括弧による a[1] と 丸括弧による a(1) の2通りの書き方がある。丸括弧を利用すると関数呼び出しや演算子の評価順序変更と紛らわしいので、角括弧を用いるほうがよい。compile_opt strictarr で丸括弧による添え字の指定を禁止できる。

代入演算子

=
代入演算子。代入式の値が必要な場合は括弧で囲む必要がある。例: a = (b = 1)とするとa, b ともに1が代入される。括弧なしで a = b = 1 とすると左から結合され、(a = b) = 1 だと解釈され Syntax error となる。
+= -= *= /= ^= MOD= <= >= #= ##= AND= OR= XOR= EQ= GE= GT= LE= LT= NE=
複合代入演算子。a += ba = a + (b) と同様の結果になる。aの型が演算の前後で変わらないときは、データのコピーは行われないため、正確にはa = temporary(a) + (b)と等価であり、メモリ消費と計算時間を節約できる。

ポインター

*
ポインターのデリファレンス(ポインタが示す先の値を取り出す)。配列のブラケットや構造体のフィールド参照のドットよりも優先順位が低いことに注意。

構造体・オブジェクト

.
1. 構造体のフィールドを参照する
2. オブジェクトのメソッドを参照する (IDL 8.0 以降)
->
オブジェクトのメソッドを参照する (.と等価)
西田圭佑 (NISHIDA Keisuke)
nishida at kwasan.kyoto-u.ac.jp