+ * The composed function h created by {@code h = g.of(f)} is such + * that {@code h.value(x) == g.value(f.value(x))} for all x. + *

+ * @param f function to compose with + * @return a new function which computes {@code this.value(f.value(x))} + * @see #postCompose(UnivariateRealFunction) + */ + public ComposableFunction of(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(f.value(x)); + } + }; + } - /** The power to which the value should be raised. */ - private final double pow; + /** Postcompose the instance with another function. + *

+ * The composed function h created by {@code h = g.postCompose(f)} is such + * that {@code h.value(x) == f.value(g.value(x))} for all x. + *

+ * @param f function to compose with + * @return a new function which computes {@code f.value(this.value(x))} + * @see #of(UnivariateRealFunction) + */ + public ComposableFunction postCompose(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return f.value(ComposableFunction.this.value(x)); + } + }; + } - /** Simple constructor. - * @param pow the power to which the value should be raised - */ - public Pow(double pow) { - this.pow = pow; - } + /** + * Return a function combining the instance and another function. + *

+ * The function h created by {@code h = g.combine(f, combiner)} is such that + * {@code h.value(x) == combiner.value(g.value(x), f.value(x))} for all x. + *

+ * @param f function to combine with the instance + * @param combiner bivariate function used for combining + * @return a new function which computes {@code combine.value(this.value(x), f.value(x))} + */ + public ComposableFunction combine(final UnivariateRealFunction f, + final BivariateRealFunction combiner) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return combiner.value(ComposableFunction.this.value(x), f.value(x)); + } + }; + } - /** {@inheritDoc} */ - public double value(double d) { - return Math.pow(d, pow); - } + /** + * Return a function adding the instance and another function. + * @param f function to combine with the instance + * @return a new function which computes {@code this.value(x) + f.value(x)} + */ + public ComposableFunction add(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) + f.value(x); + } + }; + } + + /** + * Return a function adding a constant term to the instance. + * @param a term to add + * @return a new function which computes {@code this.value(x) + a} + */ + public ComposableFunction add(final double a) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) + a; + } + }; + } + + /** + * Return a function subtracting another function from the instance. + * @param f function to combine with the instance + * @return a new function which computes {@code this.value(x) - f.value(x)} + */ + public ComposableFunction subtract(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) - f.value(x); + } + }; + } + + /** + * Return a function multiplying the instance and another function. + * @param f function to combine with the instance + * @return a new function which computes {@code this.value(x) * f.value(x)} + */ + public ComposableFunction multiply(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) * f.value(x); + } + }; + } + /** + * Return a function scaling the instance by a constant factor. + * @param scaleFactor constant scaling factor + * @return a new function which computes {@code this.value(x) * scaleFactor} + */ + public ComposableFunction multiply(final double scaleFactor) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) * scaleFactor; + } + }; } + /** + * Return a function dividing the instance by another function. + * @param f function to combine with the instance + * @return a new function which computes {@code this.value(x) / f.value(x)} + */ + public ComposableFunction divide(final UnivariateRealFunction f) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return ComposableFunction.this.value(x) / f.value(x); + } + }; + } + + /** + * Generates a function that iteratively apply instance function on all + * elements of an array. + *

+ * The generated function behaves as follows: + *

+ *
• initialize result = initialValue
• + *
• iterate: {@code result = combiner.value(result, + * this.value(nextMultivariateEntry));}
• + *
• return result
• + *
+ *

+ * @param combiner combiner to use between entries + * @param initialValue initial value to use before first entry + * @return a new function that iteratively applie instance function on all + * elements of an array. + */ + public MultivariateRealFunction asCollector(final BivariateRealFunction combiner, + final double initialValue) { + return new MultivariateRealFunction() { + /** {@inheritDoc} */ + public double value(double[] point) + throws FunctionEvaluationException, IllegalArgumentException { + double result = initialValue; + for (final double entry : point) { + result = combiner.value(result, ComposableFunction.this.value(entry)); + } + return result; + } + }; + } + + /** + * Generates a function that iteratively apply instance function on all + * elements of an array. + *

+ * Calling this method is equivalent to call {@link + * #asCollector(BivariateRealFunction, double) asCollector(BivariateRealFunction, 0.0)}. + *

+ * @param combiner combiner to use between entries + * @return a new function that iteratively applie instance function on all + * elements of an array. + * @see #asCollector(BivariateRealFunction, double) + */ + public MultivariateRealFunction asCollector(final BivariateRealFunction combiner) { + return asCollector(combiner, 0.0); + } + + /** + * Generates a function that iteratively apply instance function on all + * elements of an array. + *

+ * Calling this method is equivalent to call {@link + * #asCollector(BivariateRealFunction, double) asCollector(BinaryFunction.ADD, initialValue)}. + *

+ * @param initialValue initial value to use before first entry + * @return a new function that iteratively applie instance function on all + * elements of an array. + * @see #asCollector(BivariateRealFunction, double) + * @see BinaryFunction#ADD + */ + public MultivariateRealFunction asCollector(final double initialValue) { + return asCollector(BinaryFunction.ADD, initialValue); + } + + /** + * Generates a function that iteratively apply instance function on all + * elements of an array. + *

+ * Calling this method is equivalent to call {@link + * #asCollector(BivariateRealFunction, double) asCollector(BinaryFunction.ADD, 0.0)}. + *