    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.math.analysis;
    019
    020    import org.apache.commons.math.FunctionEvaluationException;
    021    import org.apache.commons.math.util.FastMath;
    022
    023
    024    /**
    025     * Base class for {@link UnivariateRealFunction} that can be composed with other functions.
    026     *
    027     * @since 2.1
    028     * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 f??vr. 2011) $
    029     */
    030    public abstract class ComposableFunction implements UnivariateRealFunction {
    031
    032        /** The constant function always returning 0. */
    033        public static final ComposableFunction ZERO = new ComposableFunction() {
    034            /** {@inheritDoc} */
    035            @Override
    036            public double value(double d) {
    037                return 0;
    038            }
    039        };
    040
    041        /** The constant function always returning 1. */
    042        public static final ComposableFunction ONE = new ComposableFunction() {
    043            /** {@inheritDoc} */
    044            @Override
    045            public double value(double d) {
    046                return 1;
    047            }
    048        };
    049
    050        /** The identity function. */
    051        public static final ComposableFunction IDENTITY = new ComposableFunction() {
    052            /** {@inheritDoc} */
    053            @Override
    054            public double value(double d) {
    055                return d;
    056            }
    057        };
    058
    059        /** The {@code FastMath.abs} method wrapped as a {@link ComposableFunction}. */
    060        public static final ComposableFunction ABS = new ComposableFunction() {
    061            /** {@inheritDoc} */
    062            @Override
    063            public double value(double d) {
    064                return FastMath.abs(d);
    065            }
    066        };
    067
    068        /** The - operator wrapped as a {@link ComposableFunction}. */
    069        public static final ComposableFunction NEGATE = new ComposableFunction() {
    070            /** {@inheritDoc} */
    071            @Override
    072            public double value(double d) {
    073                return -d;
    074            }
    075        };
    076
    077        /** The invert operator wrapped as a {@link ComposableFunction}. */
    078        public static final ComposableFunction INVERT = new ComposableFunction () {
    079            /** {@inheritDoc} */
    080            @Override
    081            public double value(double d){
    082                return 1/d;
    083            }
    084        };
    085
    086        /** The {@code FastMath.sin} method wrapped as a {@link ComposableFunction}. */
    087        public static final ComposableFunction SIN = new ComposableFunction() {
    088            /** {@inheritDoc} */
    089            @Override
    090            public double value(double d) {
    091                return FastMath.sin(d);
    092            }
    093        };
    094
    095        /** The {@code FastMath.sqrt} method wrapped as a {@link ComposableFunction}. */
    096        public static final ComposableFunction SQRT = new ComposableFunction() {
    097            /** {@inheritDoc} */
    098            @Override
    099            public double value(double d) {
    100                return FastMath.sqrt(d);
    101            }
    102        };
    103
    104        /** The {@code FastMath.sinh} method wrapped as a {@link ComposableFunction}. */
    105        public static final ComposableFunction SINH = new ComposableFunction() {
    106            /** {@inheritDoc} */
    107            @Override
    108            public double value(double d) {
    109                return FastMath.sinh(d);
    110            }
    111        };
    112
    113        /** The {@code FastMath.exp} method wrapped as a {@link ComposableFunction}. */
    114        public static final ComposableFunction EXP = new ComposableFunction() {
    115            /** {@inheritDoc} */
    116            @Override
    117            public double value(double d) {
    118                return FastMath.exp(d);
    119            }
    120        };
    121
    122        /** The {@code FastMath.expm1} method wrapped as a {@link ComposableFunction}. */
    123        public static final ComposableFunction EXPM1 = new ComposableFunction() {
    124            /** {@inheritDoc} */
    125            @Override
    126            public double value(double d) {
    127                return FastMath.expm1(d);
    128            }
    129        };
    130
    131        /** The {@code FastMath.asin} method wrapped as a {@link ComposableFunction}. */
    132        public static final ComposableFunction ASIN = new ComposableFunction() {
    133            /** {@inheritDoc} */
    134            @Override
    135            public double value(double d) {
    136                return FastMath.asin(d);
    137            }
    138        };
    139
    140        /** The {@code FastMath.atan} method wrapped as a {@link ComposableFunction}. */
    141        public static final ComposableFunction ATAN = new ComposableFunction() {
    142            /** {@inheritDoc} */
    143            @Override
    144            public double value(double d) {
    145                return FastMath.atan(d);
    146            }
    147        };
    148
    149        /** The {@code FastMath.tan} method wrapped as a {@link ComposableFunction}. */
    150        public static final ComposableFunction TAN = new ComposableFunction() {
    151            /** {@inheritDoc} */
    152            @Override
    153            public double value(double d) {
    154                return FastMath.tan(d);
    155            }
    156        };
    157
    158        /** The {@code FastMath.tanh} method wrapped as a {@link ComposableFunction}. */
    159        public static final ComposableFunction TANH = new ComposableFunction() {
    160            /** {@inheritDoc} */
    161            @Override
    162            public double value(double d) {
    163                return FastMath.tanh(d);
    164            }
    165        };
    166
    167        /** The {@code FastMath.cbrt} method wrapped as a {@link ComposableFunction}. */
    168        public static final ComposableFunction CBRT = new ComposableFunction() {
    169            /** {@inheritDoc} */
    170            @Override
    171            public double value(double d) {
    172                return FastMath.cbrt(d);
    173            }
    174        };
    175
    176        /** The {@code FastMath.ceil} method wrapped as a {@link ComposableFunction}. */
    177        public static final ComposableFunction CEIL = new ComposableFunction() {
    178            /** {@inheritDoc} */
    179            @Override
    180            public double value(double d) {
    181                return FastMath.ceil(d);
    182            }
    183        };
    184
    185        /** The {@code FastMath.floor} method wrapped as a {@link ComposableFunction}. */
    186        public static final ComposableFunction FLOOR = new ComposableFunction() {
    187            /** {@inheritDoc} */
    188            @Override
    189            public double value(double d) {
    190                return FastMath.floor(d);
    191            }
    192        };
    193
    194        /** The {@code FastMath.log} method wrapped as a {@link ComposableFunction}. */
    195        public static final ComposableFunction LOG = new ComposableFunction() {
    196            /** {@inheritDoc} */
    197            @Override
    198            public double value(double d) {
    199                return FastMath.log(d);
    200            }
    201        };
    202
    203        /** The {@code FastMath.log10} method wrapped as a {@link ComposableFunction}. */
    204        public static final ComposableFunction LOG10 = new ComposableFunction() {
    205            /** {@inheritDoc} */
    206            @Override
    207            public double value(double d) {
    208                return FastMath.log10(d);
    209            }
    210        };
    211
    212        /** The {@code FastMath.log1p} method wrapped as a {@link ComposableFunction}. */
    213        public static final ComposableFunction LOG1P = new ComposableFunction () {
    214            @Override
    215            public double value(double d){
    216                return FastMath.log1p(d);
    217            }
    218        };
    219
    220        /** The {@code FastMath.cos} method wrapped as a {@link ComposableFunction}. */
    221        public static final ComposableFunction COS = new ComposableFunction() {
    222            /** {@inheritDoc} */
    223            @Override
    224            public double value(double d) {
    225                return FastMath.cos(d);
    226            }
    227        };
    228
    229        /** The {@code FastMath.abs} method wrapped as a {@link ComposableFunction}. */
    230        public static final ComposableFunction ACOS = new ComposableFunction() {
    231            /** {@inheritDoc} */
    232            @Override
    233            public double value(double d) {
    234                return FastMath.acos(d);
    235            }
    236        };
    237
    238        /** The {@code FastMath.cosh} method wrapped as a {@link ComposableFunction}. */
    239        public static final ComposableFunction COSH = new ComposableFunction() {
    240            /** {@inheritDoc} */
    241            @Override
    242            public double value(double d) {
    243                return FastMath.cosh(d);
    244            }
    245        };
    246
    247        /** The {@code FastMath.rint} method wrapped as a {@link ComposableFunction}. */
    248        public static final ComposableFunction RINT = new ComposableFunction() {
    249            /** {@inheritDoc} */
    250            @Override
    251            public double value(double d) {
    252                return FastMath.rint(d);
    253            }
    254        };
    255
    256        /** The {@code FastMath.signum} method wrapped as a {@link ComposableFunction}. */
    257        public static final ComposableFunction SIGNUM = new ComposableFunction() {
    258            /** {@inheritDoc} */
    259            @Override
    260            public double value(double d) {
    261                return FastMath.signum(d);
    262            }
    263        };
    264
    265        /** The {@code FastMath.ulp} method wrapped as a {@link ComposableFunction}. */
    266        public static final ComposableFunction ULP = new ComposableFunction() {
    267            /** {@inheritDoc} */
    268            @Override
    269            public double value(double d) {
    270                return FastMath.ulp(d);
    271            }
    272        };
    273
    274        /** Precompose the instance with another function.
    275         * <p>
    276         * The composed function h created by {@code h = g.of(f)} is such
    277         * that {@code h.value(x) == g.value(f.value(x))} for all x.
    278         * </p>
    279         * @param f function to compose with
    280         * @return a new function which computes {@code this.value(f.value(x))}
    281         * @see #postCompose(UnivariateRealFunction)
    282         */
    283        public ComposableFunction of(final UnivariateRealFunction f) {
    284            return new ComposableFunction() {
    285                @Override
    286                /** {@inheritDoc} */
    287                public double value(double x) throws FunctionEvaluationException {
    288                    return ComposableFunction.this.value(f.value(x));
    289                }
    290            };
    291        }
    292
    293        /** Postcompose the instance with another function.
    294         * <p>
    295         * The composed function h created by {@code h = g.postCompose(f)} is such
    296         * that {@code h.value(x) == f.value(g.value(x))} for all x.
    297         * </p>
    298         * @param f function to compose with
    299         * @return a new function which computes {@code f.value(this.value(x))}
    300         * @see #of(UnivariateRealFunction)
    301         */
    302        public ComposableFunction postCompose(final UnivariateRealFunction f) {
    303            return new ComposableFunction() {
    304                @Override
    305                /** {@inheritDoc} */
    306                public double value(double x) throws FunctionEvaluationException {
    307                    return f.value(ComposableFunction.this.value(x));
    308                }
    309            };
    310        }
    311
    312        /**
    313         * Return a function combining the instance and another function.
    314         * <p>
    315         * The function h created by {@code h = g.combine(f, combiner)} is such that
    316         * {@code h.value(x) == combiner.value(g.value(x), f.value(x))} for all x.
    317         * </p>
    318         * @param f function to combine with the instance
    319         * @param combiner bivariate function used for combining
    320         * @return a new function which computes {@code combine.value(this.value(x), f.value(x))}
    321         */
    322        public ComposableFunction combine(final UnivariateRealFunction f,
    323                                          final BivariateRealFunction combiner) {
    324            return new ComposableFunction() {
    325                @Override
    326                /** {@inheritDoc} */
    327                public double value(double x) throws FunctionEvaluationException {
    328                    return combiner.value(ComposableFunction.this.value(x), f.value(x));
    329                }
    330            };
    331        }
    332
    333        /**
    334         * Return a function adding the instance and another function.
    335         * @param f function to combine with the instance
    336         * @return a new function which computes {@code this.value(x) + f.value(x)}
    337         */
    338        public ComposableFunction add(final UnivariateRealFunction f) {
    339            return new ComposableFunction() {
    340                @Override
    341                /** {@inheritDoc} */
    342                public double value(double x) throws FunctionEvaluationException {
    343                    return ComposableFunction.this.value(x) + f.value(x);
    344                }
    345            };
    346        }
    347
    348        /**
    349         * Return a function adding a constant term to the instance.
    350         * @param a term to add
    351         * @return a new function which computes {@code this.value(x) + a}
    352         */
    353        public ComposableFunction add(final double a) {
    354            return new ComposableFunction() {
    355                @Override
    356                /** {@inheritDoc} */
    357                public double value(double x) throws FunctionEvaluationException {
    358                    return ComposableFunction.this.value(x) + a;
    359                }
    360            };
    361        }
    362
    363        /**
    364         * Return a function subtracting another function from the instance.
    365         * @param f function to combine with the instance
    366         * @return a new function which computes {@code this.value(x) - f.value(x)}
    367         */
    368        public ComposableFunction subtract(final UnivariateRealFunction f) {
    369            return new ComposableFunction() {
    370                @Override
    371                /** {@inheritDoc} */
    372                public double value(double x) throws FunctionEvaluationException {
    373                    return ComposableFunction.this.value(x) - f.value(x);
    374                }
    375            };
    376        }
    377
    378        /**
    379         * Return a function multiplying the instance and another function.
    380         * @param f function to combine with the instance
    381         * @return a new function which computes {@code this.value(x) * f.value(x)}
    382         */
    383        public ComposableFunction multiply(final UnivariateRealFunction f) {
    384            return new ComposableFunction() {
    385                @Override
    386                /** {@inheritDoc} */
    387                public double value(double x) throws FunctionEvaluationException {
    388                    return ComposableFunction.this.value(x) * f.value(x);
    389                }
    390            };
    391        }
    392
    393        /**
    394         * Return a function scaling the instance by a constant factor.
    395         * @param scaleFactor constant scaling factor
    396         * @return a new function which computes {@code this.value(x) * scaleFactor}
    397         */
    398        public ComposableFunction multiply(final double scaleFactor) {
    399            return new ComposableFunction() {
    400                @Override
    401                /** {@inheritDoc} */
    402                public double value(double x) throws FunctionEvaluationException {
    403                    return ComposableFunction.this.value(x) * scaleFactor;
    404                }
    405            };
    406        }
    407        /**
    408         * Return a function dividing the instance by another function.
    409         * @param f function to combine with the instance
    410         * @return a new function which computes {@code this.value(x) / f.value(x)}
    411         */
    412        public ComposableFunction divide(final UnivariateRealFunction f) {
    413            return new ComposableFunction() {
    414                @Override
    415                /** {@inheritDoc} */
    416                public double value(double x) throws FunctionEvaluationException {
    417                    return ComposableFunction.this.value(x) / f.value(x);
    418                }
    419            };
    420        }
    421
    422        /**
    423         * Generates a function that iteratively apply instance function on all
    424         * elements of an array.
    425         * <p>
    426         * The generated function behaves as follows:
    427         * <ul>
    428         *   <li>initialize result = initialValue</li>
    429         *   <li>iterate: {@code result = combiner.value(result,
    430         *   this.value(nextMultivariateEntry));}</li>
    431         *   <li>return result</li>
    432         * </ul>
    433         * </p>
    434         * @param combiner combiner to use between entries
    435         * @param initialValue initial value to use before first entry
    436         * @return a new function that iteratively apply instance function on all
    437         * elements of an array.
    438         */
    439        public MultivariateRealFunction asCollector(final BivariateRealFunction combiner,
    440                                                    final double initialValue) {
    441            return new MultivariateRealFunction() {
    442                /** {@inheritDoc} */
    443                public double value(double[] point)
    444                    throws FunctionEvaluationException, IllegalArgumentException {
    445                    double result = initialValue;
    446                    for (final double entry : point) {
    447                        result = combiner.value(result, ComposableFunction.this.value(entry));
    448                    }
    449                    return result;
    450                }
    451            };
    452        }
    453
    454        /**
    455         * Generates a function that iteratively apply instance function on all
    456         * elements of an array.
    457         * <p>
    458         * Calling this method is equivalent to call {@link
    459         * #asCollector(BivariateRealFunction, double) asCollector(BivariateRealFunction, 0.0)}.
    460         * </p>
    461         * @param combiner combiner to use between entries
    462         * @return a new function that iteratively apply instance function on all
    463         * elements of an array.
    464         * @see #asCollector(BivariateRealFunction, double)
    465         */
    466        public  MultivariateRealFunction asCollector(final BivariateRealFunction combiner) {
    467            return asCollector(combiner, 0.0);
    468        }
    469
    470        /**
    471         * Generates a function that iteratively apply instance function on all
    472         * elements of an array.
    473         * <p>
    474         * Calling this method is equivalent to call {@link
    475         * #asCollector(BivariateRealFunction, double) asCollector(BinaryFunction.ADD, initialValue)}.
    476         * </p>
    477         * @param initialValue initial value to use before first entry
    478         * @return a new function that iteratively apply instance function on all
    479         * elements of an array.
    480         * @see #asCollector(BivariateRealFunction, double)
    481         * @see BinaryFunction#ADD
    482         */
    483        public  MultivariateRealFunction asCollector(final double initialValue) {
    484            return asCollector(BinaryFunction.ADD, initialValue);
    485        }
    486
    487        /**
    488         * Generates a function that iteratively apply instance function on all
    489         * elements of an array.
    490         * <p>
    491         * Calling this method is equivalent to call {@link
    492         * #asCollector(BivariateRealFunction, double) asCollector(BinaryFunction.ADD, 0.0)}.
    493         * </p>
    494         * @return a new function that iteratively apply instance function on all
    495         * elements of an array.
    496         * @see #asCollector(BivariateRealFunction, double)
    497         * @see BinaryFunction#ADD
    498         */
    499        public  MultivariateRealFunction asCollector() {
    500            return asCollector(BinaryFunction.ADD, 0.0);
    501        }
    502
    503        /** {@inheritDoc} */
    504        public abstract double value(double x) throws FunctionEvaluationException;
    505
    506    }