View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math3.analysis;
19  
20  import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
21  import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableFunction;
22  import org.apache.commons.math3.analysis.differentiation.MultivariateDifferentiableVectorFunction;
23  import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
24  import org.apache.commons.math3.analysis.function.Identity;
25  import org.apache.commons.math3.exception.DimensionMismatchException;
26  import org.apache.commons.math3.exception.NotStrictlyPositiveException;
27  import org.apache.commons.math3.exception.NumberIsTooLargeException;
28  import org.apache.commons.math3.exception.util.LocalizedFormats;
29  
30  /**
31   * Utilities for manipulating function objects.
32   *
33   * @since 3.0
34   */
35  public class FunctionUtils {
36      /**
37       * Class only contains static methods.
38       */
39      private FunctionUtils() {}
40  
41      /**
42       * Composes functions.
43       * <br/>
44       * The functions in the argument list are composed sequentially, in the
45       * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
46       *
47       * @param f List of functions.
48       * @return the composite function.
49       */
50      public static UnivariateFunction compose(final UnivariateFunction ... f) {
51          return new UnivariateFunction() {
52              /** {@inheritDoc} */
53              public double value(double x) {
54                  double r = x;
55                  for (int i = f.length - 1; i >= 0; i--) {
56                      r = f[i].value(r);
57                  }
58                  return r;
59              }
60          };
61      }
62  
63      /**
64       * Composes functions.
65       * <br/>
66       * The functions in the argument list are composed sequentially, in the
67       * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
68       *
69       * @param f List of functions.
70       * @return the composite function.
71       * @since 3.1
72       */
73      public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
74          return new UnivariateDifferentiableFunction() {
75  
76              /** {@inheritDoc} */
77              public double value(final double t) {
78                  double r = t;
79                  for (int i = f.length - 1; i >= 0; i--) {
80                      r = f[i].value(r);
81                  }
82                  return r;
83              }
84  
85              /** {@inheritDoc} */
86              public DerivativeStructure value(final DerivativeStructure t) {
87                  DerivativeStructure r = t;
88                  for (int i = f.length - 1; i >= 0; i--) {
89                      r = f[i].value(r);
90                  }
91                  return r;
92              }
93  
94          };
95      }
96  
97      /**
98       * Composes functions.
99       * <br/>
100      * The functions in the argument list are composed sequentially, in the
101      * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
102      *
103      * @param f List of functions.
104      * @return the composite function.
105      * @deprecated as of 3.1 replaced by {@link #compose(UnivariateDifferentiableFunction...)}
106      */
107     @Deprecated
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              * @throws DimensionMismatchException if functions are not consistent with each other
177              */
178             public DerivativeStructure value(final DerivativeStructure t)
179                 throws DimensionMismatchException {
180                 DerivativeStructure r = f[0].value(t);
181                 for (int i = 1; i < f.length; i++) {
182                     r = r.add(f[i].value(t));
183                 }
184                 return r;
185             }
186 
187         };
188     }
189 
190     /**
191      * Adds functions.
192      *
193      * @param f List of functions.
194      * @return a function that computes the sum of the functions.
195      * @deprecated as of 3.1 replaced by {@link #add(UnivariateDifferentiableFunction...)}
196      */
197     @Deprecated
198     public static DifferentiableUnivariateFunction add(final DifferentiableUnivariateFunction ... f) {
199         return new DifferentiableUnivariateFunction() {
200             /** {@inheritDoc} */
201             public double value(double x) {
202                 double r = f[0].value(x);
203                 for (int i = 1; i < f.length; i++) {
204                     r += f[i].value(x);
205                 }
206                 return r;
207             }
208 
209             /** {@inheritDoc} */
210             public UnivariateFunction derivative() {
211                 return new UnivariateFunction() {
212                     /** {@inheritDoc} */
213                     public double value(double x) {
214                         double r = f[0].derivative().value(x);
215                         for (int i = 1; i < f.length; i++) {
216                             r += f[i].derivative().value(x);
217                         }
218                         return r;
219                     }
220                 };
221             }
222         };
223     }
224 
225     /**
226      * Multiplies functions.
227      *
228      * @param f List of functions.
229      * @return a function that computes the product of the functions.
230      */
231     public static UnivariateFunction multiply(final UnivariateFunction ... f) {
232         return new UnivariateFunction() {
233             /** {@inheritDoc} */
234             public double value(double x) {
235                 double r = f[0].value(x);
236                 for (int i = 1; i < f.length; i++) {
237                     r *= f[i].value(x);
238                 }
239                 return r;
240             }
241         };
242     }
243 
244     /**
245      * Multiplies functions.
246      *
247      * @param f List of functions.
248      * @return a function that computes the product of the functions.
249      * @since 3.1
250      */
251     public static UnivariateDifferentiableFunction multiply(final UnivariateDifferentiableFunction ... f) {
252         return new UnivariateDifferentiableFunction() {
253 
254             /** {@inheritDoc} */
255             public double value(final double t) {
256                 double r = f[0].value(t);
257                 for (int i = 1; i < f.length; i++) {
258                     r  *= f[i].value(t);
259                 }
260                 return r;
261             }
262 
263             /** {@inheritDoc} */
264             public DerivativeStructure value(final DerivativeStructure t) {
265                 DerivativeStructure r = f[0].value(t);
266                 for (int i = 1; i < f.length; i++) {
267                     r = r.multiply(f[i].value(t));
268                 }
269                 return r;
270             }
271 
272         };
273     }
274 
275     /**
276      * Multiplies functions.
277      *
278      * @param f List of functions.
279      * @return a function that computes the product of the functions.
280      * @deprecated as of 3.1 replaced by {@link #multiply(UnivariateDifferentiableFunction...)}
281      */
282     @Deprecated
283     public static DifferentiableUnivariateFunction multiply(final DifferentiableUnivariateFunction ... f) {
284         return new DifferentiableUnivariateFunction() {
285             /** {@inheritDoc} */
286             public double value(double x) {
287                 double r = f[0].value(x);
288                 for (int i = 1; i < f.length; i++) {
289                     r *= f[i].value(x);
290                 }
291                 return r;
292             }
293 
294             /** {@inheritDoc} */
295             public UnivariateFunction derivative() {
296                 return new UnivariateFunction() {
297                     /** {@inheritDoc} */
298                     public double value(double x) {
299                         double sum = 0;
300                         for (int i = 0; i < f.length; i++) {
301                             double prod = f[i].derivative().value(x);
302                             for (int j = 0; j < f.length; j++) {
303                                 if (i != j) {
304                                     prod *= f[j].value(x);
305                                 }
306                             }
307                             sum += prod;
308                         }
309                         return sum;
310                     }
311                 };
312             }
313         };
314     }
315 
316     /**
317      * Returns the univariate function <br/>
318      * {@code h(x) = combiner(f(x), g(x))}.
319      *
320      * @param combiner Combiner function.
321      * @param f Function.
322      * @param g Function.
323      * @return the composite function.
324      */
325     public static UnivariateFunction combine(final BivariateFunction combiner,
326                                              final UnivariateFunction f,
327                                              final UnivariateFunction g) {
328         return new UnivariateFunction() {
329             /** {@inheritDoc} */
330             public double value(double x) {
331                 return combiner.value(f.value(x), g.value(x));
332             }
333         };
334     }
335 
336     /**
337      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
338      * h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
339      * </code></pre>
340      *
341      * @param combiner Combiner function.
342      * @param f Function.
343      * @param initialValue Initial value.
344      * @return a collector function.
345      */
346     public static MultivariateFunction collector(final BivariateFunction combiner,
347                                                  final UnivariateFunction f,
348                                                  final double initialValue) {
349         return new MultivariateFunction() {
350             /** {@inheritDoc} */
351             public double value(double[] point) {
352                 double result = combiner.value(initialValue, f.value(point[0]));
353                 for (int i = 1; i < point.length; i++) {
354                     result = combiner.value(result, f.value(point[i]));
355                 }
356                 return result;
357             }
358         };
359     }
360 
361     /**
362      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
363      * h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
364      * </code></pre>
365      *
366      * @param combiner Combiner function.
367      * @param initialValue Initial value.
368      * @return a collector function.
369      */
370     public static MultivariateFunction collector(final BivariateFunction combiner,
371                                                  final double initialValue) {
372         return collector(combiner, new Identity(), initialValue);
373     }
374 
375     /**
376      * Creates a unary function by fixing the first argument of a binary function.
377      *
378      * @param f Binary function.
379      * @param fixed Value to which the first argument of {@code f} is set.
380      * @return the unary function h(x) = f(fixed, x)
381      */
382     public static UnivariateFunction fix1stArgument(final BivariateFunction f,
383                                                     final double fixed) {
384         return new UnivariateFunction() {
385             /** {@inheritDoc} */
386             public double value(double x) {
387                 return f.value(fixed, x);
388             }
389         };
390     }
391     /**
392      * Creates a unary function by fixing the second argument of a binary function.
393      *
394      * @param f Binary function.
395      * @param fixed Value to which the second argument of {@code f} is set.
396      * @return the unary function h(x) = f(x, fixed)
397      */
398     public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
399                                                     final double fixed) {
400         return new UnivariateFunction() {
401             /** {@inheritDoc} */
402             public double value(double x) {
403                 return f.value(x, fixed);
404             }
405         };
406     }
407 
408     /**
409      * Samples the specified univariate real function on the specified interval.
410      * <br/>
411      * The interval is divided equally into {@code n} sections and sample points
412      * are taken from {@code min} to {@code max - (max - min) / n}; therefore
413      * {@code f} is not sampled at the upper bound {@code max}.
414      *
415      * @param f Function to be sampled
416      * @param min Lower bound of the interval (included).
417      * @param max Upper bound of the interval (excluded).
418      * @param n Number of sample points.
419      * @return the array of samples.
420      * @throws NumberIsTooLargeException if the lower bound {@code min} is
421      * greater than, or equal to the upper bound {@code max}.
422      * @throws NotStrictlyPositiveException if the number of sample points
423      * {@code n} is negative.
424      */
425     public static double[] sample(UnivariateFunction f, double min, double max, int n)
426        throws NumberIsTooLargeException, NotStrictlyPositiveException {
427 
428         if (n <= 0) {
429             throw new NotStrictlyPositiveException(
430                     LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
431                     Integer.valueOf(n));
432         }
433         if (min >= max) {
434             throw new NumberIsTooLargeException(min, max, false);
435         }
436 
437         final double[] s = new double[n];
438         final double h = (max - min) / n;
439         for (int i = 0; i < n; i++) {
440             s[i] = f.value(min + i * h);
441         }
442         return s;
443     }
444 
445     /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
446      * @param f function to convert
447      * @return converted function
448      * @deprecated this conversion method is temporary in version 3.1, as the {@link
449      * DifferentiableUnivariateFunction} interface itself is deprecated
450      */
451     @Deprecated
452     public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
453         return new DifferentiableUnivariateFunction() {
454 
455             /** {@inheritDoc} */
456             public double value(final double x) {
457                 return f.value(x);
458             }
459 
460             /** {@inheritDoc} */
461             public UnivariateFunction derivative() {
462                 return new UnivariateFunction() {
463                     /** {@inheritDoc} */
464                     public double value(final double x) {
465                         return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
466                     }
467                 };
468             }
469 
470         };
471     }
472 
473     /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
474      * <p>
475      * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
476      * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown.
477      * </p>
478      * @param f function to convert
479      * @return converted function
480      * @deprecated this conversion method is temporary in version 3.1, as the {@link
481      * DifferentiableUnivariateFunction} interface itself is deprecated
482      */
483     @Deprecated
484     public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
485         return new UnivariateDifferentiableFunction() {
486 
487             /** {@inheritDoc} */
488             public double value(final double x) {
489                 return f.value(x);
490             }
491 
492             /** {@inheritDoc}
493              * @exception NumberIsTooLargeException if derivation order is greater than 1
494              */
495             public DerivativeStructure value(final DerivativeStructure t)
496                 throws NumberIsTooLargeException {
497                 switch (t.getOrder()) {
498                     case 0 :
499                         return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
500                     case 1 : {
501                         final int parameters = t.getFreeParameters();
502                         final double[] derivatives = new double[parameters + 1];
503                         derivatives[0] = f.value(t.getValue());
504                         final double fPrime = f.derivative().value(t.getValue());
505                         int[] orders = new int[parameters];
506                         for (int i = 0; i < parameters; ++i) {
507                             orders[i] = 1;
508                             derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
509                             orders[i] = 0;
510                         }
511                         return new DerivativeStructure(parameters, 1, derivatives);
512                     }
513                     default :
514                         throw new NumberIsTooLargeException(t.getOrder(), 1, true);
515                 }
516             }
517 
518         };
519     }
520 
521     /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
522      * @param f function to convert
523      * @return converted function
524      * @deprecated this conversion method is temporary in version 3.1, as the {@link
525      * DifferentiableMultivariateFunction} interface itself is deprecated
526      */
527     @Deprecated
528     public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
529         return new DifferentiableMultivariateFunction() {
530 
531             /** {@inheritDoc} */
532             public double value(final double[] x) {
533                 return f.value(x);
534             }
535 
536             /** {@inheritDoc} */
537             public MultivariateFunction partialDerivative(final int k) {
538                 return new MultivariateFunction() {
539                     /** {@inheritDoc} */
540                     public double value(final double[] x) {
541 
542                         final int n = x.length;
543 
544                         // delegate computation to underlying function
545                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
546                         for (int i = 0; i < n; ++i) {
547                             if (i == k) {
548                                 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
549                             } else {
550                                 dsX[i] = new DerivativeStructure(1, 1, x[i]);
551                             }
552                         }
553                         final DerivativeStructure y = f.value(dsX);
554 
555                         // extract partial derivative
556                         return y.getPartialDerivative(1);
557 
558                     }
559                 };
560             }
561 
562             public MultivariateVectorFunction gradient() {
563                 return new MultivariateVectorFunction() {
564                     /** {@inheritDoc} */
565                     public double[] value(final double[] x) {
566 
567                         final int n = x.length;
568 
569                         // delegate computation to underlying function
570                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
571                         for (int i = 0; i < n; ++i) {
572                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
573                         }
574                         final DerivativeStructure y = f.value(dsX);
575 
576                         // extract gradient
577                         final double[] gradient = new double[n];
578                         final int[] orders = new int[n];
579                         for (int i = 0; i < n; ++i) {
580                             orders[i]   = 1;
581                             gradient[i] = y.getPartialDerivative(orders);
582                             orders[i]   = 0;
583                         }
584 
585                         return gradient;
586 
587                     }
588                 };
589             }
590 
591         };
592     }
593 
594     /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
595      * <p>
596      * Note that the converted function is able to handle {@link DerivativeStructure} elements
597      * that all have the same number of free parameters and order, and with order at most 1.
598      * If the function is called with inconsistent numbers of free parameters or higher order, a
599      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
600      * </p>
601      * @param f function to convert
602      * @return converted function
603      * @deprecated this conversion method is temporary in version 3.1, as the {@link
604      * DifferentiableMultivariateFunction} interface itself is deprecated
605      */
606     @Deprecated
607     public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
608         return new MultivariateDifferentiableFunction() {
609 
610             /** {@inheritDoc} */
611             public double value(final double[] x) {
612                 return f.value(x);
613             }
614 
615             /** {@inheritDoc}
616              * @exception NumberIsTooLargeException if derivation order is higher than 1
617              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
618              */
619             public DerivativeStructure value(final DerivativeStructure[] t)
620                 throws DimensionMismatchException, NumberIsTooLargeException {
621 
622                 // check parameters and orders limits
623                 final int parameters = t[0].getFreeParameters();
624                 final int order      = t[0].getOrder();
625                 final int n          = t.length;
626                 if (order > 1) {
627                     throw new NumberIsTooLargeException(order, 1, true);
628                 }
629 
630                 // check all elements in the array are consistent
631                 for (int i = 0; i < n; ++i) {
632                     if (t[i].getFreeParameters() != parameters) {
633                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
634                     }
635 
636                     if (t[i].getOrder() != order) {
637                         throw new DimensionMismatchException(t[i].getOrder(), order);
638                     }
639                 }
640 
641                 // delegate computation to underlying function
642                 final double[] point = new double[n];
643                 for (int i = 0; i < n; ++i) {
644                     point[i] = t[i].getValue();
645                 }
646                 final double value      = f.value(point);
647                 final double[] gradient = f.gradient().value(point);
648 
649                 // merge value and gradient into one DerivativeStructure
650                 final double[] derivatives = new double[parameters + 1];
651                 derivatives[0] = value;
652                 final int[] orders = new int[parameters];
653                 for (int i = 0; i < parameters; ++i) {
654                     orders[i] = 1;
655                     for (int j = 0; j < n; ++j) {
656                         derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
657                     }
658                     orders[i] = 0;
659                 }
660 
661                 return new DerivativeStructure(parameters, order, derivatives);
662 
663             }
664 
665         };
666     }
667 
668     /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
669      * @param f function to convert
670      * @return converted function
671      * @deprecated this conversion method is temporary in version 3.1, as the {@link
672      * DifferentiableMultivariateVectorFunction} interface itself is deprecated
673      */
674     @Deprecated
675     public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
676         return new DifferentiableMultivariateVectorFunction() {
677 
678             /** {@inheritDoc} */
679             public double[] value(final double[] x) {
680                 return f.value(x);
681             }
682 
683             public MultivariateMatrixFunction jacobian() {
684                 return new MultivariateMatrixFunction() {
685                     /** {@inheritDoc} */
686                     public double[][] value(final double[] x) {
687 
688                         final int n = x.length;
689 
690                         // delegate computation to underlying function
691                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
692                         for (int i = 0; i < n; ++i) {
693                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
694                         }
695                         final DerivativeStructure[] y = f.value(dsX);
696 
697                         // extract Jacobian
698                         final double[][] jacobian = new double[y.length][n];
699                         final int[] orders = new int[n];
700                         for (int i = 0; i < y.length; ++i) {
701                             for (int j = 0; j < n; ++j) {
702                                 orders[j]      = 1;
703                                 jacobian[i][j] = y[i].getPartialDerivative(orders);
704                                 orders[j]      = 0;
705                             }
706                         }
707 
708                         return jacobian;
709 
710                     }
711                 };
712             }
713 
714         };
715     }
716 
717     /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
718      * <p>
719      * Note that the converted function is able to handle {@link DerivativeStructure} elements
720      * that all have the same number of free parameters and order, and with order at most 1.
721      * If the function is called with inconsistent numbers of free parameters or higher order, a
722      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
723      * </p>
724      * @param f function to convert
725      * @return converted function
726      * @deprecated this conversion method is temporary in version 3.1, as the {@link
727      * DifferentiableMultivariateFunction} interface itself is deprecated
728      */
729     @Deprecated
730     public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
731         return new MultivariateDifferentiableVectorFunction() {
732 
733             /** {@inheritDoc} */
734             public double[] value(final double[] x) {
735                 return f.value(x);
736             }
737 
738             /** {@inheritDoc}
739              * @exception NumberIsTooLargeException if derivation order is higher than 1
740              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
741              */
742             public DerivativeStructure[] value(final DerivativeStructure[] t)
743                 throws DimensionMismatchException, NumberIsTooLargeException {
744 
745                 // check parameters and orders limits
746                 final int parameters = t[0].getFreeParameters();
747                 final int order      = t[0].getOrder();
748                 final int n          = t.length;
749                 if (order > 1) {
750                     throw new NumberIsTooLargeException(order, 1, true);
751                 }
752 
753                 // check all elements in the array are consistent
754                 for (int i = 0; i < n; ++i) {
755                     if (t[i].getFreeParameters() != parameters) {
756                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
757                     }
758 
759                     if (t[i].getOrder() != order) {
760                         throw new DimensionMismatchException(t[i].getOrder(), order);
761                     }
762                 }
763 
764                 // delegate computation to underlying function
765                 final double[] point = new double[n];
766                 for (int i = 0; i < n; ++i) {
767                     point[i] = t[i].getValue();
768                 }
769                 final double[] value      = f.value(point);
770                 final double[][] jacobian = f.jacobian().value(point);
771 
772                 // merge value and Jacobian into a DerivativeStructure array
773                 final DerivativeStructure[] merged = new DerivativeStructure[value.length];
774                 for (int k = 0; k < merged.length; ++k) {
775                     final double[] derivatives = new double[parameters + 1];
776                     derivatives[0] = value[k];
777                     final int[] orders = new int[parameters];
778                     for (int i = 0; i < parameters; ++i) {
779                         orders[i] = 1;
780                         for (int j = 0; j < n; ++j) {
781                             derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
782                         }
783                         orders[i] = 0;
784                     }
785                     merged[k] = new DerivativeStructure(parameters, order, derivatives);
786                 }
787 
788                 return merged;
789 
790             }
791 
792         };
793     }
794 
795 }