Functions preprocessor - axkr/symja_android_library GitHub Wiki
- Extend keywords in AST2Expr
- Generate files
- Implementing new functions
- Integrating your own Java library with the WXF format
- Example evaluating partial derivative function
- Integrating your own Java library with the WXF format
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.
If the AST2Expr
definitions have changed these two programs can generate new sources in the Eclipse console output:
- the FunctionIDGenerator.java program is used to generate the file org.matheclipse.core.expression.ID
- the BuiltinGenerator.java program is used to generate the predefined
IBuiltInSymbol
's in file org.matheclipse.core.expression.F
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)
.
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)
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:
- https://github.com/axkr/symja_android_library/blob/master/symja_android_library/matheclipse-core/src/main/java/org/matheclipse/core/expression/WL.java
- https://github.com/axkr/symja_android_library/blob/master/symja_android_library/matheclipse-io/src/test/java/org/matheclipse/io/system/WXFTestCase.java