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.math3.analysis;
019    
020    import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
021    import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableFunction;
022    import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableVectorFunction;
023    import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
024    import org.apache.commons.math3.analysis.function.Identity;
025    import org.apache.commons.math3.exception.DimensionMismatchException;
026    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
027    import org.apache.commons.math3.exception.NumberIsTooLargeException;
028    import org.apache.commons.math3.exception.util.LocalizedFormats;
029    
030    /**
031     * Utilities for manipulating function objects.
032     *
033     * @version $Id: FunctionUtils.java 1401837 2012-10-24 19:39:45Z luc $
034     * @since 3.0
035     */
036    public class FunctionUtils {
037        /**
038         * Class only contains static methods.
039         */
040        private FunctionUtils() {}
041    
042        /**
043         * Composes functions.
044         * <br/>
045         * The functions in the argument list are composed sequentially, in the
046         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
047         *
048         * @param f List of functions.
049         * @return the composite function.
050         */
051        public static UnivariateFunction compose(final UnivariateFunction ... f) {
052            return new UnivariateFunction() {
053                /** {@inheritDoc} */
054                public double value(double x) {
055                    double r = x;
056                    for (int i = f.length - 1; i >= 0; i--) {
057                        r = f[i].value(r);
058                    }
059                    return r;
060                }
061            };
062        }
063    
064        /**
065         * Composes functions.
066         * <br/>
067         * The functions in the argument list are composed sequentially, in the
068         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
069         *
070         * @param f List of functions.
071         * @return the composite function.
072         * @since 3.1
073         */
074        public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
075            return new UnivariateDifferentiableFunction() {
076    
077                /** {@inheritDoc} */
078                public double value(final double t) {
079                    double r = t;
080                    for (int i = f.length - 1; i >= 0; i--) {
081                        r = f[i].value(r);
082                    }
083                    return r;
084                }
085    
086                /** {@inheritDoc} */
087                public DerivativeStructure value(final DerivativeStructure t) {
088                    DerivativeStructure r = t;
089                    for (int i = f.length - 1; i >= 0; i--) {
090                        r = f[i].value(r);
091                    }
092                    return r;
093                }
094    
095            };
096        }
097    
098        /**
099         * Composes functions.
100         * <br/>
101         * The functions in the argument list are composed sequentially, in the
102         * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
103         *
104         * @param f List of functions.
105         * @return the composite function.
106         * @deprecated as of 3.1 replaced by {@link #compose(UnivariateDifferentiableFunction...)}
107         */
108        public static DifferentiableUnivariateFunction compose(final DifferentiableUnivariateFunction ... f) {
109            return new DifferentiableUnivariateFunction() {
110                /** {@inheritDoc} */
111                public double value(double x) {
112                    double r = x;
113                    for (int i = f.length - 1; i >= 0; i--) {
114                        r = f[i].value(r);
115                    }
116                    return r;
117                }
118    
119                /** {@inheritDoc} */
120                public UnivariateFunction derivative() {
121                    return new UnivariateFunction() {
122                        /** {@inheritDoc} */
123                        public double value(double x) {
124                            double p = 1;
125                            double r = x;
126                            for (int i = f.length - 1; i >= 0; i--) {
127                                p *= f[i].derivative().value(r);
128                                r = f[i].value(r);
129                            }
130                            return p;
131                        }
132                    };
133                }
134            };
135        }
136    
137        /**
138         * Adds functions.
139         *
140         * @param f List of functions.
141         * @return a function that computes the sum of the functions.
142         */
143        public static UnivariateFunction add(final UnivariateFunction ... f) {
144            return new UnivariateFunction() {
145                /** {@inheritDoc} */
146                public double value(double x) {
147                    double r = f[0].value(x);
148                    for (int i = 1; i < f.length; i++) {
149                        r += f[i].value(x);
150                    }
151                    return r;
152                }
153            };
154        }
155    
156        /**
157         * Adds functions.
158         *
159         * @param f List of functions.
160         * @return a function that computes the sum of the functions.
161         * @since 3.1
162         */
163        public static UnivariateDifferentiableFunction add(final UnivariateDifferentiableFunction ... f) {
164            return new UnivariateDifferentiableFunction() {
165    
166                /** {@inheritDoc} */
167                public double value(final double t) {
168                    double r = f[0].value(t);
169                    for (int i = 1; i < f.length; i++) {
170                        r += f[i].value(t);
171                    }
172                    return r;
173                }
174    
175                /** {@inheritDoc} */
176                public DerivativeStructure value(final DerivativeStructure t) {
177                    DerivativeStructure r = f[0].value(t);
178                    for (int i = 1; i < f.length; i++) {
179                        r = r.add(f[i].value(t));
180                    }
181                    return r;
182                }
183    
184            };
185        }
186    
187        /**
188         * Adds functions.
189         *
190         * @param f List of functions.
191         * @return a function that computes the sum of the functions.
192         * @deprecated as of 3.1 replaced by {@link #add(UnivariateDifferentiableFunction...)}
193         */
194        @Deprecated
195        public static DifferentiableUnivariateFunction add(final DifferentiableUnivariateFunction ... f) {
196            return new DifferentiableUnivariateFunction() {
197                /** {@inheritDoc} */
198                public double value(double x) {
199                    double r = f[0].value(x);
200                    for (int i = 1; i < f.length; i++) {
201                        r += f[i].value(x);
202                    }
203                    return r;
204                }
205    
206                /** {@inheritDoc} */
207                public UnivariateFunction derivative() {
208                    return new UnivariateFunction() {
209                        /** {@inheritDoc} */
210                        public double value(double x) {
211                            double r = f[0].derivative().value(x);
212                            for (int i = 1; i < f.length; i++) {
213                                r += f[i].derivative().value(x);
214                            }
215                            return r;
216                        }
217                    };
218                }
219            };
220        }
221    
222        /**
223         * Multiplies functions.
224         *
225         * @param f List of functions.
226         * @return a function that computes the product of the functions.
227         */
228        public static UnivariateFunction multiply(final UnivariateFunction ... f) {
229            return new UnivariateFunction() {
230                /** {@inheritDoc} */
231                public double value(double x) {
232                    double r = f[0].value(x);
233                    for (int i = 1; i < f.length; i++) {
234                        r *= f[i].value(x);
235                    }
236                    return r;
237                }
238            };
239        }
240    
241        /**
242         * Multiplies functions.
243         *
244         * @param f List of functions.
245         * @return a function that computes the product of the functions.
246         * @since 3.1
247         */
248        public static UnivariateDifferentiableFunction multiply(final UnivariateDifferentiableFunction ... f) {
249            return new UnivariateDifferentiableFunction() {
250    
251                /** {@inheritDoc} */
252                public double value(final double t) {
253                    double r = f[0].value(t);
254                    for (int i = 1; i < f.length; i++) {
255                        r  *= f[i].value(t);
256                    }
257                    return r;
258                }
259    
260                /** {@inheritDoc} */
261                public DerivativeStructure value(final DerivativeStructure t) {
262                    DerivativeStructure r = f[0].value(t);
263                    for (int i = 1; i < f.length; i++) {
264                        r = r.multiply(f[i].value(t));
265                    }
266                    return r;
267                }
268    
269            };
270        }
271    
272        /**
273         * Multiplies functions.
274         *
275         * @param f List of functions.
276         * @return a function that computes the product of the functions.
277         * @deprecated as of 3.1 replaced by {@link #multiply(UnivariateDifferentiableFunction...)}
278         */
279        public static DifferentiableUnivariateFunction multiply(final DifferentiableUnivariateFunction ... f) {
280            return new DifferentiableUnivariateFunction() {
281                /** {@inheritDoc} */
282                public double value(double x) {
283                    double r = f[0].value(x);
284                    for (int i = 1; i < f.length; i++) {
285                        r *= f[i].value(x);
286                    }
287                    return r;
288                }
289    
290                /** {@inheritDoc} */
291                public UnivariateFunction derivative() {
292                    return new UnivariateFunction() {
293                        /** {@inheritDoc} */
294                        public double value(double x) {
295                            double sum = 0;
296                            for (int i = 0; i < f.length; i++) {
297                                double prod = f[i].derivative().value(x);
298                                for (int j = 0; j < f.length; j++) {
299                                    if (i != j) {
300                                        prod *= f[j].value(x);
301                                    }
302                                }
303                                sum += prod;
304                            }
305                            return sum;
306                        }
307                    };
308                }
309            };
310        }
311    
312        /**
313         * Returns the univariate function <br/>
314         * {@code h(x) = combiner(f(x), g(x))}.
315         *
316         * @param combiner Combiner function.
317         * @param f Function.
318         * @param g Function.
319         * @return the composite function.
320         */
321        public static UnivariateFunction combine(final BivariateFunction combiner,
322                                                 final UnivariateFunction f,
323                                                 final UnivariateFunction g) {
324            return new UnivariateFunction() {
325                /** {@inheritDoc} */
326                public double value(double x) {
327                    return combiner.value(f.value(x), g.value(x));
328                }
329            };
330        }
331    
332        /**
333         * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
334         * h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
335         * </code></pre>
336         *
337         * @param combiner Combiner function.
338         * @param f Function.
339         * @param initialValue Initial value.
340         * @return a collector function.
341         */
342        public static MultivariateFunction collector(final BivariateFunction combiner,
343                                                     final UnivariateFunction f,
344                                                     final double initialValue) {
345            return new MultivariateFunction() {
346                /** {@inheritDoc} */
347                public double value(double[] point) {
348                    double result = combiner.value(initialValue, f.value(point[0]));
349                    for (int i = 1; i < point.length; i++) {
350                        result = combiner.value(result, f.value(point[i]));
351                    }
352                    return result;
353                }
354            };
355        }
356    
357        /**
358         * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
359         * h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
360         * </code></pre>
361         *
362         * @param combiner Combiner function.
363         * @param initialValue Initial value.
364         * @return a collector function.
365         */
366        public static MultivariateFunction collector(final BivariateFunction combiner,
367                                                     final double initialValue) {
368            return collector(combiner, new Identity(), initialValue);
369        }
370    
371        /**
372         * Creates a unary function by fixing the first argument of a binary function.
373         *
374         * @param f Binary function.
375         * @param fixed Value to which the first argument of {@code f} is set.
376         * @return the unary function h(x) = f(fixed, x)
377         */
378        public static UnivariateFunction fix1stArgument(final BivariateFunction f,
379                                                        final double fixed) {
380            return new UnivariateFunction() {
381                /** {@inheritDoc} */
382                public double value(double x) {
383                    return f.value(fixed, x);
384                }
385            };
386        }
387        /**
388         * Creates a unary function by fixing the second argument of a binary function.
389         *
390         * @param f Binary function.
391         * @param fixed Value to which the second argument of {@code f} is set.
392         * @return the unary function h(x) = f(x, fixed)
393         */
394        public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
395                                                        final double fixed) {
396            return new UnivariateFunction() {
397                /** {@inheritDoc} */
398                public double value(double x) {
399                    return f.value(x, fixed);
400                }
401            };
402        }
403    
404        /**
405         * Samples the specified univariate real function on the specified interval.
406         * <br/>
407         * The interval is divided equally into {@code n} sections and sample points
408         * are taken from {@code min} to {@code max - (max - min) / n}; therefore
409         * {@code f} is not sampled at the upper bound {@code max}.
410         *
411         * @param f Function to be sampled
412         * @param min Lower bound of the interval (included).
413         * @param max Upper bound of the interval (excluded).
414         * @param n Number of sample points.
415         * @return the array of samples.
416         * @throws NumberIsTooLargeException if the lower bound {@code min} is
417         * greater than, or equal to the upper bound {@code max}.
418         * @throws NotStrictlyPositiveException if the number of sample points
419         * {@code n} is negative.
420         */
421        public static double[] sample(UnivariateFunction f,
422                                      double min, double max, int n) {
423    
424            if (n <= 0) {
425                throw new NotStrictlyPositiveException(
426                        LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
427                        Integer.valueOf(n));
428            }
429            if (min >= max) {
430                throw new NumberIsTooLargeException(min, max, false);
431            }
432    
433            final double[] s = new double[n];
434            final double h = (max - min) / n;
435            for (int i = 0; i < n; i++) {
436                s[i] = f.value(min + i * h);
437            }
438            return s;
439        }
440    
441        /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
442         * @param f function to convert
443         * @return converted function
444         * @deprecated this conversion method is temporary in version 3.1, as the {@link
445         * DifferentiableUnivariateFunction} interface itself is deprecated
446         */
447        @Deprecated
448        public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
449            return new DifferentiableUnivariateFunction() {
450    
451                /** {@inheritDoc} */
452                public double value(final double x) {
453                    return f.value(x);
454                }
455    
456                /** {@inheritDoc} */
457                public UnivariateFunction derivative() {
458                    return new UnivariateFunction() {
459                        /** {@inheritDoc} */
460                        public double value(final double x) {
461                            return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
462                        }
463                    };
464                }
465    
466            };
467        }
468    
469        /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
470         * <p>
471         * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
472         * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown.
473         * </p>
474         * @param f function to convert
475         * @return converted function
476         * @deprecated this conversion method is temporary in version 3.1, as the {@link
477         * DifferentiableUnivariateFunction} interface itself is deprecated
478         */
479        @Deprecated
480        public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
481            return new UnivariateDifferentiableFunction() {
482    
483                /** {@inheritDoc} */
484                public double value(final double x) {
485                    return f.value(x);
486                }
487    
488                /** {@inheritDoc}
489                 * @exception NumberIsTooLargeException if derivation order is greater than 1
490                 */
491                public DerivativeStructure value(final DerivativeStructure t)
492                    throws NumberIsTooLargeException {
493                    switch (t.getOrder()) {
494                        case 0 :
495                            return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
496                        case 1 : {
497                            final int parameters = t.getFreeParameters();
498                            final double[] derivatives = new double[parameters + 1];
499                            derivatives[0] = f.value(t.getValue());
500                            final double fPrime = f.derivative().value(t.getValue());
501                            int[] orders = new int[parameters];
502                            for (int i = 0; i < parameters; ++i) {
503                                orders[i] = 1;
504                                derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
505                                orders[i] = 0;
506                            }
507                            return new DerivativeStructure(parameters, 1, derivatives);
508                        }
509                        default :
510                            throw new NumberIsTooLargeException(t.getOrder(), 1, true);
511                    }
512                }
513    
514            };
515        }
516    
517        /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
518         * @param f function to convert
519         * @return converted function
520         * @deprecated this conversion method is temporary in version 3.1, as the {@link
521         * DifferentiableMultivariateFunction} interface itself is deprecated
522         */
523        @Deprecated
524        public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
525            return new DifferentiableMultivariateFunction() {
526    
527                /** {@inheritDoc} */
528                public double value(final double[] x) {
529                    return f.value(x);
530                }
531    
532                /** {@inheritDoc} */
533                public MultivariateFunction partialDerivative(final int k) {
534                    return new MultivariateFunction() {
535                        /** {@inheritDoc} */
536                        public double value(final double[] x) {
537    
538                            final int n = x.length;
539    
540                            // delegate computation to underlying function
541                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
542                            for (int i = 0; i < n; ++i) {
543                                if (i == k) {
544                                    dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
545                                } else {
546                                    dsX[i] = new DerivativeStructure(1, 1, x[i]);
547                                }
548                            }
549                            final DerivativeStructure y = f.value(dsX);
550    
551                            // extract partial derivative
552                            return y.getPartialDerivative(1);
553    
554                        }
555                    };
556                }
557    
558                public MultivariateVectorFunction gradient() {
559                    return new MultivariateVectorFunction() {
560                        /** {@inheritDoc} */
561                        public double[] value(final double[] x) {
562    
563                            final int n = x.length;
564    
565                            // delegate computation to underlying function
566                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
567                            for (int i = 0; i < n; ++i) {
568                                dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
569                            }
570                            final DerivativeStructure y = f.value(dsX);
571    
572                            // extract gradient
573                            final double[] gradient = new double[n];
574                            final int[] orders = new int[n];
575                            for (int i = 0; i < n; ++i) {
576                                orders[i]   = 1;
577                                gradient[i] = y.getPartialDerivative(orders);
578                                orders[i]   = 0;
579                            }
580    
581                            return gradient;
582    
583                        }
584                    };
585                }
586    
587            };
588        }
589    
590        /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
591         * <p>
592         * Note that the converted function is able to handle {@link DerivativeStructure} elements
593         * that all have the same number of free parameters and order, and with order at most 1.
594         * If the function is called with inconsistent numbers of free parameters or higher order, a
595         * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
596         * </p>
597         * @param f function to convert
598         * @return converted function
599         * @deprecated this conversion method is temporary in version 3.1, as the {@link
600         * DifferentiableMultivariateFunction} interface itself is deprecated
601         */
602        @Deprecated
603        public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
604            return new MultivariateDifferentiableFunction() {
605    
606                /** {@inheritDoc} */
607                public double value(final double[] x) {
608                    return f.value(x);
609                }
610    
611                /** {@inheritDoc}
612                 * @exception DimensionMismatchException if number of parameters or derivation
613                 * order are higher than 1
614                 */
615                public DerivativeStructure value(final DerivativeStructure[] t)
616                    throws DimensionMismatchException, NumberIsTooLargeException {
617    
618                    // check parameters and orders limits
619                    final int parameters = t[0].getFreeParameters();
620                    final int order      = t[0].getOrder();
621                    final int n          = t.length;
622                    if (order > 1) {
623                        throw new NumberIsTooLargeException(order, 1, true);
624                    }
625    
626                    // check all elements in the array are consistent
627                    for (int i = 0; i < n; ++i) {
628                        if (t[i].getFreeParameters() != parameters) {
629                            throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
630                        }
631    
632                        if (t[i].getOrder() != order) {
633                            throw new DimensionMismatchException(t[i].getOrder(), order);
634                        }
635                    }
636    
637                    // delegate computation to underlying function
638                    final double[] point = new double[n];
639                    for (int i = 0; i < n; ++i) {
640                        point[i] = t[i].getValue();
641                    }
642                    final double value      = f.value(point);
643                    final double[] gradient = f.gradient().value(point);
644    
645                    // merge value and gradient into one DerivativeStructure
646                    final double[] derivatives = new double[parameters + 1];
647                    derivatives[0] = value;
648                    final int[] orders = new int[parameters];
649                    for (int i = 0; i < parameters; ++i) {
650                        orders[i] = 1;
651                        for (int j = 0; j < n; ++j) {
652                            derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
653                        }
654                        orders[i] = 0;
655                    }
656    
657                    return new DerivativeStructure(parameters, order, derivatives);
658    
659                }
660    
661            };
662        }
663    
664        /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
665         * @param f function to convert
666         * @return converted function
667         * @deprecated this conversion method is temporary in version 3.1, as the {@link
668         * DifferentiableMultivariateVectorFunction} interface itself is deprecated
669         */
670        @Deprecated
671        public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
672            return new DifferentiableMultivariateVectorFunction() {
673    
674                /** {@inheritDoc} */
675                public double[] value(final double[] x) {
676                    return f.value(x);
677                }
678    
679                public MultivariateMatrixFunction jacobian() {
680                    return new MultivariateMatrixFunction() {
681                        /** {@inheritDoc} */
682                        public double[][] value(final double[] x) {
683    
684                            final int n = x.length;
685    
686                            // delegate computation to underlying function
687                            final DerivativeStructure[] dsX = new DerivativeStructure[n];
688                            for (int i = 0; i < n; ++i) {
689                                dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
690                            }
691                            final DerivativeStructure[] y = f.value(dsX);
692    
693                            // extract Jacobian
694                            final double[][] jacobian = new double[y.length][n];
695                            final int[] orders = new int[n];
696                            for (int i = 0; i < y.length; ++i) {
697                                for (int j = 0; j < n; ++j) {
698                                    orders[j]      = 1;
699                                    jacobian[i][j] = y[i].getPartialDerivative(orders);
700                                    orders[j]      = 0;
701                                }
702                            }
703    
704                            return jacobian;
705    
706                        }
707                    };
708                }
709    
710            };
711        }
712    
713        /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
714         * <p>
715         * Note that the converted function is able to handle {@link DerivativeStructure} elements
716         * that all have the same number of free parameters and order, and with order at most 1.
717         * If the function is called with inconsistent numbers of free parameters or higher order, a
718         * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
719         * </p>
720         * @param f function to convert
721         * @return converted function
722         * @deprecated this conversion method is temporary in version 3.1, as the {@link
723         * DifferentiableMultivariateFunction} interface itself is deprecated
724         */
725        @Deprecated
726        public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
727            return new MultivariateDifferentiableVectorFunction() {
728    
729                /** {@inheritDoc} */
730                public double[] value(final double[] x) {
731                    return f.value(x);
732                }
733    
734                /** {@inheritDoc}
735                 * @exception DimensionMismatchException if number of parameters or derivation
736                 * order are higher than 1
737                 */
738                public DerivativeStructure[] value(final DerivativeStructure[] t)
739                    throws DimensionMismatchException, NumberIsTooLargeException {
740    
741                    // check parameters and orders limits
742                    final int parameters = t[0].getFreeParameters();
743                    final int order      = t[0].getOrder();
744                    final int n          = t.length;
745                    if (order > 1) {
746                        throw new NumberIsTooLargeException(order, 1, true);
747                    }
748    
749                    // check all elements in the array are consistent
750                    for (int i = 0; i < n; ++i) {
751                        if (t[i].getFreeParameters() != parameters) {
752                            throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
753                        }
754    
755                        if (t[i].getOrder() != order) {
756                            throw new DimensionMismatchException(t[i].getOrder(), order);
757                        }
758                    }
759    
760                    // delegate computation to underlying function
761                    final double[] point = new double[n];
762                    for (int i = 0; i < n; ++i) {
763                        point[i] = t[i].getValue();
764                    }
765                    final double[] value      = f.value(point);
766                    final double[][] jacobian = f.jacobian().value(point);
767    
768                    // merge value and Jacobian into a DerivativeStructure array
769                    final DerivativeStructure[] merged = new DerivativeStructure[value.length];
770                    for (int k = 0; k < merged.length; ++k) {
771                        final double[] derivatives = new double[parameters + 1];
772                        derivatives[0] = value[k];
773                        final int[] orders = new int[parameters];
774                        for (int i = 0; i < parameters; ++i) {
775                            orders[i] = 1;
776                            for (int j = 0; j < n; ++j) {
777                                derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
778                            }
779                            orders[i] = 0;
780                        }
781                        merged[k] = new DerivativeStructure(parameters, order, derivatives);
782                    }
783    
784                    return merged;
785    
786                }
787    
788            };
789        }
790    
791    }