
Derivative Library Tutorial
Wang Feng
March 18, 2014
1 Headers, Namespace and Compilation
The header file for derivative is
#include <derivative/derivative.hpp>
The header file for second derivative is
#include <derivative/second derivative.hpp>
The namespace of derivative is
using namespace numeric;
A typical commandline compilation is
g++ -o test test.cc -std=c++11 -O2 -IPATH/TO/HEAD/FILE
2 Derivative
2.1 derivatives of normal functions
To calculate the derivative of a simple function f(x, y) = sin x cos y, we first need to define
the function in c++ code:
double fxy ( double x, double y )
{
return std::sin( x ) * std::cos( y );
}
then generate the
∂f (x,y)
∂x
using
auto const& dfx = numeric::make derivative<0>( fxy );
and
∂f (x,y)
∂y
using
auto const& dfy = numeric::make derivative<1>( fxy );
to evaluate
∂f (x,y)
∂x
(1,2)
, we simply call dfx as a normal c++ function
std::cout << ”df / dx at ( 1, 2 ) is ” << dfx( 1, 2 ) << ”\n”;
also, to evaluate
∂f (x,y)
∂y
(1,2)
std::cout << ”df / dy at ( 1, 2 ) is ” << dfy( 1, 2 ) << ”\n”;
2.2 derivatives of functions that receive a pointer as argument
Same function as in the previous subsection, but we make some modification to make it
receive only one pointer:
double fxy( double* x )
{
return std::sin(x[0]) * std::cos(x[1]);
}
then define the derivatives:
auto const& dfdx = numeric::make derivative( fxy, 0 );
auto const& dfdy = numeric::make derivative( fxy, 1 );
to evaluate them at the point(1,2), we make an array x[], then call them as normal c
functions:
double x[] = { 1.0, 2.0 };
std::cout << ”\ndf/dx at (1.0, 2.0) is ” << dfdx(x) << ”\n”;
std::cout << ”\ndf/dy at (1.0, 2.0) is ” << dfdy(x) << ”\n”;
2.3 more than functions
Our derivative can also deal with functors, lambda objects etc., here is an example with a
functor:
#include <derivative/derivative.hpp>
#include <iostream>
#include <cmath>
struct sfxy
{
double a;
sfxy( double a = 2.0 ) : a(a ) {}
double operator()( double* x ) const
{
return a * std::sin(x[0]) * std::cos(x[1]);
}
};
int main()
{
sfxy const fxy( 5.0 );
auto const& dfdx = numeric::make derivative( fxy, 0 );
auto const& dfdy = numeric::make derivative( fxy, 1 );
double x[] = { 1.0, 2.0 };
std::cout << ”\ndf/dx at (1.0, 2.0) is ” << dfdx(x) << ”\n”;
std::cout << ”\ndf/dy at (1.0, 2.0) is ” << dfdy(x) << ”\n”;
return 0;
}
3 Second Derivaitve
The code creating the second derivative objects is very similar to the code creating the first
derivatives, but with one more parameter.
Second derivatives for a normal c function:
double fxyz( double x, double y, double z )
{
return std::sin(std::pow( x, y ) * z);
}
void fxyz test()
{
auto const& fxyz 00 = numeric::make second derivative<0,0>( fxyz );
auto const& fxyz 01 = numeric::make second derivative<0,1>( fxyz );
auto const& fxyz 02 = numeric::make second derivative<0,2>( fxyz );
auto const& fxyz 10 = numeric::make second derivative<1,0>( fxyz );
auto const& fxyz 11 = numeric::make second derivative<1,1>( fxyz );
auto const& fxyz 12 = numeric::make second derivative<1,2>( fxyz );
auto const& fxyz 20 = numeric::make second derivative<2,0>( fxyz );
auto const& fxyz 21 = numeric::make second derivative<2,1>( fxyz );
auto const& fxyz 22 = numeric::make second derivative<2,2>( fxyz );
std::cout << ”\nfxyz 00 at(1.0, 2.0, 3.0) is ” << fxyz 00( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 01 at(1.0, 2.0, 3.0) is ” << fxyz 01( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 02 at(1.0, 2.0, 3.0) is ” << fxyz 02( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 10 at(1.0, 2.0, 3.0) is ” << fxyz 10( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 11 at(1.0, 2.0, 3.0) is ” << fxyz 11( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 12 at(1.0, 2.0, 3.0) is ” << fxyz 12( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 20 at(1.0, 2.0, 3.0) is ” << fxyz 20( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 21 at(1.0, 2.0, 3.0) is ” << fxyz 21( 1.0, 2.0, 3.0 ) << ”\n”;
std::cout << ”\nfxyz 22 at(1.0, 2.0, 3.0) is ” << fxyz 22( 1.0, 2.0, 3.0 ) << ”\n”;
}
And for a function receiving a pointer as parameter:
double gxyz( double* x )
{
return std::sin(std::pow( x[0], x[1] ) * x[2] );
}
void gxyz test()
{
auto const& gxyz 00 = numeric::make second derivative( gxyz, 0, 0 );
auto const& gxyz 01 = numeric::make second derivative( gxyz, 0, 1 );
auto const& gxyz 02 = numeric::make second derivative( gxyz, 0, 2 );
auto const& gxyz 10 = numeric::make second derivative( gxyz, 1, 0 );
auto const& gxyz 11 = numeric::make second derivative( gxyz, 1, 1 );
auto const& gxyz 12 = numeric::make second derivative( gxyz, 1, 2 );
auto const& gxyz 20 = numeric::make second derivative( gxyz, 2, 0 );
auto const& gxyz 21 = numeric::make second derivative( gxyz, 2, 1 );
auto const& gxyz 22 = numeric::make second derivative( gxyz, 2, 2 );
double x[] = { 1.0, 2.0, 3.0 };
std::cout << ”\ngxyz 00 at(1.0, 2.0, 3.0) is ” << gxyz 00( x ) << ”\n”;
std::cout << ”\ngxyz 01 at(1.0, 2.0, 3.0) is ” << gxyz 01( x ) << ”\n”;
std::cout << ”\ngxyz 02 at(1.0, 2.0, 3.0) is ” << gxyz 02( x ) << ”\n”;
std::cout << ”\ngxyz 10 at(1.0, 2.0, 3.0) is ” << gxyz 10( x ) << ”\n”;
std::cout << ”\ngxyz 11 at(1.0, 2.0, 3.0) is ” << gxyz 11( x ) << ”\n”;
std::cout << ”\ngxyz 12 at(1.0, 2.0, 3.0) is ” << gxyz 12( x ) << ”\n”;
std::cout << ”\ngxyz 20 at(1.0, 2.0, 3.0) is ” << gxyz 20( x ) << ”\n”;
std::cout << ”\ngxyz 21 at(1.0, 2.0, 3.0) is ” << gxyz 21( x ) << ”\n”;
std::cout << ”\ngxyz 22 at(1.0, 2.0, 3.0) is ” << gxyz 22( x ) << ”\n”;
}