Inner Product

is a dyadic operator that produces a dyadic function when applied with two dyadic functions. It's a generalisation of the matrix product, allowing not just addition-multiplication, but any dyadic functions given as operands.

Examples
The shapes of the arguments must be compatible with each other: The last axis of the left argument must have the same length as the first axis of the right argument, or formally, for  it must be that. Although this rule differs from conformability, the arguments may also be subject to scalar or singleton extension. The shape of the result is.

For example, when applying inner product on two matrices, the number of columns in the left array must match with number of rows in the right array, otherwise we will get an error.

History
Inner product appeared in early Iverson Notation as $$^f_g$$ and applied even to non-scalar functions, like Compress, Iverson bringing:

\begin{align} \text{For example, if}\\ \boldsymbol{A}&=\begin{pmatrix} 1&3&2&0\\ 2&1&0&1\\ 4&0&0&2\\ \end{pmatrix} \qquad\text{and}\qquad \boldsymbol{B}=\begin{pmatrix} 4&1\\ 0&3\\ 0&2\\ 2&0\\ \end{pmatrix}\\ \text{then}\qquad\boldsymbol{A}\;^+_\times\,\boldsymbol{B}&=\begin{pmatrix} 4&14\\ 10&5\\ 20&4\\ \end{pmatrix}, \quad\boldsymbol{A}\;^\land_=\,\boldsymbol{B}=\begin{pmatrix} 0&1\\ 0&0\\ 1&0\\ \end{pmatrix}\text{,}\\ \boldsymbol{A}\;^\lor_\neq\;\boldsymbol{B}&=\begin{pmatrix} 1&0\\ 1&1\\ 0&1\\ \end{pmatrix}, \qquad\text{and}\qquad(\boldsymbol{A}\neq0)\;^+_{\,/}\,\boldsymbol{B}=\begin{pmatrix} 4&6\\ 6&4\\ 6&1\\ \end{pmatrix}\text{.} \end{align} $$ When the inner product notation was linearised (made to fit on a single line of code) the glyph  was chosed to denote what was previously indicated by positioning the two operands vertically aligned. Thus, the above correspond to the following modern APL: Note that some dialects implement Compress as a monadic operator rather than as a function, which means it cannot be an operand in the inner product. Instead, a cover function is necessary:

Differences between dialects
Implementations differ on the exact behaviour of inner product when the right operand is not a scalar function. It follows from page 121 of the ISO/IEC 13751:2001(E) standard specifies that  is equivalent to. This is indeed what APL2, APLX, APL+Win, and ngn/apl follow, while Dyalog APL, NARS2000 and GNU APL differ as described by Roger Hui: The following dop models inner product in Dyalog APL, with caveats. If you find a case where  differs from , not covered by the caveats, I'd be interested. (Explanation: What's with the  in  ?  It's because   has an implicit each, applying   to each item of its result.  But the   in   also has an implicit each.  So the   gets rid of one of those encloses.)

Caveats:


 * You can not use the hybrid  directly as an operand as it runs afoul of the parser in weird and wonderful ways.  Instead, you have to use  .  The same goes for   and   I guess.


 * It differs from ISO/IEC 13751:2001(E) in using  instead of just   in the central key expression (i.e.   instead of  ).  So does the primitive.


 * It differs from ISO/IEC 13751:2001(E) in doing full-blown single extension instead of just scalar and 1-element vector extension (as in APL2). So does the primitive  .  e.g.
 * It differs from NARS2000 or APL\360 in not permitting unit axis extension. So does the primitive .  e.g.

Documentation

 * Dyalog
 * APLX
 * J Dictionary, NuVoc

Discussion of differences between dialects

 * Dyalog / APL2000 discrepancy (Google Groups)
 * multiple inner product (GNU APL mailing list)
 * an other inner product ,., bug (GNU APL mailing list)