ドキュメントによると、* 演算子は外積を実行し、;* はドット積を実行するようです。 次のように、外積を使用して、既知のベクトルのペアに垂直なベクトルを決定したいと考えています。
p1 = [1, 2, 4];
p2 = [2, 1, 4];
p3 = [2, 2, 4];
v1 = p3 - p1;
v2 = p2 - p1;
xProd = v1*v2;
3 つの点が平面を定義し、それらの点から取得された 2 つのベクトルも同じことを行い、外積によりその平面の法線ベクトルが得られます。 問題は、乗算される 2 つの行列 (v1 と v2) の次元が一致しないことのようです。nRows(v1) は nCols(v2) と等しい必要があります。 ベクトルの外積の簡略化された式を使用してこれを手動で実装できますが、行列の乗算を処理するためにこれを別の形式でフォーマットする方法を知っている人はいますか?
パフォーマンスが劣っていても不思議ではありません...符号調整を入れてくれてありがとう。 うっかり「サインチェッカーボード」を省略してしまいました。
私の意見では、これは「できるからといって、そうすべきであるとは限りません」が当てはまる例の 1 つです... {かっこいい、楽しい、短い}は、{理解できる、保守しやすい、速い}を上回ることはありません。
@brady_bradyいいね! 使用する場合は微調整が必要です。
i = 1;
j = -1;
J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) );
</CODE><A href="https://mathinsight.org/cross_product_formula" target="_blank" rel="nofollow noopener noreferrer">https://mathinsight.org/cross_product_formula</A>中央の要素がどのように負である必要があるかを示しています。上記では、j の符号が交互に (1、-1、1)、i が増加します (1、2、3)。 J(...) 関数には、各要素の 3 番目の引数を評価する暗黙的なループがあります。</P>
<P> </P>
<P>からの直接的に修正された式<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/11962" target="_blank">@klk</A>約 3 倍速く、約 N 倍理解しやすくなります。</P>
<P> </P>
<P>テストコード。</P>
<DIV class="lia-spoiler-container"><A class="lia-spoiler-link" href="#" rel="nofollow noopener noreferrer" target="_blank">もっと見る...</A><NOSCRIPT><DIV class="lia-spoiler-content"><BR /><PRE><CODE class=" language-jsl">v1 = [0, 0, 1];
v2 = [0, 1, 0];
start = HP Time();
For( t = 1, t < 1e6, t += 1,
i = 1;
j = -1;
J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) );
);
stop = HP Time();
Show( (stop - start) / 1e6 );//9.3s
start = HP Time();
For( t = 1, t < 1e6, t += 1,
Matrix( {v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]} )
);
stop = HP Time();
Show( (stop - start) / 1e6 );//3.2s
For( q = 1, q < 10000, q += 1,
v1 = J( 3, 1, Random Uniform( -1, 1 ) );
v2 = J( 3, 1, Random Uniform( -1, 1 ) );
If(
All(
Round( Matrix( {v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]} ), 10 ) //
== //
(i = 1; j = -1 ; Round( J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) ), 10 ) ; ) //
) == 0//
, //
Throw( Char( q ) )
);
);不思議なことに、11 位に四捨五入すると結果が一致しないことがあります。 おそらくほぼ同一線上のベクトルです。
さて、復活したゾンビが私を捕まえました。 これは行列式を介してそれを行う方法です。 @Craige_Hales言及された。 短いですが、わかりません...それほど単純ではありません。
crossP = Function( {x, y, i = 1},
Return( J( 3, 1, Det( (x || y)[Remove( [1, 2, 3], i++ ), 0] ) ) )
);
つまり、最初に提供されたデータを使用します。

このゾンビ スレッドを復活させて申し訳ありませんが、ここの 2 番目の要素に符号エラーがあります。そうあるべきだと信じています
Matrix(
{v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]}<BR />)簡単にコピー&ペーストできる他の人のために、これをここに残しておきたいと思います。
cwillden に感謝します。これは基本的に私が実装したものです。 私は 3D ベクトルのみに関心があるので、これは機能しますが、これが組み込み関数ではないことに驚きました。 他にそのような方法を知っている人がいるかどうかを確認するために、しばらくこれを開いたままにしておきます。
誰かがこれを行う賢い方法を考え出すことを願っています。 det() 関数は密接に関連していますが、スカラー値以上のものを返すために det(3x3 行列) を使用する方法がわかりません。 det(2x2 sub-matrix) を 3 回使用できると思いますが、単純明快な方法だと思います。キシジーアプローチはより簡単で、同じくらい高速です。
3D シーンのサーフェス法線に使用します。いくつかの JSL があります。 https://community.jmp.com/t5/Uncharted/Custom-Visualization/ba-p/191559 。
3x1 (または 1x3) ベクトルのみを扱う場合、計算効率や優雅さはそれほど重要ではないと思います。これで十分でしょうか?
cross_prod = function({v1, v2},
matrix({v1[2]*v2[3] - v1[3]*v2[2], v1[1]*v2[3] - v1[3]*v2[1], v1[1]*v2[2] - v1[2]*v2[1]});
);
cross_prod(v1, v2);