/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-22 Bradley M. Bell

CppAD is distributed under the terms of the
             Eclipse Public License Version 2.0.

This Source Code may also be made available under the following
Secondary License when the conditions for such availability set forth
in the Eclipse Public License, Version 2.0 are satisfied:
      GNU General Public License, Version 2.0 or later.
---------------------------------------------------------------------------- */
$begin atomic_four_mat_mul$$
$spell
    Taylor
    nr
    nc
    mul
$$

$section Atomic Matrix Multiply Class: Example Implementation$$

$head Syntax$$
$codei%atomic_mat_mul %mat_mul%(%name%)
%$$
$icode%call_id% = %mat_mul%.set(%n_left%, %n_middle%, %n_right%)
%$$
$icode%mat_mul%.get(%call_id%, %n_left%, %n_middle%, %n_right%)
%$$
$icode%mat_mul%(%call_id%, %x%, %y%)
%$$

$head Purpose$$
Construct an atomic operation that computes the matrix product
$icode%C% = %A% * %B%$$.

$head n_left$$
This is the row dimension of the matrices $icode A$$ and $icode C$$.
This is an argument (return value) for the $code set$$ ($code get$$) routine.

$head n_middle$$
This is the column dimension of the matrix $icode A$$
and row dimension of the matrix $icode B$$
This is an argument (return value) for the $code set$$ ($code get$$) routine.

$head n_right$$
This is the column dimension of the matrices $icode B$$ and $icode C$$.
This is an argument (return value) for the $code set$$ ($code get$$) routine.

$head call_id$$
This is a return value (argument) for the $code set$$ ($code get$$) routine.

$head x$$
We use $icode x$$ to denote the argument to the atomic function.
The size of this vector must be
$icode%
    n = n_left * n_middle + n_middle * n_right
%$$
The matrix $icode A$$ is stored in row major order at the beginning of
$icode x$$; i.e. its $icode (i,k)$$ element is
$icode%
    A(i,k) = x[ i * n_middle + k]
%$$
The matrix $icode B$$ is stored in row major order at the end of
$icode x$$; i.e. its $icode (k,j)$$ element is
$icode%
    B(k,j) = x[ n_left * n_middle + k * n_right + j ]
%$$

$head y$$
We use $icode y$$ to denote the result of the atomic function.
The size of this vector must be
$icode m = n_middle * n_right$$.
The matrix $icode C$$ is stored in row major order in $icode y$$;
i.e. its $icode (i,k)$$ element is
$icode%
    C(i,j) = y[ i * n_right + j]
%$$

$head Theory$$

$subhead Forward$$
For $latex k = 0 , \ldots $$, the $th k$$ order Taylor coefficient
$latex C^{(k)}$$ is given by
$latex \[
    C^{(k)} = \sum_{\ell = 0}^{k} A^{(\ell)} B^{(k-\ell)}
\] $$

$subhead Matrix Argument Scalar Valued Function$$
Suppose $latex \bar{F}$$ is the derivative of the
scalar value function $latex s(F)$$ with respect to the matrix $latex F$$; i.e.,
$latex \[
    \bar{F}_{i,j} = \frac{ \partial s } { \partial F_{i,j} }
\] $$
Also suppose that $latex t$$ is a scalar valued argument and
$latex \[
    F(t) = D(t) E(t)
\] $$
It follows that
$latex \[
    F'(t) = D'(t) E(t) +  D(t) E'(t)
\] $$

$latex \[
    (s \circ F)'(t)
    =
    \R{tr} [ \bar{F}^\R{T} F'(t) ]
\] $$
$latex \[
    =
    \R{tr} [ \bar{F}^\R{T} D'(t) E(t) ] +
    \R{tr} [ \bar{F}^\R{T} D(t) E'(t) ]
\] $$
$latex \[
    =
    \R{tr} [ E(t) \bar{F}^\R{T} D'(t) ] +
    \R{tr} [ \bar{F}^\R{T} D(t) E'(t) ]
\] $$
Letting $latex E(t) = 0$$ and $latex D(t) = \Delta^{i,j} (t)$$
(where $latex \Delta^{i,j} (t)$$ is the matrix that is zero,
except for $latex i = j$$ where it is $latex t$$) we have
$latex \[
    \bar{D}_{i,j}
    = \frac{ \partial s } { \partial D_{i,j} }
    = (s \circ F)'(t)
    = \R{tr} [ E(t) \bar{F}^\R{T} \Delta^{i,j}(1) ]
\] $$
$latex \[
    \bar{D}_{i,j}
    = \sum_k D_{j,k} \bar{F}^\R{T}_{k,i}
    = \sum_k \bar{F}_{i,k} E^\R{T}_{k,j}
\] $$
$latex \[
    \bar{D} = \bar{F} E^\R{T}
\] $$
Letting $latex D(t) = 0$$ and $latex E(t) = \Delta^{i,j} (t)$$
we have
$latex \[
    \bar{E}_{i,j}
    = \frac{ \partial s } { \partial E_{i,j} }
    = (s \circ F)'(t)
    = \R{tr} [ \bar{F}^\R{T} D(t) \Delta^{i,j} ]
\] $$
$latex \[
    \bar{E}_{i,j}
    = \sum_k \bar{F}^\R{T}_{j,k} C_{k,i}
    = \sum_k D^\R{T}_{i,k} \bar{F}_{k,j}
\] $$
$latex \[
    \bar{E} = D^\R{T} \bar{F}
\] $$

$subhead Reverse$$
Reverse mode eliminates $latex C^{(k)}$$ as follows:
for $latex \ell = 0, \ldots , k$$,
$latex \[
\bar{A}^{(\ell)}  = \bar{A}^{(\ell)} + \bar{C}^{(k)} [ B^{(k-\ell)} ] ^\R{T}
\] $$
$latex \[
\bar{B}^{(k-\ell)} =  \bar{B}^{(k-\ell)} + [ A^{(\ell)} ]^\R{T} \bar{C}^{(k)}
\] $$

$childtable%
    include/cppad/example/atomic_four/mat_mul/implement.omh
    %example/atomic_four/mat_mul/forward.cpp
    %example/atomic_four/mat_mul/reverse.cpp
    %example/atomic_four/mat_mul/sparsity.cpp
    %example/atomic_four/mat_mul/rev_depend.cpp
    %example/atomic_four/mat_mul/identical_zero.cpp
%$$

$end
