Bibliotheque fonctionnelle : opérations, composition d'objets fonctions

Description

Extension de la STL (http://www.cplusplus.com/reference/std/functional/) avec mes conventions de nommage, cette petite bibliothèque permet la définition de fonctions sous forme de classe.

Il peut être pratique de pouvoir définir des fonctions "objets", c'est-à-dire des objets dont l'opérateur '()' est défini, et qui possède des attributs et des méthodes comme tout objet. Comme cela vous pouvez définir des méthodes "setAccuracy" ou "setPrecision", "setCoefficients", "setKnotVector", etc. Utilisée sans abus, elle peut vous donner un code plus concis à l'utilisation des fonctions définies à partir de ces templates.

Cette bibliothèque inclus les opérateurs + - * / et % (composition à ne pas confondre avec le modulo classique), permettant de pouvoir appeler les fonctions sous la forme (f + g)(x) par exemple.

Source / Exemple :


#include "Function.h"
#include "Integral.h"
#include <iostream>

/* Exemple d'utilisation des fonctions sous forme d'objet */

/* Définition des fonctions de type R -> R */
typedef std::unary_function<double, double> RealFunction;

/* Une simple fonction x² */
class SquareFunction : public RealFunction
{
public:
	double operator () ( double x ) const { return x*x; }
};

/* Une fonction polynôme */
class PolynomFunction : public RealFunction
{
public:
	PolynomFunction( double * coeffs, int degree ) : _coeffs( coeffs ), _degree( degree ) {}
	double operator () ( double x ) const
	{
		double y = 0.0, xn = 1.0;
		int i;

		for ( i = _degree; i >= 0; i-- )
		{
			y += _coeffs[ i ] * xn;
			xn *= x;
		}
		return y;
	}
protected:
	double * _coeffs;
	int _degree;
};

/* Une classe vecteur (qui n'est pas une fonction) */
class Vector3
{
public:
	Vector3( double x, double y, double z ) : _x( x ), _y( y ), _z( z ) {}
	double length() const { return sqrt( _x * _x + _y * _y + _z * _z ); }
private:
	double _x, _y, _z;
};

/* Une classe hélice */
class Helix3 : public std::unary_function<double, Vector3>
{
public:
	Vector3 operator () ( double t ) const { return Vector3( cos( t ), sin( t ), t ); }
	// Vecteur tangent
	Vector3 derivative( double t ) const { return Vector3( -sin( t ), cos( t ), 1. ); }
};

int main(int argc, char **argv)
{
	using std::cout;
	using std::endl;

	// x²
	double coeffs1[] = { 1, 0, 0 };
	PolynomFunction polynom1( coeffs1, 2 );

	// 2x + 1
	double coeffs2[] = { 2, 1 };
	PolynomFunction polynom2( coeffs2, 1 );

	// L'opérateur '%' est défini comme l'opérateur de composition.
	// Ceci revient à calculer (2x + 1)²
	cout << "Calcul de (2x + 1)² avec x = 3 : " << ( polynom1 % polynom2 )( 3. ) << endl;

	// Utilisation de la méthode adaptive de l'intégration de Simpson.
	SimpsonIntegral<PolynomFunction> integral( polynom1 );
	cout << "Intégrale de x² sur [0,1] : " << integral( 0., 1. ) << endl;

	// Utilisation d'un adaptateur pour les intégrales de fonctions plus complexes.
	cout << "Intégrale de x² + 2x + 1 sur [0,1] : " << simpson_integral( polynom1 + polynom2 )( 0., 1. ) << endl;

	// Composition avec appel de la méthode &Vector3::length :
	//
	// std::mem_fun_ref( &Vector3::length ) crée un objet fonction pointant sur la méthode Vector3::length.
	//
	// Helix3 : R -> R^3
	// Vector3::length : R^3 -> R
	// h : R -> R
	//
	// avec h(x) = Vector3::length( Helix3( x ) )
	cout << "Distance de l'hélice à l'origine à t = pi : " << ( std::mem_fun_ref( &Vector3::length ) % Helix3() )( M_PI ) << endl;

	// Calcul de la longueur parcourue sur une courbe :
	//
	// Pour composer des fonctions, nous devons s'assurer qu'elles sont unaires.
	// Dans le cas contraire, nous devons fixer un des arguments.
	// std::bind1st( f( x, y ), c ) est équivalent à g( y ) = f( c, y ) avec x = c fixé.
	//
	// Helix3::derivative est considérée comme une fonction binaire (accepte '*this' et un réel t).
	//
	// Ici nous calculons l'intégrale de la norme du vecteur tangent de la courbe.
	cout << "Longueur parcourue sur une hélice pour t dans [0,pi] : " <<
		simpson_integral(
			std::mem_fun_ref( &Vector3::length ) % std::bind1st( std::mem_fun_ref( &Helix3::derivative ), Helix3() )
		) ( 0., M_PI ) << endl;
	return 0;
}

Conclusion :


Sur le même modèle il est tout à fait possible de définir les opérateurs && || etc. pour étendre cette librairie. Ou bien définir les opérateurs (fonction + réel)(x), (fonction * réel)(x), (en n'oubliant pas la commutativité).

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.