diff --git a/src/main/java/org/apache/commons/math/analysis/BinaryFunction.java b/src/main/java/org/apache/commons/math/analysis/BinaryFunction.java new file mode 100644 index 000000000..f8efafc69 --- /dev/null +++ b/src/main/java/org/apache/commons/math/analysis/BinaryFunction.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math.analysis; + +import org.apache.commons.math.FunctionEvaluationException; + + + +/** + * Base class for {@link BivariateRealFunction} that can be composed with other functions. + * + * @version $Revision$ $Date$ + */ +public abstract class BinaryFunction implements BivariateRealFunction { + + /** The + operator method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction ADD = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return x + y; + } + }; + + /** The - operator method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction SUBTRACT = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return x - y; + } + }; + + /** The * operator method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction MULTIPLY = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return x * y; + } + }; + + /** The / operator method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction DIVIDE = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return x / y; + } + }; + + /** The {@code Math.pow} method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction POW = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return Math.pow(x, y); + } + }; + + /** The {@code Math.atan2} method wrapped as a {@link BinaryFunction}. */ + public static final BinaryFunction ATAN2 = new BinaryFunction() { + /** {@inheritDoc} */ + public double value(double x, double y) { + return Math.atan2(x, y); + } + }; + + /** {@inheritDoc} */ + public abstract double value(double x, double y) throws FunctionEvaluationException; + + /** Get a composable function by fixing the first argument of the instance. + * @param fixedX fixed value of the first argument + * @return a function such that {@code f.value(y) == value(fixedX, y)} + */ + public ComposableFunction fix1stArgument(final double fixedX) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return BinaryFunction.this.value(fixedX, x); + } + }; + } + + /** Get a composable function by fixing the second argument of the instance. + * @param fixedY fixed value of the second argument + * @return a function such that {@code f.value(x) == value(x, fixedY)} + */ + public ComposableFunction fix2ndArgument(final double fixedY) { + return new ComposableFunction() { + @Override + /** {@inheritDoc} */ + public double value(double x) throws FunctionEvaluationException { + return BinaryFunction.this.value(x, fixedY); + } + }; + } + +} diff --git a/src/main/java/org/apache/commons/math/analysis/BivariateRealFunction.java b/src/main/java/org/apache/commons/math/analysis/BivariateRealFunction.java new file mode 100644 index 000000000..f2bdeb2e2 --- /dev/null +++ b/src/main/java/org/apache/commons/math/analysis/BivariateRealFunction.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math.analysis; + +import org.apache.commons.math.FunctionEvaluationException; + + + +/** + * An interface representing a bivariate real function. + * + * @version $Revision$ $Date$ + */ +public interface BivariateRealFunction { + + /** + * Compute the value for the function. + * @param x abscissa for which the function value should be computed + * @param y ordinate for which the function value should be computed + * @return the value + * @throws FunctionEvaluationException if the function evaluation fails + */ + double value(double x, double y) throws FunctionEvaluationException; + +} diff --git a/src/main/java/org/apache/commons/math/analysis/ComposableFunction.java b/src/main/java/org/apache/commons/math/analysis/ComposableFunction.java new file mode 100644 index 000000000..44489bc9f --- /dev/null +++ b/src/main/java/org/apache/commons/math/analysis/ComposableFunction.java @@ -0,0 +1,462 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.math.analysis; + +import org.apache.commons.math.FunctionEvaluationException; + + +/** + * Base class for {@link UnivariateRealFunction} that can be composed with other functions. + * + * @version $Revision$ $Date$ + */ +public abstract class ComposableFunction implements UnivariateRealFunction { + + /** The constant function always returning 0. */ + public static final ComposableFunction ZERO = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return 0; + } + }; + + /** The constant function always returning 1. */ + public static final ComposableFunction ONE = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return 1; + } + }; + + /** The identity function. */ + public static final ComposableFunction IDENTITY = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return d; + } + }; + + /** The {@code Math.abs} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction ABS = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.abs(d); + } + }; + + /** The - operator wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction NEGATE = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return -d; + } + }; + + /** The {@code Math.sin} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction SIN = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.sin(d); + } + }; + + /** The {@code Math.sqrt} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction SQRT = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.sqrt(d); + } + }; + + /** The {@code Math.sinh} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction SINH = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.sinh(d); + } + }; + + /** The {@code Math.exp} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction EXP = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.exp(d); + } + }; + + /** The {@code Math.expm1} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction EXPM1 = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.expm1(d); + } + }; + + /** The {@code Math.asin} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction ASIN = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.asin(d); + } + }; + + /** The {@code Math.atan} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction ATAN = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.atan(d); + } + }; + + /** The {@code Math.tan} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction TAN = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.tan(d); + } + }; + + /** The {@code Math.tanh} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction TANH = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.tanh(d); + } + }; + + /** The {@code Math.cbrt} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction CBRT = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.cbrt(d); + } + }; + + /** The {@code Math.ceil} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction CEIL = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.ceil(d); + } + }; + + /** The {@code Math.floor} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction FLOOR = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.floor(d); + } + }; + + /** The {@code Math.log} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction LOG = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.log(d); + } + }; + + /** The {@code Math.log10} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction LOG10 = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.log10(d); + } + }; + + /** The {@code Math.cos} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction COS = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.cos(d); + } + }; + + /** The {@code Math.abs} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction ACOS = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.acos(d); + } + }; + + /** The {@code Math.cosh} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction COSH = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.cosh(d); + } + }; + + /** The {@code Math.rint} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction RINT = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.rint(d); + } + }; + + /** The {@code Math.signum} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction SIGNUM = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.signum(d); + } + }; + + /** The {@code Math.ulp} method wrapped as a {@link ComposableFunction}. */ + public static final ComposableFunction ULP = new ComposableFunction() { + /** {@inheritDoc} */ + public double value(double d) { + return Math.ulp(d); + } + }; + + /** Precompose the instance with another function. + *

+ * 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)); + } + }; + } + + /** 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)); + } + }; + } + + /** + * 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)); + } + }; + } + + /** + * 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: + *

+ *

+ * @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)}. + *

+ * @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() { + return asCollector(BinaryFunction.ADD, 0.0); + } + + /** {@inheritDoc} */ + public abstract double value(double x) throws FunctionEvaluationException; + +} diff --git a/src/main/java/org/apache/commons/math/analysis/UnivariateRealFunctions.java b/src/main/java/org/apache/commons/math/analysis/UnivariateRealFunctions.java deleted file mode 100644 index 82731ae47..000000000 --- a/src/main/java/org/apache/commons/math/analysis/UnivariateRealFunctions.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.math.analysis; - - -/** - * Set of {@link UnivariateRealFunction} classes wrapping methods from - * the standard Math class. - * - * @version $Revision$ $Date$ - */ -public class UnivariateRealFunctions { - - /** The {@code Math.abs} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction ABS = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.abs(d); - } - }; - - /** The - operator wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction NEGATE = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return -d; - } - }; - - /** The {@code Math.sin} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction SIN = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.sin(d); - } - }; - - /** The {@code Math.sqrt} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction SQRT = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.sqrt(d); - } - }; - - /** The {@code Math.sinh} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction SINH = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.sinh(d); - } - }; - - /** The {@code Math.exp} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction EXP = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.exp(d); - } - }; - - /** The {@code Math.expm1} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction EXP1M = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.expm1(d); - } - }; - - /** The {@code Math.asin} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction ASIN = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.asin(d); - } - }; - - /** The {@code Math.atan} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction ATAN = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.atan(d); - } - }; - - /** The {@code Math.tan} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction TAN = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.tan(d); - } - }; - - /** The {@code Math.tanh} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction TANH = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.tanh(d); - } - }; - - /** The {@code Math.cbrt} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction CBRT = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.cbrt(d); - } - }; - - /** The {@code Math.ceil} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction CEIL = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.ceil(d); - } - }; - - /** The {@code Math.floor} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction FLOOR = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.floor(d); - } - }; - - /** The {@code Math.log} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction LOG = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.log(d); - } - }; - - /** The {@code Math.log10} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction LOG10 = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.log10(d); - } - }; - - /** The {@code Math.cos} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction COS = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.cos(d); - } - }; - - /** The {@code Math.abs} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction ACOS = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.acos(d); - } - }; - - /** The {@code Math.cosh} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction COSH = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.cosh(d); - } - }; - - /** The {@code Math.rint} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction RINT = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.rint(d); - } - }; - - /** The {@code Math.signum} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction SIGNUM = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.signum(d); - } - }; - - /** The {@code Math.ulp} method wrapped as a {@link UnivariateRealFunction}. */ - public static final UnivariateRealFunction ULP = new UnivariateRealFunction() { - /** {@inheritDoc} */ - public double value(double d) { - return Math.ulp(d); - } - }; - - /** The {@code Math.pow} method wrapped as a {@link UnivariateRealFunction}. */ - public static class Pow implements UnivariateRealFunction { - - /** The power to which the value should be raised. */ - private final double pow; - - /** Simple constructor. - * @param pow the power to which the value should be raised - */ - public Pow(double pow) { - this.pow = pow; - } - - /** {@inheritDoc} */ - public double value(double d) { - return Math.pow(d, pow); - } - - } - -} diff --git a/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java b/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java index 7f6940682..c191d79f6 100644 --- a/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java +++ b/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java @@ -22,7 +22,7 @@ import java.util.Iterator; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.MathRuntimeException; import org.apache.commons.math.analysis.UnivariateRealFunction; -import org.apache.commons.math.analysis.UnivariateRealFunctions; +import org.apache.commons.math.analysis.ComposableFunction; /** * This class provides default basic implementations for many methods in the @@ -273,7 +273,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapAbsToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ABS); + return mapToSelf(ComposableFunction.ABS); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -287,7 +287,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapAcosToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ACOS); + return mapToSelf(ComposableFunction.ACOS); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -301,7 +301,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapAsinToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ASIN); + return mapToSelf(ComposableFunction.ASIN); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -315,7 +315,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapAtanToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ATAN); + return mapToSelf(ComposableFunction.ATAN); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -329,7 +329,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapCbrtToSelf() { try { - return mapToSelf(UnivariateRealFunctions.CBRT); + return mapToSelf(ComposableFunction.CBRT); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -343,7 +343,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapCeilToSelf() { try { - return mapToSelf(UnivariateRealFunctions.CEIL); + return mapToSelf(ComposableFunction.CEIL); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -357,7 +357,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapCosToSelf() { try { - return mapToSelf(UnivariateRealFunctions.COS); + return mapToSelf(ComposableFunction.COS); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -371,7 +371,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapCoshToSelf() { try { - return mapToSelf(UnivariateRealFunctions.COSH); + return mapToSelf(ComposableFunction.COSH); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -390,7 +390,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapExpToSelf() { try { - return mapToSelf(UnivariateRealFunctions.EXP); + return mapToSelf(ComposableFunction.EXP); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -404,7 +404,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapExpm1ToSelf() { try { - return mapToSelf(UnivariateRealFunctions.EXP1M); + return mapToSelf(ComposableFunction.EXPM1); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -418,7 +418,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapFloorToSelf() { try { - return mapToSelf(UnivariateRealFunctions.FLOOR); + return mapToSelf(ComposableFunction.FLOOR); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -437,7 +437,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapLogToSelf() { try { - return mapToSelf(UnivariateRealFunctions.LOG); + return mapToSelf(ComposableFunction.LOG); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -451,7 +451,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapLog10ToSelf() { try { - return mapToSelf(UnivariateRealFunctions.LOG10); + return mapToSelf(ComposableFunction.LOG10); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -465,7 +465,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapLog1pToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ASIN); + return mapToSelf(ComposableFunction.ASIN); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -489,7 +489,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapRintToSelf() { try { - return mapToSelf(UnivariateRealFunctions.RINT); + return mapToSelf(ComposableFunction.RINT); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -503,7 +503,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapSignumToSelf() { try { - return mapToSelf(UnivariateRealFunctions.SIGNUM); + return mapToSelf(ComposableFunction.SIGNUM); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -517,7 +517,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapSinToSelf() { try { - return mapToSelf(UnivariateRealFunctions.SIN); + return mapToSelf(ComposableFunction.SIN); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -531,7 +531,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapSinhToSelf() { try { - return mapToSelf(UnivariateRealFunctions.SINH); + return mapToSelf(ComposableFunction.SINH); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -545,7 +545,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapSqrtToSelf() { try { - return mapToSelf(UnivariateRealFunctions.SQRT); + return mapToSelf(ComposableFunction.SQRT); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -564,7 +564,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapTanToSelf() { try { - return mapToSelf(UnivariateRealFunctions.TAN); + return mapToSelf(ComposableFunction.TAN); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -578,7 +578,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapTanhToSelf() { try { - return mapToSelf(UnivariateRealFunctions.TANH); + return mapToSelf(ComposableFunction.TANH); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } @@ -592,7 +592,7 @@ public abstract class AbstractRealVector implements RealVector { /** {@inheritDoc} */ public RealVector mapUlpToSelf() { try { - return mapToSelf(UnivariateRealFunctions.ULP); + return mapToSelf(ComposableFunction.ULP); } catch (FunctionEvaluationException e) { throw new IllegalArgumentException(e); } diff --git a/src/site/xdoc/changes.xml b/src/site/xdoc/changes.xml index f64cb18e2..70c612e31 100644 --- a/src/site/xdoc/changes.xml +++ b/src/site/xdoc/changes.xml @@ -39,6 +39,9 @@ The type attribute can be add,update,fix,remove. + + Added composition features for real functions. + Added mapping and iteration methods to vectors. Provided a default implementation for the numerous simple methods in the RealVectorInterface. diff --git a/src/test/java/org/apache/commons/math/analysis/BinaryFunctionTest.java b/src/test/java/org/apache/commons/math/analysis/BinaryFunctionTest.java new file mode 100644 index 000000000..08cbbf6f7 --- /dev/null +++ b/src/test/java/org/apache/commons/math/analysis/BinaryFunctionTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.FunctionEvaluationException; +import org.junit.Assert; +import org.junit.Test; + +public class BinaryFunctionTest { + + @Test + public void testAdd() throws FunctionEvaluationException { + Assert.assertEquals(5.0, BinaryFunction.ADD.value(2, 3), 1.0e-15); + Assert.assertEquals(0.0, BinaryFunction.ADD.value(-1, 1), 1.0e-15); + } + + @Test + public void testSubtract() throws FunctionEvaluationException { + Assert.assertEquals(-1.0, BinaryFunction.SUBTRACT.value(2, 3), 1.0e-15); + Assert.assertEquals(-2.0, BinaryFunction.SUBTRACT.value(-1, 1), 1.0e-15); + } + + @Test + public void testMultiply() throws FunctionEvaluationException { + Assert.assertEquals(6.0, BinaryFunction.MULTIPLY.value(2, 3), 1.0e-15); + Assert.assertEquals(-1.0, BinaryFunction.MULTIPLY.value(-1, 1), 1.0e-15); + } + + @Test + public void testDivide() throws FunctionEvaluationException { + Assert.assertEquals(1.5, BinaryFunction.DIVIDE.value(3, 2), 1.0e-15); + Assert.assertEquals(-1.0, BinaryFunction.DIVIDE.value(-1, 1), 1.0e-15); + } + + @Test + public void testPow() throws FunctionEvaluationException { + Assert.assertEquals(9.0, BinaryFunction.POW.value(3, 2), 1.0e-15); + Assert.assertEquals(-1.0, BinaryFunction.POW.value(-1, 1), 1.0e-15); + } + + @Test + public void testAtan2() throws FunctionEvaluationException { + Assert.assertEquals(Math.PI / 4, BinaryFunction.ATAN2.value(1, 1), 1.0e-15); + Assert.assertEquals(-Math.PI / 4, BinaryFunction.ATAN2.value(-1, 1), 1.0e-15); + } + + @Test + public void testFix1st() throws FunctionEvaluationException { + ComposableFunction f = BinaryFunction.POW.fix1stArgument(2); + for (double x = 0.0; x < 1.0; x += 0.01) { + Assert.assertEquals(Math.pow(2.0, x), f.value(x), 1.0e-15); + } + } + + @Test + public void testFix2nd() throws FunctionEvaluationException { + ComposableFunction f = BinaryFunction.POW.fix2ndArgument(2); + for (double y = 0.0; y < 1.0; y += 0.01) { + Assert.assertEquals(y * y, f.value(y), 1.0e-15); + } + } + +} diff --git a/src/test/java/org/apache/commons/math/analysis/ComposableFunctionTest.java b/src/test/java/org/apache/commons/math/analysis/ComposableFunctionTest.java new file mode 100644 index 000000000..61a670b0e --- /dev/null +++ b/src/test/java/org/apache/commons/math/analysis/ComposableFunctionTest.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.math.analysis; + +import org.apache.commons.math.FunctionEvaluationException; +import org.junit.Assert; +import org.junit.Test; + +public class ComposableFunctionTest { + + @Test + public void testZero() throws FunctionEvaluationException { + Assert.assertEquals(0.0, ComposableFunction.ZERO.value(1), 1.0e-15); + Assert.assertEquals(0.0, ComposableFunction.ZERO.value(2), 1.0e-15); + } + + @Test + public void testOne() throws FunctionEvaluationException { + Assert.assertEquals(1.0, ComposableFunction.ONE.value(1), 1.0e-15); + Assert.assertEquals(1.0, ComposableFunction.ONE.value(2), 1.0e-15); + } + + @Test + public void testIdentity() throws FunctionEvaluationException { + Assert.assertEquals(1.0, ComposableFunction.IDENTITY.value(1), 1.0e-15); + Assert.assertEquals(2.0, ComposableFunction.IDENTITY.value(2), 1.0e-15); + } + + @Test + public void testRint() throws FunctionEvaluationException { + Assert.assertEquals(1.0, ComposableFunction.RINT.value(0.9), 1.0e-15); + Assert.assertEquals(2.0, ComposableFunction.RINT.value(2.2), 1.0e-15); + } + + @Test + public void testSignum() throws FunctionEvaluationException { + Assert.assertEquals(1.0, ComposableFunction.SIGNUM.value(12.3), 1.0e-15); + Assert.assertEquals(-1.0, ComposableFunction.SIGNUM.value(-6), 1.0e-15); + } + + @Test + public void testComposition() throws FunctionEvaluationException { + ComposableFunction abs = ComposableFunction.ABS; + ComposableFunction acos = ComposableFunction.ACOS; + ComposableFunction asin = ComposableFunction.ASIN; + ComposableFunction atan = ComposableFunction.ATAN; + ComposableFunction cbrt = ComposableFunction.CBRT; + ComposableFunction ceil = ComposableFunction.CEIL; + ComposableFunction cos = ComposableFunction.COS; + ComposableFunction cosh = ComposableFunction.COSH; + ComposableFunction exp = ComposableFunction.EXP; + ComposableFunction expm1 = ComposableFunction.EXPM1; + ComposableFunction floor = ComposableFunction.FLOOR; + ComposableFunction id = ComposableFunction.IDENTITY; + ComposableFunction log = ComposableFunction.LOG; + ComposableFunction log10 = ComposableFunction.LOG10; + ComposableFunction negate = ComposableFunction.NEGATE; + ComposableFunction sin = ComposableFunction.SIN; + ComposableFunction sinh = ComposableFunction.SINH; + ComposableFunction sqrt = ComposableFunction.SQRT; + ComposableFunction tan = ComposableFunction.TAN; + ComposableFunction tanh = ComposableFunction.TANH; + ComposableFunction ulp = ComposableFunction.ULP; + + ComposableFunction f1 = sqrt.of(abs.of(expm1.of(cbrt.of(tanh).of(id)))); + for (double x = 0.1; x < 0.9; x += 0.01) { + Assert.assertEquals(Math.sqrt(Math.abs(Math.expm1(Math.cbrt(Math.tanh(x))))), + f1.value(x), 1.0e-15); + } + + ComposableFunction f2 = cosh.of(sinh.of(tanh.of(ceil.postCompose(log.postCompose(cosh))))); + for (double x = 0.1; x < 12.9; x += 1.0) { + Assert.assertEquals(Math.cosh(Math.sinh(Math.tanh(Math.cosh(Math.log(Math.ceil(x)))))), + f2.value(x), 1.0e-15); + } + + ComposableFunction f3 = cos.of(sin.of(tan.of(acos.of(asin.of(log10.of(log.of(ulp))))))); + for (double x = 1.0e16; x < 1.0e17; x += 1.0e16) { + Assert.assertEquals(Math.cos(Math.sin(Math.tan(Math.acos(Math.asin(Math.log10(Math.log(Math.ulp(x)))))))), + f3.value(x), 1.0e-15); + } + + ComposableFunction f4 = atan.of(exp.of(negate.of(floor))); + for (double x = 1.1; x < 10.2; x += 1.0) { + Assert.assertEquals(Math.atan(Math.exp(-Math.floor(x))), + f4.value(x), 1.0e-15); + } + + } + + @Test + public void testCombine() throws FunctionEvaluationException { + + ComposableFunction f = + ComposableFunction.COS.combine(ComposableFunction.ASIN, BinaryFunction.POW); + for (double x = 0.1; x < 0.9; x += 0.01) { + Assert.assertEquals(Math.pow(Math.cos(x), Math.asin(x)), f.value(x), 1.0e-15); + } + + } + + @Test + public void testSimpleCombination() throws FunctionEvaluationException { + + ComposableFunction f1 = ComposableFunction.COS.add(3); + ComposableFunction f2 = ComposableFunction.COS.add(ComposableFunction.SIN); + ComposableFunction f3 = ComposableFunction.COS.subtract(ComposableFunction.SIN); + ComposableFunction f4 = ComposableFunction.COS.multiply(ComposableFunction.SIN); + ComposableFunction f5 = ComposableFunction.COS.multiply(5); + ComposableFunction f6 = ComposableFunction.COS.divide(ComposableFunction.SIN); + for (double x = 0.1; x < 0.9; x += 0.01) { + Assert.assertEquals(Math.cos(x) + 3, f1.value(x), 1.0e-15); + Assert.assertEquals(Math.cos(x) + Math.sin(x), f2.value(x), 1.0e-15); + Assert.assertEquals(Math.cos(x) - Math.sin(x), f3.value(x), 1.0e-15); + Assert.assertEquals(Math.cos(x) * Math.sin(x), f4.value(x), 1.0e-15); + Assert.assertEquals(Math.cos(x) * 5, f5.value(x), 1.0e-15); + Assert.assertEquals(Math.cos(x) / Math.sin(x), f6.value(x), 1.0e-15); + } + + } + + @Test + public void testCollector() throws FunctionEvaluationException { + + ComposableFunction f = BinaryFunction.POW.fix2ndArgument(2); + Assert.assertEquals(30, f.asCollector().value(new double[] { 1, 2, 3, 4 }), 1.0e-15); + Assert.assertEquals(33, f.asCollector(3).value(new double[] { 1, 2, 3, 4 }), 1.0e-15); + Assert.assertEquals(-30, f.asCollector(BinaryFunction.SUBTRACT).value(new double[] { 1, 2, 3, 4 }), 1.0e-15); + Assert.assertEquals(1152, f.asCollector(BinaryFunction.MULTIPLY, 2).value(new double[] { 1, 2, 3, 4 }), 1.0e-15); + } + +}