Math Parser Interface

Parser initialization / deinitialization

[DLL interface]

Create a new instance handle. You can create as many different instance handles as you like. Each will internally reference a different parser object. When using the DLL it is necessary to manually release any parser handle created by mupInit() by calling mupRelease(hParser).

muParserHandle_t hParser;
hParser = mupInit(); // Create a new handle

// use the parser...
mupRelease(hParser); // Release an existing parser handle

Internally a handle is nothing more than a pointer to a parser object casted to a void pointer.

[Parser class interface]

Code for creating a new parser object. (In case of dynamic allocation use new and delete for initialization and deinitialization.)

mu::Parser parser;

Setting the expression

[DLL interface]

Setting the expression when using the DLL requires a valid parser handle and a pointer to const char pointing to the expression.

mupSetExpr(hParser, szLine);

See also: example2/example2.c.

[Parser class interface]

Setting the expression using the parser class requires a std::string containing the expression as the only parameter.


See also: example1/example1.cpp; src/muParserTest.cpp.

Defining identifier character sets

Sometimes it is necessary to change the character sets that are used for token identifiers in order to avoid conflicts. The parser uses three different character sets for names, operators and infix operators.

The name character set, is used for:
  • function identifiers
  • variable identifiers
  • constant identifiers
The operator character set is used for:
  • binary operator identifiers
  • postfix operator identifiers

The Infix operator charset is used for infix operator identifiers only

When using the default implementation mu::muParser directly, you can skip this section. (The DLL version uses the default implementation internally.)

[DLL interface]

mupDefineNameChars(hParser, "0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
mupDefineOprtChars(hParser, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_");
mupDefineInfixOprtChars(hParser, "/+-*^?<>=#!$%&|~'_");

[Parser class interface]

See also: muparser/src/muParser.cpp; muparser/src/muParserInt.cpp.

Evaluating an expression

Single return value

Expression evaluation is done by calling the mupEval() function in the DLL version or the Eval() member function of a parser object. When evaluating an expression for the first time the parser evaluates the expression string directly and creates a bytecode during this first time evaluation. Every sucessive call to Eval() will evaluate the bytecode directly unless you call a function that will silently reset the parser to string parse mode. Some functions invalidate the bytecode due to possible changes in callback function pointers or variable addresses. By doing so they effectively cause a recreation of the bytecode during the next call to Eval().

Internally there are different evaluation functions. One for parsing from a string, the other for parsing from bytecode (and a third one used only if the expression can be simplified to a constant). Initially, Eval() will call the string parsing function which is slow due to all the necessary syntax checking, variable lookup, and bytecode creation. Once this function succeeds, Eval() will change its internal parse function pointer to either the bytecode parsing function or the const result function which are significantly (approx. 1000 times) faster. You don't have to worry about this, it's done automatically, just keep in mind that the first time evaluation of an expression is significantly slower than any successive call to Eval().

[DLL interface]

double fVal;
fVal = mupEval(hParser);

See also: example2/example2.c.

[Parser class interface]

double fVal;
  fVal = parser.Eval();
catch (Parser::exception_type &e)
  std::cout << e.GetMsg() << endl;

See also: example1/example1.cpp.

If the expression contains multiple separated subexpressions the return value of Eval()/ mupEval() is the result of the last subexpression. If you need all of the results use the Eval overload described in the next section.

Multiple return values

muparser accepts expressions that are made up of several subexpressions delimited by the function argument separator. For instance take a look at the following expression:


It is made up of three expression separated by commas hence it will create three return values. (Assuming the comma is defined as the argument separator). The number of return values as well as their value can be queried with an overload of the Eval function. This overload takes a reference to an integer value for storing the total number of return values and returns a pointer to an array of value_type holding the actual values with the first value at the botton of the array and the last at the top.

[DLL interface]

int nNum, i;
muFloat_t *v = mupEvalMulti(hParser, &nNum);
for (i=0; i<nNum; ++i)
	printf("v[i]=%2.2f\n", v[i]);

[Parser class interface]

int nNum;
value_type *v = parser.Eval(nNum);
for (int i=0; i<nNum; ++i)
	std::cout << v[i] << "\n";

See also: example1/example1.cpp.

The function GetNumResults() can be used in order to finf out whether a given expression has produced multiple return values.

Bulk mode evaluations

Please note: Using the bulk mode without also enabling OpenMP during compilation is pointless!

The basic idea behind the bulkmode is to minimize the overhead of function calls and allow for parallelization of the expression evaluation loop when the same espression shall be evaluated for ever changing variables. If muparser was compiled with OpenMP support the calculation load will be spread among all available CPU cores. When using the bulk mode variable pointers submitted to the DefineVar function must be arrays instead of single variables. All variable arrays must have the same size and each array index represents a distinct set of variables to be used in the expression.

Although the bulk mode does work with standard callback functions it may sometimes be necessary to have additional information inside a callback function. Especially Informations like the index of the current variable set and the index of the thread performing the calculation may be crucial to the evaluation process. To facilitate this need a special set of callback functions was added. Those must use callbacks of type bulkfun_type1...bulkfun_type10. They take two additional parameters. The first one is the variable index, the second one is the thread id.

[DLL interface]

void CalcBulk()
	int nBulkSize = 200, i;

	// allocate the arrays for variables and return values
	muFloat_t *x = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
	muFloat_t *y = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));
	muFloat_t *r = (muFloat_t*)malloc(nBulkSize * sizeof(muFloat_t));

	// initialize the parser and variables
	muParserHandle_t hParser = mupCreate(muBASETYPE_FLOAT);  
	for (i=0; i<nBulkSize; ++i)
		x[i] = i;
		y[i] = i;
		r[i] = 0;

	// Set up variables and functions and evaluate the expression
	mupDefineVar(hParser, "x", x);  
	mupDefineVar(hParser, "y", y);
	mupDefineBulkFun1(hParser, "bulktest", BulkTest);
	mupSetExpr(hParser, "bulktest(x+y)");
	mupEvalBulk(hParser, r, nBulkSize);
	if (mupError(hParser))
		printf("Message:  %s\n", mupGetErrorMsg(hParser) );
		printf("Token:    %s\n", mupGetErrorToken(hParser) );
		printf("Position: %d\n", mupGetErrorPos(hParser) );
		printf("Errc:     %d\n", mupGetErrorCode(hParser) );

	// Output the result
	for (i=0; i<nBulkSize; ++i)
		printf("%d: bulkfun(%2.2f + %2.2f) = %2.2f\n", i, x[i], y[i], r[i]);