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    }