ベクトル計算

レイトレースベンチの移植の続きをしていたのだけど、
ベクトルの和にすらパターンマッチで[X, Y, Z]=LISTという感じで展開してから
個々に計算するという状況に強いストレスを感じたので一旦作業を中断して他の方法を調べた。
lists:zipとリスト内包表記の組み合わせを使うのがよさげか。

% 和
34> V=[1, 2, 3].
[1,2,3]
35> Q=[2, 3, 4].
[2,3,4]
37> [X+Y || {X, Y}<-lists:zip(V, Q)].
[3,5,7]

% 定数倍
38> [X*3 || X<-V].
[3,6,9]

% 内積
39> [X*Y || {X, Y}<-lists:zip(V, Q)].
[2,6,12]

% 合計するのを忘れていたw
4> lists:sum([X*Y || {X, Y}<-lists:zip(V, Q)]).
20

もっと短く書ける方法は無いのかしら。
むしろvec_add, vec_dot_productとかいう感じで関数を整備するべきなのか。
うぅむ。

続き

ひとまずレイトレースベンチを書きながらベクトル用の関数を別モジュールに分離した。
球にグラデーションがつくところまでできた。
残りは、複数の球を配置する部分とシャドウレイのところ。

-module(vec).
-compile(export_all).

% 和
add(LV, RV)->
  [L+R || {L, R}<-lists:zip(LV, RV)].

% 差
sub(LV, RV)->
  [L-R || {L, R}<-lists:zip(LV, RV)].

% 定数倍
times(N, V)->
  [N*Val || Val<-V].

% 内積
dot(LV, RV)->
  lists:sum([L*R || {L, R}<-lists:zip(LV, RV)]).

% ベクトルの正規化
normalize(Vec)->
  [N/norm(Vec) || N<-Vec].

% ベクトルの大きさ
norm(Vec)->
  math:sqrt(sqnorm(Vec)).

% 大きさの二乗
sqnorm(Vec)->
  lists:sum([N*N || N<-Vec]).

% 反転
negative(V)->
  [-Val || Val<-V].

反転追加。