Declarations of functions associated with the outer product within group_D.
Version of Friday 13 September 2024.
The two outer product functions are:
/* D3 */ permzbi operator* (permzbi const & b) const; /* D3 */ permzbi & operator*= (permzbi const & b);
and are related to these functions:
// direct sum /* D2 */ permzbi operator<< (permzbi const & b) const; /* D2 */ permzbi & operator<<= (permzbi const & b); // skew sum /* D2 */ permzbi operator>> (permzbi const & b) const; /* D2 */ permzbi & operator>>= (permzbi const & b);
In each case, the assignment version of the operator assigns the result to the left-hand operand, as customary in C++.
It is unwieldy to write the general formula for the outer product. However, the following example will give the idea.
Start with permzbis P = {p0, p1, p2}, and Q = {q0, q1, q2, q3}. Meanwhile, let pc be the number of components in P, in this example 3; and qc be the number of components in Q, in this example 4.
Then P * Q will have pc * qc components, in this example 12. Here is the outer product:
P * Q = | { | q0 + p0*qc, q1 + p0*qc, q2 + p0*qc, q3 + p0*qc, |
q0 + p1*qc, q1 + p1*qc, q2 + p1*qc, q3 + p1*qc, | ||
q0 + p2*qc, q1 + p2*qc, q2 + p2*qc, q3 + p2*qc } |
This example can be made more concrete. Let permzbis P = {2, 0, 1}, and Q = {3, 1, 0, 2}. Then pc = 3 and qc = 4; and (P * Q)c = 3 * 4 = 12. Substituting:
P * Q = | { | 3 + 2*4, 1 + 2*4, 0 + 2*4, 2 + 2*4, |
3 + 0*4, 1 + 0*4, 0 + 0*4, 2 + 0*4, | ||
3 + 1*4, 1 + 1*4, 0 + 1*4, 2 + 1*4 } | ||
P * Q = | { | 3 + 8, 1 + 8, 0 + 8, 2 + 8, |
3 + 0, 1 + 0, 0 + 0, 2 + 0, | ||
3 + 4, 1 + 4, 0 + 4, 2 + 4 } | ||
P * Q = | { | 11,  9,  8, 10, |
 3,  1,  0,  2, | ||
 7,  5,  4,  6 } |
Remark 1. The present author has not seen this outer product defined in any other literature, although this operation is so natural that someone somewhere would presumably have found and documented it before now.
Remark 2. The name "outer product" comes from a resemblance to the outer product of vectors.
The outer product is associative. In other words, for all permzbis P, Q, R, which need not be of the same size, (P * Q) * R == P * (Q * R).
The outer product is not commutative: in general, P * Q does not equal Q * P.
Further, (P * Q).inverse() == P.inverse() * Q.inverse(). Because the outer product is non-commutative, one might expect that the order of the factors be reversed on one side or the other (as with matrices), but that is not the case here.
Here is a detailed example of the relationship of the outer product to the direct and skew sums. If permzbi A is { 2, 3, 0, 1}, and B is any permzbi, then A * B equals (B << B) >> (B << B), as highlighted in red in the table below: row 3, column 3.
The outer product cannot be used to represent an expression like (B << C) >> (D << E) — all the operands have to be the same.
Also, if A is {1, 3, 0, 2} or {2, 0, 3, 1}, there is no expression of direct and skew sums of any parenthesization of four instances of B that will yield A * B (for all B, of course). This is because {1, 3, 0, 2} and {2, 0, 3, 1} are not separable, as can be tested directly with the following permzbi function:
/* G2 */ bool is_separable () const;
For the case where A is a four-component permzbi, the table below the eight possible sequences of sign (by row) and the five possible parenthesizations (by column). Observe that no A value is repeated from one row to another. The subscript on each A represents its position in lexicographical order
column 1 (B op (B op B)) op B | column 2 ((B op B) op B) op B | column 3 (B op B) op (B op B) | column 4 B op (B op (B op B)) | column 5 B op ((B op B) op B) | |
---|---|---|---|---|---|
row 1 << << << |
A0 = { 0, 1, 2, 3 } | ||||
(B << (B << B)) << B | ((B << B) << B) << B | (B << B) << (B << B) | B << (B << (B << B)) | B << ((B << B) << B) | |
row 2 << << >> |
A9 = { 1, 2, 3, 0} | A1 = { 0, 1, 3, 2} | A3 = { 0, 2, 3, 1} | ||
(B << (B << B)) >> B | ((B << B) << B) >> B | (B << B) << (B >> B) | B << (B << (B >> B)) | B << ((B << B) >> B) | |
row 3 << >> << |
A2 = { 0, 2, 1, 3 } (same as col 5) |
A8 = { 1, 2, 0, 3 } | A16 = { 2, 3, 0, 1 } | A4 = { 0, 3, 1, 2 } | A2 = { 0, 2, 1, 3 } (same as col 1) |
(B << (B >> B)) << B | ((B << B) >> B) << B | (B << B) >> (B << B) | B << (B >> (B << B)) | B << ((B >> B) << B) | |
row 4 << >> >> |
A11 = { 1, 3, 2, 0 } | A17 = { 2, 3, 1, 0 } | A5 = { 0, 3, 2, 1 } | ||
(B << (B >> B)) >> B | ((B << B) >> B) >> B | (B << B) >> (B >> B) | B << (B >> (B >> B)) | B << ((B >> B) >> B) | |
row 5 >> << << |
A12 = { 2, 0, 1, 3 } | A6 = { 1, 0, 2, 3 } | A18 = { 3, 0, 1, 2 } | ||
(B >> (B << B)) << B | ((B >> B) << B) << B | (B >> B) << (B << B) | B >> (B << (B << B)) | B >> ((B << B) << B) | |
row 6 >> << >> |
A21 = { 3, 1, 2, 0 } (same as col 5) |
A15 = { 2, 1, 3, 0 } | A7 = { 1, 0, 3, 2 } | A19 = { 3, 0, 2, 1 } | A21 = { 3, 1, 2, 0 } (same as col 1) |
(B >> (B << B)) >> B | ((B >> B) << B) >> B | (B >> B) << (B >> B) | B >> (B << (B >> B)) | B >> ((B << B) >> B) | |
row 7 >> >> << |
A14 = { 2, 1, 0, 3 } | A22 = { 3, 2, 0, 1 } | A20 = { 3, 1, 0, 2 } | ||
(B >> (B >> B)) << B | ((B >> B) >> B) << B | (B >> B) >> (B << B) | B >> (B >> (B << B)) | B >> ((B >> B) << B) | |
row 8 >> >> >> |
A23 = { 3, 2, 1, 0 } | ||||
(B >> (B >> B)) >> B | ((B >> B) >> B) >> B | (B >> B) >> (B >> B) | B >> (B >> (B >> B)) | B >> ((B >> B) >> B) | |
A10 = {1, 3, 0, 2} and A13 = {2, 0, 3, 1} are omitted by necessity |