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       * <p>
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))).</p>
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       * <p>
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))).</p>
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       * <p>
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))).</p>
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
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      * <p>
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}.</p>
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     /**
446      * Convert a {@link UnivariateDifferentiableFunction} into a {@link DifferentiableUnivariateFunction}.
447      *
448      * @param f function to convert
449      * @return converted function
450      * @deprecated this conversion method is temporary in version 3.1, as the {@link
451      * DifferentiableUnivariateFunction} interface itself is deprecated
452      */
453     @Deprecated
454     public static DifferentiableUnivariateFunction toDifferentiableUnivariateFunction(final UnivariateDifferentiableFunction f) {
455         return new DifferentiableUnivariateFunction() {
456 
457             /** {@inheritDoc} */
458             public double value(final double x) {
459                 return f.value(x);
460             }
461 
462             /** {@inheritDoc} */
463             public UnivariateFunction derivative() {
464                 return new UnivariateFunction() {
465                     /** {@inheritDoc} */
466                     public double value(final double x) {
467                         return f.value(new DerivativeStructure(1, 1, 0, x)).getPartialDerivative(1);
468                     }
469                 };
470             }
471 
472         };
473     }
474 
475     /**
476      * Convert a {@link DifferentiableUnivariateFunction} into a {@link UnivariateDifferentiableFunction}.
477      * <p>
478      * Note that the converted function is able to handle {@link DerivativeStructure} up to order one.
479      * If the function is called with higher order, a {@link NumberIsTooLargeException} is thrown.
480      * </p>
481      * @param f function to convert
482      * @return converted function
483      * @deprecated this conversion method is temporary in version 3.1, as the {@link
484      * DifferentiableUnivariateFunction} interface itself is deprecated
485      */
486     @Deprecated
487     public static UnivariateDifferentiableFunction toUnivariateDifferential(final DifferentiableUnivariateFunction f) {
488         return new UnivariateDifferentiableFunction() {
489 
490             /** {@inheritDoc} */
491             public double value(final double x) {
492                 return f.value(x);
493             }
494 
495             /** {@inheritDoc}
496              * @exception NumberIsTooLargeException if derivation order is greater than 1
497              */
498             public DerivativeStructure value(final DerivativeStructure t)
499                 throws NumberIsTooLargeException {
500                 switch (t.getOrder()) {
501                     case 0 :
502                         return new DerivativeStructure(t.getFreeParameters(), 0, f.value(t.getValue()));
503                     case 1 : {
504                         final int parameters = t.getFreeParameters();
505                         final double[] derivatives = new double[parameters + 1];
506                         derivatives[0] = f.value(t.getValue());
507                         final double fPrime = f.derivative().value(t.getValue());
508                         int[] orders = new int[parameters];
509                         for (int i = 0; i < parameters; ++i) {
510                             orders[i] = 1;
511                             derivatives[i + 1] = fPrime * t.getPartialDerivative(orders);
512                             orders[i] = 0;
513                         }
514                         return new DerivativeStructure(parameters, 1, derivatives);
515                     }
516                     default :
517                         throw new NumberIsTooLargeException(t.getOrder(), 1, true);
518                 }
519             }
520 
521         };
522     }
523 
524     /**
525      * Convert a {@link MultivariateDifferentiableFunction} into a {@link DifferentiableMultivariateFunction}.
526      *
527      * @param f function to convert
528      * @return converted function
529      * @deprecated this conversion method is temporary in version 3.1, as the {@link
530      * DifferentiableMultivariateFunction} interface itself is deprecated
531      */
532     @Deprecated
533     public static DifferentiableMultivariateFunction toDifferentiableMultivariateFunction(final MultivariateDifferentiableFunction f) {
534         return new DifferentiableMultivariateFunction() {
535 
536             /** {@inheritDoc} */
537             public double value(final double[] x) {
538                 return f.value(x);
539             }
540 
541             /** {@inheritDoc} */
542             public MultivariateFunction partialDerivative(final int k) {
543                 return new MultivariateFunction() {
544                     /** {@inheritDoc} */
545                     public double value(final double[] x) {
546 
547                         final int n = x.length;
548 
549                         // delegate computation to underlying function
550                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
551                         for (int i = 0; i < n; ++i) {
552                             if (i == k) {
553                                 dsX[i] = new DerivativeStructure(1, 1, 0, x[i]);
554                             } else {
555                                 dsX[i] = new DerivativeStructure(1, 1, x[i]);
556                             }
557                         }
558                         final DerivativeStructure y = f.value(dsX);
559 
560                         // extract partial derivative
561                         return y.getPartialDerivative(1);
562 
563                     }
564                 };
565             }
566 
567             /** {@inheritDoc} */
568             public MultivariateVectorFunction gradient() {
569                 return new MultivariateVectorFunction() {
570                     /** {@inheritDoc} */
571                     public double[] value(final double[] x) {
572 
573                         final int n = x.length;
574 
575                         // delegate computation to underlying function
576                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
577                         for (int i = 0; i < n; ++i) {
578                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
579                         }
580                         final DerivativeStructure y = f.value(dsX);
581 
582                         // extract gradient
583                         final double[] gradient = new double[n];
584                         final int[] orders = new int[n];
585                         for (int i = 0; i < n; ++i) {
586                             orders[i]   = 1;
587                             gradient[i] = y.getPartialDerivative(orders);
588                             orders[i]   = 0;
589                         }
590 
591                         return gradient;
592 
593                     }
594                 };
595             }
596 
597         };
598     }
599 
600     /**
601      * Convert a {@link DifferentiableMultivariateFunction} into a {@link MultivariateDifferentiableFunction}.
602      * <p>
603      * Note that the converted function is able to handle {@link DerivativeStructure} elements
604      * that all have the same number of free parameters and order, and with order at most 1.
605      * If the function is called with inconsistent numbers of free parameters or higher order, a
606      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
607      * </p>
608      * @param f function to convert
609      * @return converted function
610      * @deprecated this conversion method is temporary in version 3.1, as the {@link
611      * DifferentiableMultivariateFunction} interface itself is deprecated
612      */
613     @Deprecated
614     public static MultivariateDifferentiableFunction toMultivariateDifferentiableFunction(final DifferentiableMultivariateFunction f) {
615         return new MultivariateDifferentiableFunction() {
616 
617             /** {@inheritDoc} */
618             public double value(final double[] x) {
619                 return f.value(x);
620             }
621 
622             /** {@inheritDoc}
623              * @exception NumberIsTooLargeException if derivation order is higher than 1
624              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
625              */
626             public DerivativeStructure value(final DerivativeStructure[] t)
627                 throws DimensionMismatchException, NumberIsTooLargeException {
628 
629                 // check parameters and orders limits
630                 final int parameters = t[0].getFreeParameters();
631                 final int order      = t[0].getOrder();
632                 final int n          = t.length;
633                 if (order > 1) {
634                     throw new NumberIsTooLargeException(order, 1, true);
635                 }
636 
637                 // check all elements in the array are consistent
638                 for (int i = 0; i < n; ++i) {
639                     if (t[i].getFreeParameters() != parameters) {
640                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
641                     }
642 
643                     if (t[i].getOrder() != order) {
644                         throw new DimensionMismatchException(t[i].getOrder(), order);
645                     }
646                 }
647 
648                 // delegate computation to underlying function
649                 final double[] point = new double[n];
650                 for (int i = 0; i < n; ++i) {
651                     point[i] = t[i].getValue();
652                 }
653                 final double value      = f.value(point);
654                 final double[] gradient = f.gradient().value(point);
655 
656                 // merge value and gradient into one DerivativeStructure
657                 final double[] derivatives = new double[parameters + 1];
658                 derivatives[0] = value;
659                 final int[] orders = new int[parameters];
660                 for (int i = 0; i < parameters; ++i) {
661                     orders[i] = 1;
662                     for (int j = 0; j < n; ++j) {
663                         derivatives[i + 1] += gradient[j] * t[j].getPartialDerivative(orders);
664                     }
665                     orders[i] = 0;
666                 }
667 
668                 return new DerivativeStructure(parameters, order, derivatives);
669 
670             }
671 
672         };
673     }
674 
675     /**
676      * Convert a {@link MultivariateDifferentiableVectorFunction} into a {@link DifferentiableMultivariateVectorFunction}.
677      *
678      * @param f function to convert
679      * @return converted function
680      * @deprecated this conversion method is temporary in version 3.1, as the {@link
681      * DifferentiableMultivariateVectorFunction} interface itself is deprecated
682      */
683     @Deprecated
684     public static DifferentiableMultivariateVectorFunction toDifferentiableMultivariateVectorFunction(final MultivariateDifferentiableVectorFunction f) {
685         return new DifferentiableMultivariateVectorFunction() {
686 
687             /** {@inheritDoc} */
688             public double[] value(final double[] x) {
689                 return f.value(x);
690             }
691 
692             /** {@inheritDoc} */
693             public MultivariateMatrixFunction jacobian() {
694                 return new MultivariateMatrixFunction() {
695                     /** {@inheritDoc} */
696                     public double[][] value(final double[] x) {
697 
698                         final int n = x.length;
699 
700                         // delegate computation to underlying function
701                         final DerivativeStructure[] dsX = new DerivativeStructure[n];
702                         for (int i = 0; i < n; ++i) {
703                             dsX[i] = new DerivativeStructure(n, 1, i, x[i]);
704                         }
705                         final DerivativeStructure[] y = f.value(dsX);
706 
707                         // extract Jacobian
708                         final double[][] jacobian = new double[y.length][n];
709                         final int[] orders = new int[n];
710                         for (int i = 0; i < y.length; ++i) {
711                             for (int j = 0; j < n; ++j) {
712                                 orders[j]      = 1;
713                                 jacobian[i][j] = y[i].getPartialDerivative(orders);
714                                 orders[j]      = 0;
715                             }
716                         }
717 
718                         return jacobian;
719 
720                     }
721                 };
722             }
723 
724         };
725     }
726 
727     /**
728      * Convert a {@link DifferentiableMultivariateVectorFunction} into a {@link MultivariateDifferentiableVectorFunction}.
729      * <p>
730      * Note that the converted function is able to handle {@link DerivativeStructure} elements
731      * that all have the same number of free parameters and order, and with order at most 1.
732      * If the function is called with inconsistent numbers of free parameters or higher order, a
733      * {@link DimensionMismatchException} or a {@link NumberIsTooLargeException} will be thrown.
734      * </p>
735      * @param f function to convert
736      * @return converted function
737      * @deprecated this conversion method is temporary in version 3.1, as the {@link
738      * DifferentiableMultivariateFunction} interface itself is deprecated
739      */
740     @Deprecated
741     public static MultivariateDifferentiableVectorFunction toMultivariateDifferentiableVectorFunction(final DifferentiableMultivariateVectorFunction f) {
742         return new MultivariateDifferentiableVectorFunction() {
743 
744             /** {@inheritDoc} */
745             public double[] value(final double[] x) {
746                 return f.value(x);
747             }
748 
749             /** {@inheritDoc}
750              * @exception NumberIsTooLargeException if derivation order is higher than 1
751              * @exception DimensionMismatchException if numbers of free parameters are inconsistent
752              */
753             public DerivativeStructure[] value(final DerivativeStructure[] t)
754                 throws DimensionMismatchException, NumberIsTooLargeException {
755 
756                 // check parameters and orders limits
757                 final int parameters = t[0].getFreeParameters();
758                 final int order      = t[0].getOrder();
759                 final int n          = t.length;
760                 if (order > 1) {
761                     throw new NumberIsTooLargeException(order, 1, true);
762                 }
763 
764                 // check all elements in the array are consistent
765                 for (int i = 0; i < n; ++i) {
766                     if (t[i].getFreeParameters() != parameters) {
767                         throw new DimensionMismatchException(t[i].getFreeParameters(), parameters);
768                     }
769 
770                     if (t[i].getOrder() != order) {
771                         throw new DimensionMismatchException(t[i].getOrder(), order);
772                     }
773                 }
774 
775                 // delegate computation to underlying function
776                 final double[] point = new double[n];
777                 for (int i = 0; i < n; ++i) {
778                     point[i] = t[i].getValue();
779                 }
780                 final double[] value      = f.value(point);
781                 final double[][] jacobian = f.jacobian().value(point);
782 
783                 // merge value and Jacobian into a DerivativeStructure array
784                 final DerivativeStructure[] merged = new DerivativeStructure[value.length];
785                 for (int k = 0; k < merged.length; ++k) {
786                     final double[] derivatives = new double[parameters + 1];
787                     derivatives[0] = value[k];
788                     final int[] orders = new int[parameters];
789                     for (int i = 0; i < parameters; ++i) {
790                         orders[i] = 1;
791                         for (int j = 0; j < n; ++j) {
792                             derivatives[i + 1] += jacobian[k][j] * t[j].getPartialDerivative(orders);
793                         }
794                         orders[i] = 0;
795                     }
796                     merged[k] = new DerivativeStructure(parameters, order, derivatives);
797                 }
798 
799                 return merged;
800 
801             }
802 
803         };
804     }
805 
806 }