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