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 }