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   * @version $Id: FunctionUtils.java 1455194 2013-03-11 15:45:54Z luc $
34   * @since 3.0
35   */
36  public class FunctionUtils {
37      /**
38       * Class only contains static methods.
39       */
40      private FunctionUtils() {}
41  
42      /**
43       * Composes functions.
44       * <br/>
45       * The functions in the argument list are composed sequentially, in the
46       * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
47       *
48       * @param f List of functions.
49       * @return the composite function.
50       */
51      public static UnivariateFunction compose(final UnivariateFunction ... f) {
52          return new UnivariateFunction() {
53              /** {@inheritDoc} */
54              public double value(double x) {
55                  double r = x;
56                  for (int i = f.length - 1; i >= 0; i--) {
57                      r = f[i].value(r);
58                  }
59                  return r;
60              }
61          };
62      }
63  
64      /**
65       * Composes functions.
66       * <br/>
67       * The functions in the argument list are composed sequentially, in the
68       * given order.  For example, compose(f1,f2,f3) acts like f1(f2(f3(x))).
69       *
70       * @param f List of functions.
71       * @return the composite function.
72       * @since 3.1
73       */
74      public static UnivariateDifferentiableFunction compose(final UnivariateDifferentiableFunction ... f) {
75          return new UnivariateDifferentiableFunction() {
76  
77              /** {@inheritDoc} */
78              public double value(final double t) {
79                  double r = t;
80                  for (int i = f.length - 1; i >= 0; i--) {
81                      r = f[i].value(r);
82                  }
83                  return r;
84              }
85  
86              /** {@inheritDoc} */
87              public DerivativeStructure value(final DerivativeStructure t) {
88                  DerivativeStructure r = t;
89                  for (int i = f.length - 1; i >= 0; i--) {
90                      r = f[i].value(r);
91                  }
92                  return r;
93              }
94  
95          };
96      }
97  
98      /**
99       * 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              * @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     public static DifferentiableUnivariateFunction multiply(final DifferentiableUnivariateFunction ... f) {
283         return new DifferentiableUnivariateFunction() {
284             /** {@inheritDoc} */
285             public double value(double x) {
286                 double r = f[0].value(x);
287                 for (int i = 1; i < f.length; i++) {
288                     r *= f[i].value(x);
289                 }
290                 return r;
291             }
292 
293             /** {@inheritDoc} */
294             public UnivariateFunction derivative() {
295                 return new UnivariateFunction() {
296                     /** {@inheritDoc} */
297                     public double value(double x) {
298                         double sum = 0;
299                         for (int i = 0; i < f.length; i++) {
300                             double prod = f[i].derivative().value(x);
301                             for (int j = 0; j < f.length; j++) {
302                                 if (i != j) {
303                                     prod *= f[j].value(x);
304                                 }
305                             }
306                             sum += prod;
307                         }
308                         return sum;
309                     }
310                 };
311             }
312         };
313     }
314 
315     /**
316      * Returns the univariate function <br/>
317      * {@code h(x) = combiner(f(x), g(x))}.
318      *
319      * @param combiner Combiner function.
320      * @param f Function.
321      * @param g Function.
322      * @return the composite function.
323      */
324     public static UnivariateFunction combine(final BivariateFunction combiner,
325                                              final UnivariateFunction f,
326                                              final UnivariateFunction g) {
327         return new UnivariateFunction() {
328             /** {@inheritDoc} */
329             public double value(double x) {
330                 return combiner.value(f.value(x), g.value(x));
331             }
332         };
333     }
334 
335     /**
336      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
337      * h(x[]) = combiner(...combiner(combiner(initialValue,f(x[0])),f(x[1]))...),f(x[x.length-1]))
338      * </code></pre>
339      *
340      * @param combiner Combiner function.
341      * @param f Function.
342      * @param initialValue Initial value.
343      * @return a collector function.
344      */
345     public static MultivariateFunction collector(final BivariateFunction combiner,
346                                                  final UnivariateFunction f,
347                                                  final double initialValue) {
348         return new MultivariateFunction() {
349             /** {@inheritDoc} */
350             public double value(double[] point) {
351                 double result = combiner.value(initialValue, f.value(point[0]));
352                 for (int i = 1; i < point.length; i++) {
353                     result = combiner.value(result, f.value(point[i]));
354                 }
355                 return result;
356             }
357         };
358     }
359 
360     /**
361      * Returns a MultivariateFunction h(x[]) defined by <pre> <code>
362      * h(x[]) = combiner(...combiner(combiner(initialValue,x[0]),x[1])...),x[x.length-1])
363      * </code></pre>
364      *
365      * @param combiner Combiner function.
366      * @param initialValue Initial value.
367      * @return a collector function.
368      */
369     public static MultivariateFunction collector(final BivariateFunction combiner,
370                                                  final double initialValue) {
371         return collector(combiner, new Identity(), initialValue);
372     }
373 
374     /**
375      * Creates a unary function by fixing the first argument of a binary function.
376      *
377      * @param f Binary function.
378      * @param fixed Value to which the first argument of {@code f} is set.
379      * @return the unary function h(x) = f(fixed, x)
380      */
381     public static UnivariateFunction fix1stArgument(final BivariateFunction f,
382                                                     final double fixed) {
383         return new UnivariateFunction() {
384             /** {@inheritDoc} */
385             public double value(double x) {
386                 return f.value(fixed, x);
387             }
388         };
389     }
390     /**
391      * Creates a unary function by fixing the second argument of a binary function.
392      *
393      * @param f Binary function.
394      * @param fixed Value to which the second argument of {@code f} is set.
395      * @return the unary function h(x) = f(x, fixed)
396      */
397     public static UnivariateFunction fix2ndArgument(final BivariateFunction f,
398                                                     final double fixed) {
399         return new UnivariateFunction() {
400             /** {@inheritDoc} */
401             public double value(double x) {
402                 return f.value(x, fixed);
403             }
404         };
405     }
406 
407     /**
408      * Samples the specified univariate real function on the specified interval.
409      * <br/>
410      * The interval is divided equally into {@code n} sections and sample points
411      * are taken from {@code min} to {@code max - (max - min) / n}; therefore
412      * {@code f} is not sampled at the upper bound {@code max}.
413      *
414      * @param f Function to be sampled
415      * @param min Lower bound of the interval (included).
416      * @param max Upper bound of the interval (excluded).
417      * @param n Number of sample points.
418      * @return the array of samples.
419      * @throws NumberIsTooLargeException if the lower bound {@code min} is
420      * greater than, or equal to the upper bound {@code max}.
421      * @throws NotStrictlyPositiveException if the number of sample points
422      * {@code n} is negative.
423      */
424     public static double[] sample(UnivariateFunction f, double min, double max, int n)
425        throws NumberIsTooLargeException, NotStrictlyPositiveException {
426 
427         if (n <= 0) {
428             throw new NotStrictlyPositiveException(
429                     LocalizedFormats.NOT_POSITIVE_NUMBER_OF_SAMPLES,
430                     Integer.valueOf(n));
431         }
432         if (min >= max) {
433             throw new NumberIsTooLargeException(min, max, false);
434         }
435 
436         final double[] s = new double[n];
437         final double h = (max - min) / n;
438         for (int i = 0; i < n; i++) {
439             s[i] = f.value(min + i * h);
440         }
441         return s;
442     }
443 
444     /** Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
445      * @param f function to convert
446      * @return converted function
447      * @deprecated this conversion method is temporary in version 3.1, as the {@link
448      * DifferentiableUnivariateFunction} interface itself is deprecated
449      */
450     @Deprecated
451     public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
452         return new DifferentiableUnivariateFunction() {
453 
454             /** {@inheritDoc} */
455             public double value(final double x) {
456                 return f.value(x);
457             }
458 
459             /** {@inheritDoc} */
460             public UnivariateFunction derivative() {
461                 return new UnivariateFunction() {
462                     /** {@inheritDoc} */
463                     public double value(final double x) {
464                         return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
465                     }
466                 };
467             }
468 
469         };
470     }
471 
472     /** Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
473      * <p>
474      * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
475      * If the function is called with higher order, a {@link NumberIsTooLargeException} will be thrown.
476      * </p>
477      * @param f function to convert
478      * @return converted function
479      * @deprecated this conversion method is temporary in version 3.1, as the {@link
480      * DifferentiableUnivariateFunction} interface itself is deprecated
481      */
482     @Deprecated
483     public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
484         return new UnivariateDifferentiableFunction() {
485 
486             /** {@inheritDoc} */
487             public double value(final double x) {
488                 return f.value(x);
489             }
490 
491             /** {@inheritDoc}
492              * @exception NumberIsTooLargeException if derivation order is greater than 1
493              */
494             public DerivativeStructure value(final DerivativeStructure t)
495                 throws NumberIsTooLargeException {
496                 switch (t.getOrder()) {
497                     case 0 :
498                         return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
499                     case 1 : {
500                         final int parameters = t.getFreeParameters();
501                         final double[] derivatives = new double[parameters + 1];
502                         derivatives[0] = f.value(t.getValue());
503                         final double fPrime = f.derivative().value(t.getValue());
504                         int[] orders = new int[parameters];
505                         for (int i = 0; i < parameters; ++i) {
506                             orders[i] = 1;
507                             derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
508                             orders[i] = 0;
509                         }
510                         return new DerivativeStructure(parameters, 1, derivatives);
511                     }
512                     default :
513                         throw new NumberIsTooLargeException(t.getOrder(), 1, true);
514                 }
515             }
516 
517         };
518     }
519 
520     /** Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
521      * @param f function to convert
522      * @return converted function
523      * @deprecated this conversion method is temporary in version 3.1, as the {@link
524      * DifferentiableMultivariateFunction} interface itself is deprecated
525      */
526     @Deprecated
527     public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
528         return new DifferentiableMultivariateFunction() {
529 
530             /** {@inheritDoc} */
531             public double value(final double[] x) {
532                 return f.value(x);
533             }
534 
535             /** {@inheritDoc} */
536             public MultivariateFunction partialDerivative(final int k) {
537                 return new MultivariateFunction() {
538                     /** {@inheritDoc} */
539                     public double value(final double[] x) {
540 
541                         final int n = x.length;
542 
543                         // delegate computation to underlying function
544                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
545                         for (int i = 0; i < n; ++i) {
546                             if (i == k) {
547                                 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
548                             } else {
549                                 dsX[i] = new DerivativeStructure(1, 1, x[i]);
550                             }
551                         }
552                         final DerivativeStructure y = f.value(dsX);
553 
554                         // extract partial derivative
555                         return y.getPartialDerivative(1);
556 
557                     }
558                 };
559             }
560 
561             public MultivariateVectorFunction gradient() {
562                 return new MultivariateVectorFunction() {
563                     /** {@inheritDoc} */
564                     public double[] value(final double[] x) {
565 
566                         final int n = x.length;
567 
568                         // delegate computation to underlying function
569                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
570                         for (int i = 0; i < n; ++i) {
571                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
572                         }
573                         final DerivativeStructure y = f.value(dsX);
574 
575                         // extract gradient
576                         final double[] gradient = new double[n];
577                         final int[] orders = new int[n];
578                         for (int i = 0; i < n; ++i) {
579                             orders[i]   = 1;
580                             gradient[i] = y.getPartialDerivative(orders);
581                             orders[i]   = 0;
582                         }
583 
584                         return gradient;
585 
586                     }
587                 };
588             }
589 
590         };
591     }
592 
593     /** Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
594      * <p>
595      * Note that the converted function is able to handle {@link DerivativeStructure} elements
596      * that all have the same number of free parameters and order, and with order at most 1.
597      * If the function is called with inconsistent numbers of free parameters or higher order, a
598      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
599      * </p>
600      * @param f function to convert
601      * @return converted function
602      * @deprecated this conversion method is temporary in version 3.1, as the {@link
603      * DifferentiableMultivariateFunction} interface itself is deprecated
604      */
605     @Deprecated
606     public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
607         return new MultivariateDifferentiableFunction() {
608 
609             /** {@inheritDoc} */
610             public double value(final double[] x) {
611                 return f.value(x);
612             }
613 
614             /** {@inheritDoc}
615              * @exception NumberIsTooLargeException if derivation order is higher than 1
616              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
617              */
618             public DerivativeStructure value(final DerivativeStructure[] t)
619                 throws DimensionMismatchException, NumberIsTooLargeException {
620 
621                 // check parameters and orders limits
622                 final int parameters = t[0].getFreeParameters();
623                 final int order      = t[0].getOrder();
624                 final int n          = t.length;
625                 if (order > 1) {
626                     throw new NumberIsTooLargeException(order, 1, true);
627                 }
628 
629                 // check all elements in the array are consistent
630                 for (int i = 0; i < n; ++i) {
631                     if (t[i].getFreeParameters() != parameters) {
632                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
633                     }
634 
635                     if (t[i].getOrder() != order) {
636                         throw new DimensionMismatchException(t[i].getOrder(), order);
637                     }
638                 }
639 
640                 // delegate computation to underlying function
641                 final double[] point = new double[n];
642                 for (int i = 0; i < n; ++i) {
643                     point[i] = t[i].getValue();
644                 }
645                 final double value      = f.value(point);
646                 final double[] gradient = f.gradient().value(point);
647 
648                 // merge value and gradient into one DerivativeStructure
649                 final double[] derivatives = new double[parameters + 1];
650                 derivatives[0] = value;
651                 final int[] orders = new int[parameters];
652                 for (int i = 0; i < parameters; ++i) {
653                     orders[i] = 1;
654                     for (int j = 0; j < n; ++j) {
655                         derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
656                     }
657                     orders[i] = 0;
658                 }
659 
660                 return new DerivativeStructure(parameters, order, derivatives);
661 
662             }
663 
664         };
665     }
666 
667     /** Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
668      * @param f function to convert
669      * @return converted function
670      * @deprecated this conversion method is temporary in version 3.1, as the {@link
671      * DifferentiableMultivariateVectorFunction} interface itself is deprecated
672      */
673     @Deprecated
674     public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
675         return new DifferentiableMultivariateVectorFunction() {
676 
677             /** {@inheritDoc} */
678             public double[] value(final double[] x) {
679                 return f.value(x);
680             }
681 
682             public MultivariateMatrixFunction jacobian() {
683                 return new MultivariateMatrixFunction() {
684                     /** {@inheritDoc} */
685                     public double[][] value(final double[] x) {
686 
687                         final int n = x.length;
688 
689                         // delegate computation to underlying function
690                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
691                         for (int i = 0; i < n; ++i) {
692                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
693                         }
694                         final DerivativeStructure[] y = f.value(dsX);
695 
696                         // extract Jacobian
697                         final double[][] jacobian = new double[y.length][n];
698                         final int[] orders = new int[n];
699                         for (int i = 0; i < y.length; ++i) {
700                             for (int j = 0; j < n; ++j) {
701                                 orders[j]      = 1;
702                                 jacobian[i][j] = y[i].getPartialDerivative(orders);
703                                 orders[j]      = 0;
704                             }
705                         }
706 
707                         return jacobian;
708 
709                     }
710                 };
711             }
712 
713         };
714     }
715 
716     /** Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
717      * <p>
718      * Note that the converted function is able to handle {@link DerivativeStructure} elements
719      * that all have the same number of free parameters and order, and with order at most 1.
720      * If the function is called with inconsistent numbers of free parameters or higher order, a
721      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
722      * </p>
723      * @param f function to convert
724      * @return converted function
725      * @deprecated this conversion method is temporary in version 3.1, as the {@link
726      * DifferentiableMultivariateFunction} interface itself is deprecated
727      */
728     @Deprecated
729     public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
730         return new MultivariateDifferentiableVectorFunction() {
731 
732             /** {@inheritDoc} */
733             public double[] value(final double[] x) {
734                 return f.value(x);
735             }
736 
737             /** {@inheritDoc}
738              * @exception NumberIsTooLargeException if derivation order is higher than 1
739              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
740              */
741             public DerivativeStructure[] value(final DerivativeStructure[] t)
742                 throws DimensionMismatchException, NumberIsTooLargeException {
743 
744                 // check parameters and orders limits
745                 final int parameters = t[0].getFreeParameters();
746                 final int order      = t[0].getOrder();
747                 final int n          = t.length;
748                 if (order > 1) {
749                     throw new NumberIsTooLargeException(order, 1, true);
750                 }
751 
752                 // check all elements in the array are consistent
753                 for (int i = 0; i < n; ++i) {
754                     if (t[i].getFreeParameters() != parameters) {
755                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
756                     }
757 
758                     if (t[i].getOrder() != order) {
759                         throw new DimensionMismatchException(t[i].getOrder(), order);
760                     }
761                 }
762 
763                 // delegate computation to underlying function
764                 final double[] point = new double[n];
765                 for (int i = 0; i < n; ++i) {
766                     point[i] = t[i].getValue();
767                 }
768                 final double[] value      = f.value(point);
769                 final double[][] jacobian = f.jacobian().value(point);
770 
771                 // merge value and Jacobian into a DerivativeStructure array
772                 final DerivativeStructure[] merged = new DerivativeStructure[value.length];
773                 for (int k = 0; k < merged.length; ++k) {
774                     final double[] derivatives = new double[parameters + 1];
775                     derivatives[0] = value[k];
776                     final int[] orders = new int[parameters];
777                     for (int i = 0; i < parameters; ++i) {
778                         orders[i] = 1;
779                         for (int j = 0; j < n; ++j) {
780                             derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
781                         }
782                         orders[i] = 0;
783                     }
784                     merged[k] = new DerivativeStructure(parameters, order, derivatives);
785                 }
786 
787                 return merged;
788 
789             }
790 
791         };
792     }
793 
794 }