MFGドキュメント
Home
Getting Started
Reference
  • ja-JP
  • en-US
Home
Getting Started
Reference
  • ja-JP
  • en-US
  • MEP 4: タプルのvectorization

MEP 4: タプルのvectorization

  • Created: 2022-09-12 10:41:25

r, g, bには同じ処理をする事が多いので、vectorizationが欲しい。 以下みたいなの。

let [r3, b3, g3] = [r2, b2, g2]/a2

パーサーの段階で展開されるシンタックスシュガーにしたい。 現状はテンソルのタプルの扱いなどはletの所で展開しているけれど、expressionの所で展開したい。 そうすれば同じ処理でvectorizationも扱えるはず。

vectorizationしたいもの

  • 割り算
  • 掛け算
  • cast_f32等

最後を考えるに、関数一般をvectorizationしてしまっても良いかも?


既存のスクリプトをvectorizationしてみる。

モザイク

@bounds( (input.extent(0)-1)/MOSAIC_WIDTH+1, (input.extent(1)-1)/MOSAIC_WIDTH+1)
def avg |x, y|{
    rsum(0:MOSAIC_WIDTH, 0:MOSAIC_WIDTH) |rx, ry|{
        let [a, r, g, b] = clamped( MOSAIC_WIDTH*x+rx, MOSAIC_WIDTH*y+ry )
        let [r2, g2, b2] = [r, g, b]*a
        [a, r2, g2, b2]
    }
}

def result |x2, y2| {
    let [a2, r2, g2, b2] = avg( x2/MOSAIC_WIDTH, y2/MOSAIC_WIDTH )
    let [r3, g3, b3] = [r2, g2, b2]/a2
    ifel(a2==0,
        0,
        argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH),
            r3, 
            g3,
            b3 ) )
}

悪くないが、インラインでそのまま書けないものかなぁ。 以下のように書きたいが、spreadしてくれないといけない。

うーん。関数呼び出しも同じ感じで書きたいよなぁ。

argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH),
  [r2, g2, b2]/a2)

やりたいのは、タプルに対して演算した結果を個々の要素に展開したい。


JavaScriptのspread演算子は同じ事をする。

[a, ...[r, g, b]*a]

argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH), ...[r2, g2, b2]/a2)

kotlin, python, rubyはアスタリスク(Rubyではsplatオペレーターと言うらしい)

[a, *[r, g, b]*a]

argb( a2/(MOSAIC_WIDTH*MOSAIC_WIDTH), *[r2, g2, b2]/a2)

swiftやrustには無さそう。

個人的にはJSの方が好きだが、業界的にはsplatで統一されつつあるのかなぁ。


vectorizationと合わせる事を考えると...の方がいい気がするな。 とりあえず...とvectorizationを合わせる方針で行ってみよう。

  • ...は関数の引数とタプルの生成時のみサポート
  • vectorizationは/, *と任意の関数(タプルを引数に取る関数が必要になったらそれは特別扱い)
  • どちらもパースの段階で処理するシンタックスシュガー

最後が本当に実現出来るかは以下で簡単に考えておこう。

追記: やはり関数の最後のplace holderの ... との区別が面倒だったので、 *にする。


vectorizationは、IRとしては展開したものを持つ。 つまり

は、

と展開する。 つまりタプルの正体が分からないようなケースではうまく処理出来ない。 関数の引数がタプル、みたいなものの時。 ただ、テンソルの場合、

は、以下のような感じに展開されて、

[ts(x,y)[0], ts(x,y)[1], ts(x,y)[2]]/a2

以後は通常の展開になる予定。すべてのタプルはこのように、展開を記述出来るとする(現状はこうなっていないが)。そもそもtensorのタプルのケースでのindexは現状使った事無いのでサポートしていない気がする(いつもdestructuring代入で十分なので)。 これは関数の引数などでもサポートする時には考える必要がありそう(ただ、スクリプトとしてはいつもdestructuring代入のみでも十分な気もしないでもない)

castなどの関数やsinなどは、全てかってに展開される。 つまり、以下は、

展開されてIR上では以下のようになる。

[cast_u64(r), cast_u64(g), cast_u64(b)]

spreadの仕様

  • タプルの初期化と関数呼び出しのarg listのみで使える
  • *をexprの前に置く事でそれを展開したものが引数として解釈される
最終更新: 2025/11/20 15:14
Contributors: Kazuma Arino