Skip to content

Functions preprocessor

Axel Kramer edited this page Jan 26, 2024 · 11 revisions

Add new identifiers in AST2Expr

To add new predefined constants or function symbols you have to extend the following String arrays in org.matheclipse.core.convert.AST2Expr

  • UPPERCASE_SYMBOL_STRINGS - symbols which are exactly one uppercase constant or function
  • DOLLAR_STRINGS - symbols starting with a '$' character
  • SYMBOL_STRINGS - constant identifiers, which are not used as a function identifier
  • FUNCTION_STRINGS - function identifiers

We can for example add a new user function MyFunction to the FUNCTION_STRINGS array.

Generate files

If the AST2Expr definitions have changed these two programs can generate new sources in the Eclipse console output:

Implementing new functions

The built-in Symja constants are implemented in the file:

The built-in Symja functions are implemented in the packages:

System built-in functions must implement the interface IFunctionEvaluator and are evaluated according to the assigned function symbol attributes defined in the IFunctionEvaluator#setUp() method (only very special built-in functions must implement the interface ICoreFunctionEvaluator and evaluate their arguments in a non standard way).

A lot of the system functions have associated pattern matching rule files in the folders:

These rules are converted by the class org.matheclipse.core.preprocessor.RulePreprocessor into the package org.matheclipse.core.reflection.system.rules

A new built-in Symja function name should be added to org.matheclipse.core.convert.AST2Expr#FUNCTION_STRINGS String[] array, with a leading upper case character in its name.

A typical "template" for an example built-in function MyFunction is implemented like this. The evaluation of MyFunction({a,b,c}) should return the first argument {a,b,c} if the first argument is a list.

package org.matheclipse.core.builtin;

import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IExpr;

public class UserFunctions {
	static {
		F.MyFunction.setEvaluator(new MyFunction());
	}

	private static class MyFunction extends AbstractEvaluator {

		@Override
		public IExpr evaluate(final IAST ast, EvalEngine engine) {
		   // test if only 1 argument is allowed:
			Validate.checkRange(ast, 2);
			if (ast.arg1().isList()) {
				return ast.arg1();
			}
			return F.NIL;
		}
	}

	private final static UserFunctions CONST = new UserFunctions();

	public static UserFunctions initialize() {
		return CONST;
	}

	private UserFunctions() {

	}

}

It must be initialized in the F.class static block:

...

	static {
		Thread INIT_THREAD = null;
...

			VectorAnalysisFunctions.initialize();
			QuantityFunctions.initialize();
			FinancialFunctions.initialize();
			WXFFunctions.initialize();
			WindowFunctions.initialize();
			UserFunctions.initialize();
...


	}	
...

Now the evaluation of MyFunction({a,b,c}) returns the first argument {a,b,c}. And the evaluation of MyFunction(test) returns unevaluated as MyFunction(test).

Example evaluating partial derivative function

In the following section the evaluation and implementation of the partial derivative function is described.

Example usage:

>> D(sin(x)^3 + x, x)
1+3*Sin(x)^2*Cos(x)

To see the intermediate evaluation steps you can use the Trace( ) function

>> Trace(D(sin(x)^3 + x, x)) 

Internally the D(<expression>, x) function uses the Derivative( ) function. Both function names are defined in

Both of these built-in functions are defined in the org.matheclipse.core.reflection.system package:

The Derivative( ) rules are converted by the class org.matheclipse.core.preprocessor.RulePreprocessor into the rules java file org.matheclipse.core.reflection.system.rules.DerivativeRules.

To use these functions (or other built-in constants and functions) from within other java sources you can import org.matheclipse.core.expression.F

For D and Derivative there are two static methods defined:

public static IAST D(final IExpr a0, final IExpr a1)

public static IAST Derivative(final IExpr... a)

Integrating your own Java library with the WXF format

For creating a quick prototype which can use Symja functions to call your own library, you should consider implementing functions similar to the BinarySerialize, BinaryDeserialize functions with the WXF format:

The implementation which is used in Symja can be found here:

Clone this wiki locally