# ifndef CPPAD_SPEED_MAT_SUM_SQ_HPP
# define CPPAD_SPEED_MAT_SUM_SQ_HPP
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 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 mat_sum_sq$$
$spell
    sq
    namespace
    const
    CppAD
    sq
    cppad
    hpp
$$

$section Sum Elements of a Matrix Times Itself$$

$head Syntax$$
$codei%# include <cppad/speed/mat_sum_sq.hpp>
%$$
$icode%mat_sum_sq(%n%, %x%, %y%, %z%)%$$

$head Purpose$$
This routine is intended for use with the matrix multiply speed tests;
to be specific, it computes
$latex \[
\begin{array}{rcl}
    y_{i,j} & = & \sum_{k=0}^{n-1} x_{i,k} x_{k,j}
    \\
    z_0     & = & \sum_{i=0}^{n-1} \sum_{j=0}^{n-1} y_{i,j}
\end{array}
\] $$
see $cref link_mat_mul$$.

$head Inclusion$$
The template function $code mat_sum_sq$$ is defined in the $code CppAD$$
namespace by including
the file $code cppad/speed/mat_sum_sq.hpp$$
(relative to the CppAD distribution directory).

$head n$$
This argument has prototype
$codei%
    size_t %n%
%$$
It specifies the size of the matrices.

$head x$$
The argument $icode x$$ has prototype
$codei%
    const %Vector% &%x%
%$$
and $icode%x%.size() == %n% * %n%$$.
It contains the elements of $latex x$$ in row major order; i.e.,
$latex \[
    x_{i,j} = x [ i * n + j ]
\] $$

$head y$$
The argument $icode y$$ has prototype
$codei%
    %Vector%& %y%
%$$
and $icode%y%.size() == %n% * %n%$$.
The input value of its elements does not matter.
Upon return,
$latex \[
\begin{array}{rcl}
    y_{i,j}        & = & \sum_{k=0}^{n-1} x_{i,k} x_{k,j}
    \\
    y[ i * n + j ] & = & y_{i,j}
\end{array}
\] $$


$head z$$
The argument $icode d$$ has prototype
$codei%
    %Vector%& %z%
%$$.
The input value of its element does not matter.
Upon return
$latex \[
\begin{array}{rcl}
    z_0 & = & \sum_{i=0}^{n-1} \sum_{j=0}^n y_{i,j}
    \\
    z[0] & = & z_0
\end{array}
\] $$

$head Vector$$
The type $icode Vector$$ is any
$cref SimpleVector$$, or it can be a raw pointer to the vector elements.
The element type must support
addition, multiplication, and assignment to both its own type
and to a double value.

$children%
    speed/example/mat_sum_sq.cpp%
    omh/mat_sum_sq_hpp.omh
%$$


$head Example$$
The file
$cref mat_sum_sq.cpp$$
contains an example and test of $code mat_sum_sq.hpp$$.

$head Source Code$$
The file
$cref mat_sum_sq.hpp$$
contains the source for this template function.

$end
------------------------------------------------------------------------------
*/
// BEGIN C++
# include <cstddef>
//
namespace CppAD {
    template <class Vector>
    void mat_sum_sq(size_t n, Vector& x , Vector& y , Vector& z)
    {   size_t i, j, k;
        // Very simple computation of y = x * x for speed comparison
        for(i = 0; i < n; i++)
        {   for(j = 0; j < n; j++)
            {   y[i * n + j] = 0.;
                for(k = 0; k < n; k++)
                    y[i * n + j] += x[i * n + k] * x[k * n + j];
            }
        }
        z[0] = 0.;
        for(i = 0; i < n; i++)
        {   for(j = 0; j < n; j++)
                z[0] += y[i * n + j];
        }
        return;
    }

}
// END C++
# endif
