f=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");
defines a function which maps from 3-space to 2-space. The first and
second derivatives of an ExpressionFunction are available.The evaluate for the Expression Function uses the coordinates of the point in the domain to give values to identifiers in the expression, and then "executes" the expression.
In the constructor shown above, the first string is a list of identifiers,
(enclosed in parentheses, and separated by commas), which associates an
identifier to each coordinate of the point in the domain. The domain is always
(for this constructor) a RealEuclideanNSpace
, with a dimension which is the number of identifiers listed. There is no
special meaning to the identifier names,
f1=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");
f2=new NAExpressionFunction("(r,theta,phi)","(sin(r)*sin(theta)*sin(phi),phi*theta)");
and,
f3=new NAExpressionFunction("(z,y,x)","(sin(z)*sin(y)*sin(x),x*y)");
all define functions which evalute to the same thing. However, the order is
important,
f1=new NAExpressionFunction("(x,y,z)","(sin(x)*sin(y)*sin(z),z*y)");
and,
f2=new NAExpressionFunction("(y,x,z)","(sin(x)*sin(y)*sin(z),z*y)");
do not define the same function.The second string passed to this constructor is a list of expressions (enclosed in parentheses, and separated by commas). This string gives the formula for computing the coordinates of the result. The range (again, for this constructor), is always a RealEuclideanNSpace. The dimension of the range of the function is the number of expressions listed. The expressions may use any (or none) of the identifiers listed in the first argument. If other identifiers are used, a run time error will result when the function is evaluated.
The basic operators +,-,*,/ and ** (exponentiation) are allowed. The following
ways of defining constants are allowed:
The values of the identifiers
There are quite a few functions available for use in the expressions. They all take a single argument. The "basic" functions are from the "C" math library:
If the SpecialFunctions library (specfun), from netlib, is installed (see the installation instructions), then the following special functions are available:
NAO/ExprFn.hand link against library
libNAOBase.aThe following constructors are provided:
| NAExpressionFunction(FS ,expression ); | ||||||
| Create an Expression Function. | ||||||
|
| NAExpressionFunction(expression ); | |||
| Create a new ExpressionFunction. | |||
|
| NAExpressionFunction(variableList ,expression ); | ||||||
| Create a new ExpressionFunction. | ||||||
|
| NAExpressionFunction(FS ,variables ,expression ); | |||||||||
| Create an Expression Function. | |||||||||
|
| NAExpressionFunction(variables ,expression ,declarations ,values ); | ||||||||||||
| Create an Expression Function. | ||||||||||||
|
| NAExpressionFunction(unknowns ,expressions ,declarations ,constants ); | ||||||||||||
| Create a new ExpressionFunction. | ||||||||||||
|
The following member functions are available in addition to those provided
by the abstract interface NAFunction:
The NAExpressionFunction uses the strings input by the user, breaks them up into individual expressions, "compiles" them using the ExpressionCompiler, and stores pointers to the list of object codes. When the function is called to be evaluated, the NAExpressionFunction class uses the stored list of identifiers to set the identifiers in the symbol table of the object code to the corresponding coordinate of the point at which the function is being evaluated.
Derivatives are performed by "differentiating" the object code. This is done by the ExpressionCompiler library, and uses standard techniques for differentiation of subroutines. Essentially, all operations in the object code are duplicated, as are the registers they operate on. The second operation is then modified to perform the derivative of the operation. ( Ri+Rj becomes dRi+dRj, Ri*Rj becomes dRi*Rj+Ri*dRj, etc.). The result is an object code which evaluates the function and its derivative. A symbolic representation of the derivative is never constructed.
The constructor creates object code, and two differentiations of the object code. In the differentiation, identifiers which are function calls (eg sin(x)) generate new identifiers for the derivatives, simple by prepending a "D" (sin(x) -> Dsin(x) and DDsin(x)). The derivatives of the ExpressionFunction therefore depend on the symbols for special functions and their derivatives. The current implementation of the NAExpressionFunction sets many of the basic functions (see the overview above), and their derivatives. Second derivatives are not set at this time, nor are first derivatives of the special functions.
#include <NAO/ExprFn.h>
NAFunction *f=new NAExpressionFunction("(theta)",
"(4*cos(2*\%pi*theta),4*sin(2*\%pi*theta))");
NAPointOnManifold *x=new NADoublePointOnManifold(1);
NAPointOnManifold *y=new NADoublePointOnManifold(2);
cout << "Points around a circle of radius 4" << endl;
for(i=0;i<10;i++)
{
x->setCoordinate(0,.1*i);
f->evaluate(x,y);
cout << i << " (" << y->getCoordinate(0).Double() << "," <<
y->getCoordinate(1).Double() << ")" << endl;
}
Getting constants into a string is not as easy as it could be. Here's
an example where the constants are written into a string:
#include <NAO/ExprFn.h>
char list[256];
char expression[80];
strcpy(list,"(");
sprintf(expression,"sin(2*\%pi*theta)*(%f+%f*cos(2*\%pi*phi))",R1,R0);
strcat(list,expression);
strcat(list,",");
sprintf(expression,"cos(2*\%pi*theta)*(%f+%f*cos(2*\%pi*phi))",R1,R0);
strcat(list,expression);
strcat(list,",");
sprintf(expression,"%f*sin(2*\%pi*theta)",R0);
strcat(list,expression);
strcat(list,",");
NAFunction *f=new NAExpressionFunction("(theta,phi)",expression);
NAPointOnManifold *x=new NADoublePointOnManifold(2);
NAPointOnManifold *y=new NADoublePointOnManifold(2);
cout << "Points around a torus with small radius of " << R0
<< " and large radius << R1 << endl;
for(i=0;i<10;i++)
{
theta=i*.1;
x->setCoordinate(0,theta);
for(j=0;j<10;i++)
{
phi=j*.1;
x->setCoordinate(1,phi);
f->evaluate(x,y);
cout << "(" << i << "," << j << ") -> (" << y->getCoordinate(0).Double() << "," <<
y->getCoordinate(1).Double() << ")" << endl;
}
}
Siblings of this class:
ExpressionFunctions are used in one of the constructors for the
NATableFunction
which uses an ExpressionFunction (built and destroyed in the constructor) to
give values to the vertices of a grid. The Expression Compiler is
used in the routines:
[Comments | NAO home page ]
[ IBM home page | Order | Privacy | ContactIBM | Legal ]