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