/* $Id: sparse_jac_fun.hpp 2506 2012-10-24 19:36:49Z bradbell $ */
# ifndef CPPAD_SPARSE_JAC_FUN_INCLUDED
# define CPPAD_SPARSE_JAC_FUN_INCLUDED

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

CppAD is distributed under multiple licenses. This distribution is under
the terms of the 
                    Eclipse Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */
/*
$begin sparse_jac_fun$$
$spell
	Jacobian
	jac
	cppad
	hpp
	fp
	CppAD
	namespace
	const
	bool
	exp
	arg
$$

$section Evaluate a Function That Has a Sparse Jacobian$$ 

$index sparse_jac_fun, function$$
$index function, sparse_jac_fun$$

$head Syntax$$
$codei%# include <cppad/speed/sparse_jac_fun.hpp>
%$$
$codei%sparse_jac_fun(%m%, %n%, %x%, %row%, %col%, %p%, %fp%)%$$

$head Purpose$$
This routine evaluates
$latex f(x)$$ and $latex f^{(1)} (x)$$
where the Jacobian $latex f^{(1)} (x)$$ is sparse.
The function $latex f : \B{R}^n \rightarrow \B{R}^m$$ only depends on the 
size and contents of the index vectors $icode row$$ and $icode col$$. 
The non-zero entries in the Jacobian of this function have 
one of the following forms:
$latex \[
	\D{ f[row[k]]}{x[col[k]]}
\] $$
for some $latex k $$ between zero and $latex K-1$$.
All the other terms of the Jacobian are zero.

$head Inclusion$$
The template function $code sparse_jac_fun$$ 
is defined in the $code CppAD$$ namespace by including 
the file $code cppad/speed/sparse_jac_fun.hpp$$ 
(relative to the CppAD distribution directory).
It is only intended for example and testing purposes, 
so it is not automatically included by
$cref/cppad.hpp/cppad/$$.

$head Float$$
The type $icode Float$$ must be a $cref NumericType$$.
In addition, if $icode y$$ and $icode z$$ are $icode Float$$ objects,
$codei%
	%y% = exp(%z%)
%$$ 
must set the $icode y$$ equal the exponential of $icode z$$, i.e.,
the derivative of $icode y$$ with respect to $icode z$$ is equal to $icode y$$.

$head FloatVector$$
The type $icode FloatVector$$ is any
$cref SimpleVector$$, or it can be a raw pointer, 
with elements of type $icode Float$$.

$head n$$
The argument $icode n$$ has prototype
$icode%
	size_t %n%
%$$
It specifies the dimension for the domain space for $latex f(x)$$.

$head m$$
The argument $icode m$$ has prototype
$icode%
	size_t %m%
%$$
It specifies the dimension for the range space for $latex f(x)$$.

$head x$$
The argument $icode x$$ has prototype
$codei%
	const %FloatVector%& %x%
%$$
It contains the argument value for which the function,
or its derivative, is being evaluated.
We use $latex n$$ to denote the size of the vector $icode x$$.

$head row$$
The argument $icode row$$ has prototype
$codei%
	 const CppAD::vector<size_t>& %row%
%$$
It specifies indices in the range of $latex f(x)$$ for non-zero components
of the Jacobian
(see $cref/purpose/sparse_hes_fun/Purpose/$$ above).
The value $latex K$$ is defined by $icode%K% = %row%.size()%$$.
All the elements of $icode row$$ must be between zero and $icode%m%-1%$$.

$head col$$
The argument $icode row$$ has prototype
$codei%
	 const CppAD::vector<size_t>& %col%
%$$
and its size must be $latex K$$; i.e., the same as for $icode col$$.
It specifies the component of $latex x$$ for 
the non-zero Jacobian terms.
All the elements of $icode col$$ must be between zero and $icode%n%-1%$$.

$head p$$
The argument $icode p$$ has prototype
$icode%
	size_t %p%
%$$
It is either zero or one and
specifies the order of the derivative of $latex f$$
that is being evaluated, i.e., $latex f^{(p)} (x)$$ is evaluated.

$head fp$$
The argument $icode fp$$ has prototype
$icode%
	%FloatVector%& %fp%
%$$
The input value of the elements of $icode fp$$ does not matter.

$subhead Function$$
If $icode p$$ is zero, $icode fp$$ has size $latex m$$ and
$codei%(%fp%[0]%, ... , %fp%[%m%-1])%$$ is the value of $latex f(x)$$.

$subhead Jacobian$$
If $icode p$$ is one, $icode fp$$ has size $icode%m% * %n%$$ and 
for $latex i = 0 , \ldots , m-1$$,
$latex j = 0 , \ldots , n-1$$
$latex \[
	\D{f[i]}{x[j]} = fp [ i * n + j ]
\] $$

$children%
	speed/example/sparse_jac_fun.cpp%
	omh/sparse_jac_fun.omh
%$$

$head Example$$
The file
$cref sparse_jac_fun.cpp$$
contains an example and test  of $code sparse_jac_fun.hpp$$.
It returns true if it succeeds and false otherwise.

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

$end
------------------------------------------------------------------------------
*/
// BEGIN C++
# include <cppad/local/cppad_assert.hpp>
# include <cppad/check_numeric_type.hpp>
# include <cppad/vector.hpp>

// following needed by gcc under fedora 17 so that exp(double) is defined
# include <cppad/base_require.hpp> 

namespace CppAD {
	template <class Float, class FloatVector>
	void sparse_jac_fun(
		size_t                       m    ,
		size_t                       n    ,
		const FloatVector&           x    ,
		const CppAD::vector<size_t>& row  , 
		const CppAD::vector<size_t>& col  , 
		size_t                       p    ,
		FloatVector&                 fp   )
	{
		// check numeric type specifications
		CheckNumericType<Float>();
		// check value of p
		CPPAD_ASSERT_KNOWN(
			p < 2,
			"sparse_jac_fun: p > 1"
		);
		size_t i, j, k;
		size_t size = m;
		if( p > 0 )
			size *= n;
		for(k = 0; k < size; k++)
			fp[k] = Float(0);

		size_t K = row.size();
		Float t;
		for(k = 0; k < K; k++)
		{	i    = row[k];
			j    = col[k];
			t    = exp( x[j] * x[j] / 2.0 );	
			switch(p)
			{
				case 0:
				fp[i] += t;
				break;

				case 1:
				fp[i * n + j] += t * x[j];
				break;
			}
		}
	}
}
// END C++
# endif
