Class Functions
Math as function objects, as
well as a few more basic functions.
Function objects conveniently allow to express arbitrary functions in a generic manner. Essentially, a function object is an object that can perform a function on some arguments. It has a minimal interface: a method apply that takes the arguments, computes something and returns some result value. Function objects are comparable to function pointers in C used for call-backs.
Unary functions are of type DoubleFunction, binary functions
of type DoubleDoubleFunction. All can be retrieved via public
static final variables named after the function.
Unary predicates are of type DoubleProcedure, binary predicates
of type DoubleDoubleProcedure. All can be retrieved via public
static final variables named isXXX.
Binary functions and predicates also exist as unary functions with the second argument being fixed to a constant. These are generated and retrieved via factory methods (again with the same name as the function). Example:
- Functions.pow gives the function ab.
- Functions.pow.apply(2,3)==8.
- Functions.pow(3) gives the function a3.
- Functions.pow(3).apply(2)==8.
bindArg1(DoubleDoubleFunction,double)
and bindArg2(DoubleDoubleFunction,double). The order of arguments
can be swapped so that the first argument becomes the second and vice-versa. See
method swapArgs(DoubleDoubleFunction). Example:
- Functions.pow gives the function ab.
- Functions.bindArg2(Functions.pow,3) gives the function x3.
- Functions.bindArg1(Functions.pow,3) gives the function 3x.
- Functions.swapArgs(Functions.pow) gives the function ba.
Even more general, functions can be chained (composed, assembled). Assume we have two unary
functions g and h. The unary function g(h(a)) applying
both in sequence can be generated via chain(DoubleFunction,DoubleFunction):
- Functions.chain(g,h);
chain(DoubleFunction,DoubleDoubleFunction):
- Functions.chain(g,f);
chain(DoubleDoubleFunction,DoubleFunction,DoubleFunction):
- Functions.chain(f,g,h);
- chain(plus,sin,chain(square,cos));
new DoubleDoubleFunction() {
public final double apply(double a, double b) { return Math.sin(a) + Math.pow(Math.cos(b),2); }
}
For aliasing see functions.
Try this
// should yield 1.4399560356056456 in all cases
double a = 0.5;
double b = 0.2;
double v = Math.sin(a) + Math.pow(Math.cos(b),2);
System.out.println(v);
Functions F = Functions.functions;
DoubleDoubleFunction f = F.chain(F.plus,F.sin,F.chain(F.square,F.cos));
System.out.println(f.apply(a,b));
DoubleDoubleFunction g = new DoubleDoubleFunction() {
public double apply(double a, double b) { return Math.sin(a) + Math.pow(Math.cos(b),2); }
};
System.out.println(g.apply(a,b));
|
Performance
Surprise. Using modern non-adaptive JITs such as SunJDK 1.2.2 (java -classic) there seems to be no or only moderate performance penalty in using function objects in a loop over traditional code in a loop. For complex nested function objects (e.g. F.chain(F.abs,F.chain(F.plus,F.sin,F.chain(F.square,F.cos)))) the penalty is zero, for trivial functions (e.g. F.plus) the penalty is often acceptable.| Iteration Performance [million function
evaluations per second] Pentium Pro 200 Mhz, SunJDK 1.2.2, NT, java -classic, |
||||||
|
30000000 iterations |
3000000 iterations (10 times less) | |||||
| F.plus | a+b | F.chain(F.abs,F.chain(F.plus,F.sin,F.chain(F.square,F.cos))) | Math.abs(Math.sin(a) + Math.pow(Math.cos(b),2)) | |||
| 10.8 | 29.6 | 0.43 | 0.35 | |||
- Version:
- 1.0, 09/24/99
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final DoubleFunctionFunction that returns Math.abs(a).static final DoubleFunctionFunction that returns Math.acos(a).static final DoubleFunctionFunction that returns Math.asin(a).static final DoubleFunctionFunction that returns Math.atan(a).static final DoubleDoubleFunctionFunction that returns Math.atan2(a,b).static final DoubleFunctionFunction that returns Math.ceil(a).static final DoubleDoubleFunctionFunction that returns a invalid input: '<' b ? -1 : a > b ? 1 : 0.static final DoubleFunctionFunction that returns Math.cos(a).static final DoubleDoubleFunctionFunction that returns a / b.static final DoubleDoubleFunctionFunction that returns a == b ? 1 : 0.static final DoubleFunctionFunction that returns Math.exp(a).static final DoubleFunctionFunction that returns Math.floor(a).static final FunctionsLittle trick to allow for "aliasing", that is, renaming this class.static final DoubleDoubleFunctionFunction that returns a > b ? 1 : 0.static final DoubleFunctionFunction that returns its argument.static final DoubleDoubleFunctionFunction that returns Math.IEEEremainder(a,b).static final DoubleFunctionFunction that returns 1.0 / a.static final DoubleDoubleProcedureFunction that returns a == b.static final DoubleDoubleProcedureFunction that returns a > b.static final DoubleDoubleProcedureFunction that returns a invalid input: '<' b.static final DoubleDoubleFunctionFunction that returns a invalid input: '<' b ? 1 : 0.static final DoubleDoubleFunctionFunction that returns Math.log(a) / Math.log(b).static final DoubleFunctionFunction that returns Math.log(a).static final DoubleFunctionFunction that returns Math.log(a) / Math.log(2).static final DoubleDoubleFunctionFunction that returns Math.max(a,b).static final DoubleDoubleFunctionFunction that returns Math.min(a,b).static final DoubleDoubleFunctionFunction that returns a - b.static final DoubleDoubleFunctionFunction that returns a % b.static final DoubleDoubleFunctionFunction that returns a * b.static final DoubleFunctionFunction that returns -a.static final DoubleDoubleFunctionFunction that returns a + b.static final DoubleDoubleFunctionFunction that returns Math.abs(a) + Math.abs(b).static final DoubleDoubleFunctionFunction that returns Math.pow(a,b).static final DoubleFunctionFunction that returns Math.rint(a).static final DoubleFunctionFunction that returns a invalid input: '<' 0 ? -1 : a > 0 ? 1 : 0.static final DoubleFunctionFunction that returns Math.sin(a).static final DoubleFunctionFunction that returns Math.sqrt(a).static final DoubleFunctionFunction that returns a * a.static final DoubleFunctionFunction that returns Math.tan(a). -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedMakes this class non instantiable, but still let's others inherit from it. -
Method Summary
Modifier and TypeMethodDescriptionstatic DoubleFunctionbetween(double from, double to) Constructs a function that returns (frominvalid input: '<'=a invalid input: '&'invalid input: '&' ainvalid input: '<'=to) ? 1 : 0.static DoubleFunctionbindArg1(DoubleDoubleFunction function, double c) Constructs a unary function from a binary function with the first operand (argument) fixed to the given constant c.static DoubleFunctionbindArg2(DoubleDoubleFunction function, double c) Constructs a unary function from a binary function with the second operand (argument) fixed to the given constant c.static DoubleDoubleFunctionConstructs the function f( g(a), h(b) ).static DoubleDoubleFunctionConstructs the function g( h(a,b) ).static DoubleFunctionConstructs the function g( h(a) ).static DoubleFunctioncompare(double b) Constructs a function that returns a invalid input: '<' b ? -1 : a > b ? 1 : 0.static DoubleFunctionconstant(double c) Constructs a function that returns the constant c.static voiddemo1()Demonstrates usage of this class.static voiddemo2(int size) Benchmarks and demonstrates usage of trivial and complex functions.static DoubleFunctiondiv(double b) Constructs a function that returns a / b.static DoubleFunctionequals(double b) Constructs a function that returns a == b ? 1 : 0.static DoubleFunctiongreater(double b) Constructs a function that returns a > b ? 1 : 0.static DoubleFunctionIEEEremainder(double b) Constructs a function that returns Math.IEEEremainder(a,b).static DoubleProcedureisBetween(double from, double to) Constructs a function that returns frominvalid input: '<'=a invalid input: '&'invalid input: '&' ainvalid input: '<'=to.static DoubleProcedureisEqual(double b) Constructs a function that returns a == b.static DoubleProcedureisGreater(double b) Constructs a function that returns a > b.static DoubleProcedureisLess(double b) Constructs a function that returns a invalid input: '<' b.static DoubleFunctionless(double b) Constructs a function that returns a invalid input: '<' b ? 1 : 0.static DoubleFunctionlg(double b) Constructs a function that returns Math.log(a) / Math.log(b).protected static voidTests various methods of this class.static DoubleFunctionmax(double b) Constructs a function that returns Math.max(a,b).static DoubleFunctionmin(double b) Constructs a function that returns Math.min(a,b).static DoubleFunctionminus(double b) Constructs a function that returns a - b.static DoubleDoubleFunctionminusMult(double constant) Constructs a function that returns a - b*constant.static DoubleFunctionmod(double b) Constructs a function that returns a % b.static DoubleFunctionmult(double b) Constructs a function that returns a * b.static DoubleFunctionplus(double b) Constructs a function that returns a + b.static DoubleDoubleFunctionplusMult(double constant) Constructs a function that returns a + b*constant.static DoubleFunctionpow(double b) Constructs a function that returns Math.pow(a,b).static DoubleFunctionrandom()Constructs a function that returns a new uniform random number in the open unit interval(0.0,1.0)(excluding 0.0 and 1.0).static DoubleFunctionround(double precision) Constructs a function that returns the number rounded to the given precision; Math.rint(a/precision)*precision.static DoubleDoubleFunctionswapArgs(DoubleDoubleFunction function) Constructs a function that returns function.apply(b,a), i.e.
-
Field Details
-
functions
Little trick to allow for "aliasing", that is, renaming this class. Writing code likeFunctions.chain(Functions.plus,Functions.sin,Functions.chain(Functions.square,Functions.cos));
is a bit awkward, to say the least. Using the aliasing you can instead write
Functions F = Functions.functions;
F.chain(F.plus,F.sin,F.chain(F.square,F.cos)); -
abs
Function that returns Math.abs(a). -
acos
Function that returns Math.acos(a). -
asin
Function that returns Math.asin(a). -
atan
Function that returns Math.atan(a). -
ceil
Function that returns Math.ceil(a). -
cos
Function that returns Math.cos(a). -
exp
Function that returns Math.exp(a). -
floor
Function that returns Math.floor(a). -
identity
Function that returns its argument. -
inv
Function that returns 1.0 / a. -
log
Function that returns Math.log(a). -
log2
Function that returns Math.log(a) / Math.log(2). -
neg
Function that returns -a. -
rint
Function that returns Math.rint(a). -
sign
Function that returns a invalid input: '<' 0 ? -1 : a > 0 ? 1 : 0. -
sin
Function that returns Math.sin(a). -
sqrt
Function that returns Math.sqrt(a). -
square
Function that returns a * a. -
tan
Function that returns Math.tan(a). -
atan2
Function that returns Math.atan2(a,b). -
compare
Function that returns a invalid input: '<' b ? -1 : a > b ? 1 : 0. -
div
Function that returns a / b. -
equals
Function that returns a == b ? 1 : 0. -
greater
Function that returns a > b ? 1 : 0. -
IEEEremainder
Function that returns Math.IEEEremainder(a,b). -
isEqual
Function that returns a == b. -
isLess
Function that returns a invalid input: '<' b. -
isGreater
Function that returns a > b. -
less
Function that returns a invalid input: '<' b ? 1 : 0. -
lg
Function that returns Math.log(a) / Math.log(b). -
max
Function that returns Math.max(a,b). -
min
Function that returns Math.min(a,b). -
minus
Function that returns a - b. -
mod
Function that returns a % b. -
mult
Function that returns a * b. -
plus
Function that returns a + b. -
plusAbs
Function that returns Math.abs(a) + Math.abs(b). -
pow
Function that returns Math.pow(a,b).
-
-
Constructor Details
-
Functions
protected Functions()Makes this class non instantiable, but still let's others inherit from it.
-
-
Method Details
-
between
Constructs a function that returns (frominvalid input: '<'=a invalid input: '&'invalid input: '&' ainvalid input: '<'=to) ? 1 : 0. a is a variable, from and to are fixed. -
bindArg1
Constructs a unary function from a binary function with the first operand (argument) fixed to the given constant c. The second operand is variable (free).- Parameters:
function- a binary function taking operands in the form function.apply(c,var).- Returns:
- the unary function function(c,var).
-
bindArg2
Constructs a unary function from a binary function with the second operand (argument) fixed to the given constant c. The first operand is variable (free).- Parameters:
function- a binary function taking operands in the form function.apply(var,c).- Returns:
- the unary function function(var,c).
-
chain
public static DoubleDoubleFunction chain(DoubleDoubleFunction f, DoubleFunction g, DoubleFunction h) Constructs the function f( g(a), h(b) ).- Parameters:
f- a binary function.g- a unary function.h- a unary function.- Returns:
- the binary function f( g(a), h(b) ).
-
chain
Constructs the function g( h(a,b) ).- Parameters:
g- a unary function.h- a binary function.- Returns:
- the unary function g( h(a,b) ).
-
chain
Constructs the function g( h(a) ).- Parameters:
g- a unary function.h- a unary function.- Returns:
- the unary function g( h(a) ).
-
compare
Constructs a function that returns a invalid input: '<' b ? -1 : a > b ? 1 : 0. a is a variable, b is fixed. -
constant
Constructs a function that returns the constant c. -
demo1
public static void demo1()Demonstrates usage of this class. -
demo2
public static void demo2(int size) Benchmarks and demonstrates usage of trivial and complex functions. -
div
Constructs a function that returns a / b. a is a variable, b is fixed. -
equals
Constructs a function that returns a == b ? 1 : 0. a is a variable, b is fixed. -
greater
Constructs a function that returns a > b ? 1 : 0. a is a variable, b is fixed. -
IEEEremainder
Constructs a function that returns Math.IEEEremainder(a,b). a is a variable, b is fixed. -
isBetween
Constructs a function that returns frominvalid input: '<'=a invalid input: '&'invalid input: '&' ainvalid input: '<'=to. a is a variable, from and to are fixed. -
isEqual
Constructs a function that returns a == b. a is a variable, b is fixed. -
isGreater
Constructs a function that returns a > b. a is a variable, b is fixed. -
isLess
Constructs a function that returns a invalid input: '<' b. a is a variable, b is fixed. -
less
Constructs a function that returns a invalid input: '<' b ? 1 : 0. a is a variable, b is fixed. -
lg
Constructs a function that returns Math.log(a) / Math.log(b). a is a variable, b is fixed. -
main
Tests various methods of this class. -
max
Constructs a function that returns Math.max(a,b). a is a variable, b is fixed. -
min
Constructs a function that returns Math.min(a,b). a is a variable, b is fixed. -
minus
Constructs a function that returns a - b. a is a variable, b is fixed. -
minusMult
Constructs a function that returns a - b*constant. a and b are variables, constant is fixed. -
mod
Constructs a function that returns a % b. a is a variable, b is fixed. -
mult
Constructs a function that returns a * b. a is a variable, b is fixed. -
plus
Constructs a function that returns a + b. a is a variable, b is fixed. -
plusMult
Constructs a function that returns a + b*constant. a and b are variables, constant is fixed. -
pow
Constructs a function that returns Math.pow(a,b). a is a variable, b is fixed. -
random
Constructs a function that returns a new uniform random number in the open unit interval(0.0,1.0)(excluding 0.0 and 1.0). Currently the engine isMersenneTwisterand is seeded with the current time.Note that any random engine derived from
RandomEngineand any random distribution derived fromAbstractDistributionare function objects, because they implement the proper interfaces. Thus, if you are not happy with the default, just pass your favourite random generator to function evaluating methods. -
round
Constructs a function that returns the number rounded to the given precision; Math.rint(a/precision)*precision. Examples:precision = 0.01 rounds 0.012 --> 0.01, 0.018 --> 0.02 precision = 10 rounds 123 --> 120 , 127 --> 130
-
swapArgs
Constructs a function that returns function.apply(b,a), i.e. applies the function with the first operand as second operand and the second operand as first operand.- Parameters:
function- a function taking operands in the form function.apply(a,b).- Returns:
- the binary function function(b,a).
-