Jep 4 Releases | Jep 3 Releases | Jep 2 Releases | Jep 1 Releases
Contents:round(100000,-5) -> 99999.99999999999 in Round and RInt
parent was not always set when building node trees. SimpleNode.jjtAddChild(Node, int) modified
to ensure this.
java.util.Observable has been deprecated. Code that relies on this feature
has been removed, affecting the Variable and VariableTable classes.
The com.singularsys.jep.misc.VariableTableObserver class has also been removed.
The publishingvariable package serves as a replacement, see below
Jep.getAdditionalComponent(Class<T> cl) method
will now throw an exceptions if two matching components are found. This is safer behaviour,
but may break existing code that adds the same component twice. Outdated components can be
removed with Jep.getAdditionalComponents().remove(JepComponent comp).
FunctionTable.addFunction(String name, PostfixMathCommandI pfmc)
will throw a JepException if the function is a
implements CallbackEvaluationI and extends one of
Unary, Binary, Nary, NaryBinary or Nullary function,
as the types are not compatible.
Typos have been fixed in a number of classes, field and method names. These changes will break existing code.
com.singularsys.jep.walkers
PostfixTreeWalker.supressExaminingChildren(Node)PostfixTreeWalker.suppressExaminingChildren(Node)TreeAnalyzer.VariableComparitorTreeAnalyzer.VariableComparator Not visible outside packagecom.singularsys.jep.configurableparser.matchers
IdentifierTokenMatcher.basicIndetifierMatcher() this was deprecated in previous release and is now deletedIdentifierTokenMatcher.basicIdentifierMatcher()IdentifierTokenMatcher.dottedIndetifierMatcher() this was deprecated in previous release and is now deletedIdentifierTokenMatcher.dottedIdentifierMatcher()com.singularsys.jep - messages.properties
standard.Complex.CannotModififyAnImmutableComplexstandard.Complex.CannotModifyAnImmutableComplexOperator.CommuativeOperator.Commutativewalkers.PostfixTreeWalker.ExpectedSentinalOnStackwalkers.PostfixTreeWalker.ExpectedSentinelOnStack
The new com.singularsys.jep.misc.publishingvariable
package uses the java.util.concurrent.Flow
system of Publishers and Subscribers to provide a system to monitor changes to variables
using the Observer pattern, and replaces
the removed VariableTableObserver class.
It provides:
PublishingVariable a variable which publishes changes to its
value.
PublishingVariableFactory a factory for creating
PublishingVariables.
PublishingVariableTable a variable table which publishes changes
such as adding variables and changes to any of the variables in table.
VariableTableAction an action representing a change to a variable
or table, which is sent by the publisher to subscribers.
VariableTableSubscriber a base class for implementing a
subscriber.
VariableTableUpdater a subscriber which updates a variable table
when the changes to the variables are reported.
The new com.singularsys.jep.misc.overloadedfunctions package package allows functions to be overloaded.
OverloadedUnaryFunction,
OverloadedBinaryFunction,
OverloadedNaryFunction
each allow one of two functions to be selected
during evaluation based on a predicate using the values of arguments.
AlternateFunctions one of a set functions can be
selected based on the number of arguments.
OverloadedFunctionByStructure one of two functions
can be selected based on a predicate using the structure of the Node tree.
AlternateFunctionGrammerMatcher allows the parser
to select a function at parse time from
an AlternateFunctions or OverloadedFunctionByStructure.
OverloadedOperator represents
a pair of operators with different pfmc's that are selected
based on a predicate on the structure of a node.
OverloadResolver used to resolve operators
and pfmc's after parsing, but before evaluation.
The new
com.singularsys.jep.misc.dictionary
package provides a grammar matcher supporting a JSON like
syntax for dictionaries
map = {'x':2, 'y':3} }
and functions like put(map,'x', 5),
get(map,'x'),
and keys(map), for operation on on them.
The new com.singularsys.jep.misc.parallelparsing package has classes to allow equations to be parsed in parallel.
ConcurrentVariableTable is backed by a ConcurrentHashMap and
with atomic methods for adding Variables.
ParallelConfigurableParser has a parse(Reader)
method that is safe to use in multiple threads.
MultipleEquationParser allows each thread to
parse multiple expressions given in a single string, and the
MultipleEquationParsingJep is a Jep class providing
compatibility of some methods when using the ParallelConfigurableParser.
Additionally the ConfigurableParser class has two new
constructors ConfigurableParser(ConfigurableParser cp) and
ConfigurableParser(Jep jep, ConfigurableParser cp)
these both reuse an existing parsers grammar and token matchers,
allowing parsers that can be safely used in multiple threads to be efficiently created.
NullaryFunction, UnaryFunction
BinaryFunction NaryBinaryFunction with a
java.util.function lambda expression.
jep.addFunction("sum",
BinaryFunction.instanceOf((x,y) ->
((Number) x).doubleValue() + ((Number) y).doubleValue());
jep.addFunction("cubrt",
UnaryFunction.instanceOf(Double.class, Math::cbrt));
FunctionTable and FunctionSet
and descendents are now specified in properties files. Both now allow
a function to be skipped if its name in the properties file starts with a !.
PostfixMathCommandI.getDescription() method added to provide a description of the function
for use in documentation. By default descriptions are found in the properties file with key class-name.description.
BigDecSum and BigDecVSum.
com.singularsys.jep.functions.RoundBD PFMC that resolves tricky rounding cases
like round(265.335,2). Here
a simple algorithm like multiplying by 100 and rounding fails due to inexact representation in java.
The RoundBD function converts numbers to BigDecimals with a given scale which gives behaves better.
com.singularsys.jep.misc.functions.AssignableList
PFMC that extends the List function and allows list
of variables to be used on the left hand side of an assignment.
[x,y] = [3,4].
PostfixMathCommand.toString() returns either the name of the function if set
or the class name.PostfixMathCommand.asDouble(0, arg) work with Complex
numbers when the imaginary part is zero, and throw an exception otherwise.
PostfixMathCommand.asType(String.class, 0, arg) a new protected
method to convert an argument to a given type.
ZeroLengthBehaviourI that specifies methods for
setting the behaviour of functions when then encounter zero-length inputs.
Has a inner enum ZeroLengthErrorBehaviour specifying
three types EXCEPTION, NAN, VALUE.
ArrayFunctionBase, now implements ZeroLengthBehaviourI
so can now have a specified value that is returned for zero-length arrays,
with corresponding constructor and getters/setters.
VSum now respects the ZeroLengthErrorBehaviour flag, and allows custom values
to be returned for zero-length arrays.
MinMax now be specified with an MinMaxType enum for a more descriptive constructor.
Abs now accepts Number arguments, using their doubleValue().Comparative now compares List<Object>
using eq(l,r) to compare elements. So vectors with positive and negative zero will be considered equal.
Add, Subtract, Multiply, Divide,
UMinus, Ele, Dot, Cross,
relax the type for vector arguments accepting List<Object>
rather than Vector<Number>.
ExpandingEle versions of the Ele
function whose set expands and modifies the Vector value of the variable.
This can be useful for creating large lists
by repeatedly adding elements.
Count function that counts the number of elements in a list
final modifier from NaryBinaryFunction.eval(Object[])
and NaryBinaryFunction.run(Stack<>).
Dot and Cross have new constructors
for custom implementations of Add, Subtract and Multiply.
Jep classJep method <T> T getAdditionalComponent(Class<T>) method will now
throw an exception if two matching components are found.
It is now a template method so the result can be used directly without casting.
<T> T getAdditionalComponentExact(Class<T> cl) which
checks for exact matches of components rather than instances of subclasses.
Jep.parse(String) now throws a ParseException on a null stringboolean setVariableValue(String name,Object value) method
to set the value of an already existing variable.
OperatorTable2 getOperatorTable2() that casts the return value.
continueParsing() sets the last root node on successful parses.
ConfigurableParser has a new copy-constructor.
ConfigurableParser
has new methods replaceGrammarMatcher, replaceTokenMatcher
to make it easier to modify an existing parser.
[1..5]
moved from the extensions package to the core, with a new
RangeOperator, Range function,
a matcher ListOrRangeGrammarMatcher,
and ConfigurableParserWithRange which has the new grammar matcher.
ExtendedOperatorSet now allow Unicode superscripts as suffix
power operators like x² and x³.
New JccArrayAccessGrammarMatcher that produces
node trees matching the produced by the JccParser.
EmptyOperatorTable has a new getKeys(Operator)
method and deprecates getKey(Operator). removeOperator(op)
now removes all associated keys and replaceOperator(Operator oldOp, Operator op)
throws and exception if multiple keys are found.
It also deprecates getOperatorsByName(name) and adds
getAllOperatorsByName(name) getOperatorByName(name).
ConfigurableParser.getToken(String) method to search
for matching OperatorTokens and SymbolTokens.
ShuntingYard modified to allow both the ternary operator
syntax x>y ? x : y and the new dictionary syntax
{'x' : 3}.
StandardComponents, LightWeightComponentSet and MediumWeightComponentSet to allow
preferred components to be specified. To achieve this a protected method
ComponentSet.findOrElse(JepComponent[], Class<T>, Supplier<T>)
looks for an instance of a class in the components, if not found the supplier is used.
com.singularsys.jep.walkers.LightWeightImportationVisitor
needed to MacroFunctions work
with Overloaded functions.
MacroFunctions modified to work with the LightWeightImportationVisitor
OneShotComponent base class for components that should only be initilised once.
The FunctionSet and StringFunctionSet classes now extend this class,
prevents conflicts with manually adding functions.
eval(NodeFactory nf, String name, PostfixMathCommandI pfmc, Node... children)
added to the Evaluator interface to allow a NodeFactory to be used to create nodes.
Most visitors have been reworked to implement the com.singularsys.jep.GenericVisitor
interface, which provides better type safety
and more specific method signatures.
GenericVisitor<R,D,E> that offers better
type safety with the return type, context data type and exception type
all specified by type parameters.
GenericDoNothingVisitor<D>
and
GenericDeepCopyVisitor<D>
for visitors that return a new Node tree.
TestingVisitor that uses a predicate
to test every node in a tree.
LightWeightImportationVisitor
using the LightWeightInstance of pfmc if needed.
ImportationVisitor.deepCopy(Node)
method is now deprecated, the more descriptive method
importEqn(Node n) should be used instead.
Variable.copyPropertiesFrom(Variable)
that copies properties like its constant status, valid value
status, and hooks from an existing variable.
VariableTable.copyVariablesFrom(VariableTable vt)
and VariableTable.copyConstantsFrom(VariableTable vt)
modified to use this method and use the addVariable()
and addConstant() methods, ensuring the correct type of variable
is always created.
Variable.toString() using getter methods rather
than accessing fields directly, so that subclasses can modify the behaviour.
DecoratingVariableTable
allowing a VariableTable to be decorated with additional behaviour. This serves as the base class
for the CaseInsensitiveVariableTable and PublishingVariableTable
allowing both to be used together.
CaseInsensitiveVariableTable now extends DecoratingVariableTable.
CaseInsensitiveVariableTable now overloads addConstant() and addVariable() and remove().
setarrayoffset command to set whether zero or one-based array indexing is used.clearvariables command which removes all variables and constants
$1 and $$ for values from previous results.
functions command
setMonitor and a summary of numbers
of calls printed using showCalls
and the call tree using showTree.
Console class:
getHistory(),
printFunctionEntry(name,pfmc),
setIndexShift(offset),
clearVars(),
setMonitor(),
setEvaluator(ev),
showCalls(),
showTree(),
finaliseCommand(name, node, res).
\\
at the end of a line.
BigDecimalConsole supports fixed point arithmetic.
Node.getChildren() returns an array of the children of a node.
Implemented in SimpleNode.
Operator.toFullString() reports the Not-in-parser flag.
to make it easier to modify an existing parser.
com.singularsys.jep.misc.StrictDoubleNumberFactory
class that is a stricter version when all methods return Double.
PrintVisitor.visit(Node) method than can be called from PrintRulesI classes.
PrintVisitor has additional methods getSpecialRule(Operator),
getSpecialFunRule(String) and getSpecialVarName
to interrogate existing setup.
NullPrintVisitor has do-nothing implementations of some methods to
prevent exceptions if called.
JepMessages now allows additional resource bundles to be added
MonitoringEvaluator that counts the number of
times each function, operator and variable and constant
is used during evaluation.
DO_NOT_PRINT_TESTS environment variable to true.
@Tag("slow_tests") and @Tag("known-failure")
added to JUnit tests, allowing slow tests and known failures to be excluded.
A modularized version of Jep for use with Java 11 is available in the modules directory.
The code is written to be compatible with both long term support versions Java SE 8 and Java SE 11.
Most functions can work fine in multiple threads, there are some which need special treatment.
These functions can be indicated by implementing JepComponent which
provides a getLightWeightInstance() to return a thread-safe copy of the function.
When using the FunctionTable and OperatorTable
in multiple threads their getLightWeightInstance() methods will just return
this which is more memory efficient in the default case. This is the behaviour in Jep 3.4 and earlier.
Starting in version 4.0, both FunctionTable and OperatorTableI
have shallowCopy() methods. This will create new instance of the table and copies all functions
operators into the new table. If the function implements JepComponent then its getLightWeightInstance()
is called to return a thread-safe version.
There is also a MediumWeightComponentSet class which can be used to create a Jep
instance which insures thread-safe versions of functions. To use
Jep jep = new Jep(); Jep copy = new Jep(new MediumWeightComponentSet(jep));and the copy instance can be safely used in new thread.
To implement this functionality FunctionTable, and EmptyOperatorTable have
protected threadSafeMapCopy()
methods which returns a copy of the internal map respecting JepComponents.
They also have protected FunctionTable(Map<,>), EmptyOperatorTable(Map<,>)
constructors. This allows subclasses
it easily implements this behaviour
class MyFunctionTable extends FunctionTable {
...
protected MyFunctionTable(Map<String, PostfixMathCommandI> tbl) {
super(tbl);
}
public FunctionTable shallowCopy() {
Map<String,PostfixMathCommandI> newMap = this.threadSafeMapCopy();
FunctionTable ft = new MyFunctionTable(newMap);
return ft;
}
All subclasses also implement these constructors.
The Jep 3.5 release had a broken implementation of getLightWeightInstance() which would always return an empty table.
A new UncheckedEvaluator evaluator which does no checking of intermediate values during evaluation. Produces a 10-20% speed increase.
Slight change in the logic of the FastEvaluator. Test for
functions which implement CallbackEvaluationI happens after
tests for UnaryFunction etc.
The UnaryFunction, BinaryFunction and NaryBinaryFunction
have static factory methods which allow creation using lambda functions.
For example
// Function using explicit class
UnaryFunction recip = UnaryFunction.instanceOf(
x -> 1.0 / ((Number) x).doubleValue());
// Function where arguments are of an explicit type
UnaryFunction neg = UnaryFunction.instanceOf(Integer.class, x -> -x );
// Function using a method reference
UnaryFunction cubrt = UnaryFunction.instanceOf(Double.class,Math::cbrt);
// Binary function
BinaryFunction diff = BinaryFunction.instanceOf(Number.class,
(x,y) -> x.doubleValue() - y.doubleValue());
// NaryBinaryFunction
NaryBinaryFunction sum = NaryBinaryFunction.instanceOf(
(x,y) -> ((Number) x).doubleValue() + ((Number) y).doubleValue());
ImmutableComplex class who's values cannot be changed, and the results
of all operations yield immutable results.
Complex.ZERO, Complex.ONE, Complex.I
are now immutable, but for compatibility results of operations using these constants
can be changed. These constants use the Complex.NonPropagatingImmutableComplex
inner class.
power(Complex w) methods checks to see if the argument is an integer, if so
the power(int n) method is used. This in turn calls either fastPower(int n), or powerI(int n).
The first of these is faster but may be less accurate for large powers. A new powerD(double d)
is also introduced which uses the general double algorithm [r:th] -> [r^d:d th].
SpeedTestComplex diagnostic class.
standard.Complex.ToStringImaginaryWithI removed and properties
standard.Complex.ToStringNoBracketsRealWithI={0}
standard.Complex.ToStringNoBracketsNegRealWithI=-{0}
standard.Complex.ToStringNoBracketsImaginaryWithI={1} i
standard.Complex.ToStringNoBracketsImaginaryWithNegI={1} i
standard.Complex.ToStringBracketsRealWithI={0}
standard.Complex.ToStringBracketsNegRealWithI=-{0}
standard.Complex.ToStringBracketsImaginaryWithI={1} i
standard.Complex.ToStringBracketsImaginaryWithNegI={1} i
added.
MacroFunction which could give incorrect results on recursive functions.
Complex.reciprocal() gave incorrect results when im!=0.
PostfixTreeWalker the visit() methods are now called with the
correct number of children in cases when supressExaminingChildren(Node) returns true.
Parsing
BracketedSequenceGrammarMatcher FunctionSequenceGrammarMatcher
which parses lists and sequences, but the sequences separator , is treated
as a normal operator, and sequences passed using the ShuntingYard.
StandardConfigurableParser
so a multi-character symbol would be recognized before a single character matching operator.
NumberTokenMatcher so that 1..2 is not misinterpreted.
Functions and operators
Operator class has a new duplicate() method creating
a new operator with an identical set of fields.
EmptyOperatorTable now has methods
addOperator(new_op,existing_op)
insertOperator(new_op,existing_op)
appendOperator(new_op,existing_op) which don't require an explicit key to
be specified.
TernaryConditional function now use lazy evaluation.
TernaryOperator implements PrintRulesI.
NullWrappedPassThroughFunction for functions which should not be wrapped in the NullWrappedFunctionTable.
MacroFunction now has a working getLightWeightInstance() method.
It has a new constructor allowing a node tree to be specified. This allows use in threads which do not have parsers.
Fields now made protected to allow subclasses. Now catches stack errors on evaluation.
Power.power(int) to be strictly positive,
as it was too fragile.
Printing
PrintVisitor allows operators to implement PrintRulesI.
PrintVisitor now has public visibility for the testLeft(), testMid()
and testRight() functions allowing them to be used in a PrintRule.
allows operators to implement PrintRulesI.
java.text.DecimalFormatSymbols to set the strings used.
Variables
VariableFactory.copyVariable(Variable var) now copies all information
about the source variable, including constant flag, valid value flag,
and hooks.VariableTable.copyVariablesFrom(VariableTable vt)
and VariableTable.copyConstantsFrom(VariableTable vt)
copies all information about the source variable, including constant flag, valid value flag,
and hooks. If there already is a variable with the same name all properties are
copied and pre-existing hooks deleted.
Light weight components, hooks and serialization
ImportationVisitor now ensures it gets its operators and functions
from the specific Jep instance.
LightWeightComponentSet makes lightweight instances
of the additional components.
Node.HookKey is now Serializable and information on hooks is includes in
SerializableExpression. Some care is needed to ensure implementations of HookKey are properly
deserialized, and the use of SerializableExpression between versions.
DeepCopyVisitor copies information about hooks on each node.
HookRemover walker which removes hooks from nodes.
Collection<HookKey> hookKeys()
methods of Node and Variable when no keys set.
Other changes
JepRuntimeException for use in cases where a normal JepException cannot be thrown.
JepMessages class has new String format(String key,Object ... args) methods
to make it easier to use a message to formats its arguments.
Examples and tests
Fractal example application reworked to use multi-thread approach.